efifile.c revision 1.3.2.2 1 1.3.2.2 pgoyette /* $NetBSD: efifile.c,v 1.3.2.2 2018/09/06 06:56:47 pgoyette Exp $ */
2 1.3.2.2 pgoyette
3 1.3.2.2 pgoyette /*-
4 1.3.2.2 pgoyette * Copyright (c) 2018 Jared McNeill <jmcneill (at) invisible.ca>
5 1.3.2.2 pgoyette * All rights reserved.
6 1.3.2.2 pgoyette *
7 1.3.2.2 pgoyette * Redistribution and use in source and binary forms, with or without
8 1.3.2.2 pgoyette * modification, are permitted provided that the following conditions
9 1.3.2.2 pgoyette * are met:
10 1.3.2.2 pgoyette * 1. Redistributions of source code must retain the above copyright
11 1.3.2.2 pgoyette * notice, this list of conditions and the following disclaimer.
12 1.3.2.2 pgoyette * 2. Redistributions in binary form must reproduce the above copyright
13 1.3.2.2 pgoyette * notice, this list of conditions and the following disclaimer in the
14 1.3.2.2 pgoyette * documentation and/or other materials provided with the distribution.
15 1.3.2.2 pgoyette *
16 1.3.2.2 pgoyette * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 1.3.2.2 pgoyette * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1.3.2.2 pgoyette * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1.3.2.2 pgoyette * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 1.3.2.2 pgoyette * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.3.2.2 pgoyette * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 1.3.2.2 pgoyette * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.3.2.2 pgoyette * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 1.3.2.2 pgoyette * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.3.2.2 pgoyette * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.3.2.2 pgoyette * SUCH DAMAGE.
27 1.3.2.2 pgoyette */
28 1.3.2.2 pgoyette
29 1.3.2.2 pgoyette #include <sys/param.h>
30 1.3.2.2 pgoyette
31 1.3.2.2 pgoyette #include "efiboot.h"
32 1.3.2.2 pgoyette #include "efifile.h"
33 1.3.2.2 pgoyette
34 1.3.2.2 pgoyette static EFI_HANDLE *efi_vol;
35 1.3.2.2 pgoyette static UINTN efi_nvol;
36 1.3.2.2 pgoyette
37 1.3.2.2 pgoyette static int
38 1.3.2.2 pgoyette efi_file_parse(const char *fname, UINTN *pvol, const char **pfile)
39 1.3.2.2 pgoyette {
40 1.3.2.2 pgoyette intmax_t vol;
41 1.3.2.2 pgoyette char *ep = NULL;
42 1.3.2.2 pgoyette
43 1.3.2.2 pgoyette if (strchr(fname, ':') != NULL) {
44 1.3.2.2 pgoyette if (strncasecmp(fname, "fs", 2) != 0)
45 1.3.2.2 pgoyette return EINVAL;
46 1.3.2.2 pgoyette vol = strtoimax(fname + 2, &ep, 10);
47 1.3.2.2 pgoyette if (vol < 0 || vol >= efi_nvol || *ep != ':')
48 1.3.2.2 pgoyette return ENXIO;
49 1.3.2.2 pgoyette *pvol = vol;
50 1.3.2.2 pgoyette *pfile = ep + 1;
51 1.3.2.2 pgoyette return 0;
52 1.3.2.2 pgoyette }
53 1.3.2.2 pgoyette
54 1.3.2.2 pgoyette return EINVAL;
55 1.3.2.2 pgoyette }
56 1.3.2.2 pgoyette
57 1.3.2.2 pgoyette void
58 1.3.2.2 pgoyette efi_file_system_probe(void)
59 1.3.2.2 pgoyette {
60 1.3.2.2 pgoyette EFI_STATUS status;
61 1.3.2.2 pgoyette
62 1.3.2.2 pgoyette status = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &efi_nvol, &efi_vol);
63 1.3.2.2 pgoyette if (EFI_ERROR(status))
64 1.3.2.2 pgoyette return;
65 1.3.2.2 pgoyette }
66 1.3.2.2 pgoyette
67 1.3.2.2 pgoyette int
68 1.3.2.2 pgoyette efi_file_open(struct open_file *f, ...)
69 1.3.2.2 pgoyette {
70 1.3.2.2 pgoyette EFI_DEVICE_PATH *dp;
71 1.3.2.2 pgoyette SIMPLE_READ_FILE srf;
72 1.3.2.2 pgoyette EFI_HANDLE device, file;
73 1.3.2.2 pgoyette EFI_STATUS status;
74 1.3.2.2 pgoyette UINTN vol;
75 1.3.2.2 pgoyette const char *fname, *path;
76 1.3.2.2 pgoyette CHAR16 *upath;
77 1.3.2.2 pgoyette va_list ap;
78 1.3.2.2 pgoyette size_t len;
79 1.3.2.2 pgoyette int rv, n;
80 1.3.2.2 pgoyette
81 1.3.2.2 pgoyette va_start(ap, f);
82 1.3.2.2 pgoyette fname = va_arg(ap, const char *);
83 1.3.2.2 pgoyette va_end(ap);
84 1.3.2.2 pgoyette
85 1.3.2.2 pgoyette rv = efi_file_parse(fname, &vol, &path);
86 1.3.2.2 pgoyette if (rv != 0)
87 1.3.2.2 pgoyette return rv;
88 1.3.2.2 pgoyette
89 1.3.2.2 pgoyette device = efi_vol[vol];
90 1.3.2.2 pgoyette
91 1.3.2.2 pgoyette upath = NULL;
92 1.3.2.2 pgoyette rv = utf8_to_ucs2(path, &upath, &len);
93 1.3.2.2 pgoyette if (rv != 0)
94 1.3.2.2 pgoyette return rv;
95 1.3.2.2 pgoyette
96 1.3.2.2 pgoyette dp = FileDevicePath(device, upath);
97 1.3.2.2 pgoyette FreePool(upath);
98 1.3.2.2 pgoyette if (dp == NULL)
99 1.3.2.2 pgoyette return EINVAL;
100 1.3.2.2 pgoyette
101 1.3.2.2 pgoyette status = OpenSimpleReadFile(TRUE, NULL, 0, &dp, &file, &srf);
102 1.3.2.2 pgoyette FreePool(dp);
103 1.3.2.2 pgoyette if (EFI_ERROR(status))
104 1.3.2.2 pgoyette return status == EFI_NOT_FOUND ? ENOENT : EIO;
105 1.3.2.2 pgoyette
106 1.3.2.2 pgoyette for (n = 0; n < ndevs; n++)
107 1.3.2.2 pgoyette if (strcmp(DEV_NAME(&devsw[n]), "efifile") == 0) {
108 1.3.2.2 pgoyette f->f_dev = &devsw[n];
109 1.3.2.2 pgoyette break;
110 1.3.2.2 pgoyette }
111 1.3.2.2 pgoyette if (n == ndevs)
112 1.3.2.2 pgoyette return ENXIO;
113 1.3.2.2 pgoyette f->f_devdata = f;
114 1.3.2.2 pgoyette f->f_fsdata = srf;
115 1.3.2.2 pgoyette f->f_flags = F_NODEV | F_READ;
116 1.3.2.2 pgoyette
117 1.3.2.2 pgoyette return 0;
118 1.3.2.2 pgoyette }
119 1.3.2.2 pgoyette
120 1.3.2.2 pgoyette int
121 1.3.2.2 pgoyette efi_file_close(struct open_file *f)
122 1.3.2.2 pgoyette {
123 1.3.2.2 pgoyette SIMPLE_READ_FILE srf = f->f_fsdata;
124 1.3.2.2 pgoyette
125 1.3.2.2 pgoyette CloseSimpleReadFile(srf);
126 1.3.2.2 pgoyette
127 1.3.2.2 pgoyette return 0;
128 1.3.2.2 pgoyette }
129 1.3.2.2 pgoyette
130 1.3.2.2 pgoyette int
131 1.3.2.2 pgoyette efi_file_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize)
132 1.3.2.2 pgoyette {
133 1.3.2.2 pgoyette struct open_file *f = devdata;
134 1.3.2.2 pgoyette SIMPLE_READ_FILE srf = f->f_fsdata;
135 1.3.2.2 pgoyette EFI_STATUS status;
136 1.3.2.2 pgoyette UINTN len;
137 1.3.2.2 pgoyette
138 1.3.2.2 pgoyette if (rw != F_READ)
139 1.3.2.2 pgoyette return EROFS;
140 1.3.2.2 pgoyette
141 1.3.2.2 pgoyette len = size;
142 1.3.2.2 pgoyette status = ReadSimpleReadFile(srf, f->f_offset, &len, buf);
143 1.3.2.2 pgoyette if (EFI_ERROR(status))
144 1.3.2.2 pgoyette return EIO;
145 1.3.2.2 pgoyette *rsize = len;
146 1.3.2.2 pgoyette
147 1.3.2.2 pgoyette return 0;
148 1.3.2.2 pgoyette }
149