devpath4.c revision 1.1 1 1.1 christos /* $NetBSD: devpath4.c,v 1.1 2025/02/24 13:47:56 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Redistribution and use in source and binary forms, with or without
5 1.1 christos * modification, are permitted provided that the following conditions
6 1.1 christos * are met:
7 1.1 christos * 1. Redistributions of source code must retain the above copyright
8 1.1 christos * notice, this list of conditions and the following disclaimer.
9 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
10 1.1 christos * notice, this list of conditions and the following disclaimer in the
11 1.1 christos * documentation and/or other materials provided with the distribution.
12 1.1 christos *
13 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
14 1.1 christos * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 1.1 christos * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 1.1 christos * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 1.1 christos * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 1.1 christos * SUCH DAMAGE.
24 1.1 christos */
25 1.1 christos
26 1.1 christos #include <sys/cdefs.h>
27 1.1 christos #ifndef lint
28 1.1 christos __RCSID("$NetBSD: devpath4.c,v 1.1 2025/02/24 13:47:56 christos Exp $");
29 1.1 christos #endif /* not lint */
30 1.1 christos
31 1.1 christos #include <sys/uuid.h>
32 1.1 christos
33 1.1 christos #include <assert.h>
34 1.1 christos #include <stdio.h>
35 1.1 christos #include <stdlib.h>
36 1.1 christos #include <util.h>
37 1.1 christos
38 1.1 christos #include "defs.h"
39 1.1 christos #include "devpath.h"
40 1.1 christos #include "devpath4.h"
41 1.1 christos #include "utils.h"
42 1.1 christos
43 1.1 christos #define easprintf (size_t)easprintf
44 1.1 christos
45 1.1 christos #define EFI_VIRTUAL_DISK_GUID \
46 1.1 christos ((uuid_t){0x77AB535A,0x45FC,0x624B,0x55,0x60,\
47 1.1 christos {0xF7,0xB2,0x81,0xD1,0xF9,0x6E}})
48 1.1 christos
49 1.1 christos #define EFI_VIRTUAL_CD_GUID \
50 1.1 christos ((uuid_t){0x3D5ABD30,0x4175,0x87CE,0x6D,0x64,\
51 1.1 christos {0xD2,0xAD,0xE5,0x23,0xC4,0xBB}})
52 1.1 christos
53 1.1 christos #define EFI_PERSISTENT_VIRTUAL_DISK_GUID \
54 1.1 christos ((uuid_t){0x5CEA02C9,0x4D07,0x69D3,0x26,0x9F,\
55 1.1 christos {0x44,0x96,0xFB,0xE0,0x96,0xF9}})
56 1.1 christos
57 1.1 christos #define EFI_PERSISTENT_VIRTUAL_CD_GUID \
58 1.1 christos ((uuid_t){0x08018188,0x42CD,0xBB48,0x10,0x0F,\
59 1.1 christos {0x53,0x87,0xD5,0x3D,0xED,0x3D }})
60 1.1 christos
61 1.1 christos /************************************************************************
62 1.1 christos * Type 4 - Media Device Path
63 1.1 christos ************************************************************************/
64 1.1 christos
65 1.1 christos static void
66 1.1 christos devpath_media_harddisk(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
67 1.1 christos { /* See 10.3.5.1 */
68 1.1 christos struct { /* Sub-Type 1 */
69 1.1 christos devpath_t hdr; /* Length 42 */
70 1.1 christos uint32_t PartitionNumber;
71 1.1 christos uint64_t PartitionStart;
72 1.1 christos uint64_t PartitionSize;
73 1.1 christos uuid_t PartitionSignature;
74 1.1 christos uint8_t PartitionFormat;
75 1.1 christos #define PARTITION_FORMAT_MBR 0x01
76 1.1 christos #define PARTITION_FORMAT_GPT 0x02
77 1.1 christos uint8_t SignatureType;
78 1.1 christos #define SIGNATURE_TYPE_NONE 0x00
79 1.1 christos #define SIGNATURE_TYPE_MBR 0x01
80 1.1 christos #define SIGNATURE_TYPE_GUID 0x02
81 1.1 christos } __packed *p = (void *)dp;
82 1.1 christos __CTASSERT(sizeof(*p) == 42);
83 1.1 christos char uuid_str[UUID_STR_LEN];
84 1.1 christos const char *name_PartitionFormat;
85 1.1 christos
86 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str),
87 1.1 christos &p->PartitionSignature);
88 1.1 christos
89 1.1 christos switch (p->PartitionFormat) {
90 1.1 christos case PARTITION_FORMAT_MBR: name_PartitionFormat = "MBR"; break;
91 1.1 christos case PARTITION_FORMAT_GPT: name_PartitionFormat = "GPT"; break;
92 1.1 christos default: name_PartitionFormat = "unknown"; break;
93 1.1 christos }
94 1.1 christos
95 1.1 christos path->sz = easprintf(&path->cp, "HD(%u,%s,%s,0x%lx,0x%lx)",
96 1.1 christos p->PartitionNumber,
97 1.1 christos name_PartitionFormat,
98 1.1 christos uuid_str,
99 1.1 christos p->PartitionStart,
100 1.1 christos p->PartitionSize);
101 1.1 christos
102 1.1 christos if (dbg != NULL) {
103 1.1 christos const char *name_SignatureType;
104 1.1 christos
105 1.1 christos switch (p->SignatureType) {
106 1.1 christos case SIGNATURE_TYPE_NONE: name_SignatureType = "NONE"; break;
107 1.1 christos case SIGNATURE_TYPE_MBR: name_SignatureType = "MBR"; break;
108 1.1 christos case SIGNATURE_TYPE_GUID: name_SignatureType = "GUID"; break;
109 1.1 christos default: name_SignatureType = "unknown"; break;
110 1.1 christos }
111 1.1 christos
112 1.1 christos dbg->sz = easprintf(&dbg->cp,
113 1.1 christos DEVPATH_FMT_HDR
114 1.1 christos DEVPATH_FMT(PartitionNumber: %u\n)
115 1.1 christos DEVPATH_FMT(PartitionStart: 0x%lx\n)
116 1.1 christos DEVPATH_FMT(PartitionSize: 0x%lx\n)
117 1.1 christos DEVPATH_FMT(PartitionSignature: %s\n)
118 1.1 christos DEVPATH_FMT(PartitionFormat: %s(%u)\n)
119 1.1 christos DEVPATH_FMT(SignatureType: %s(%u)\n),
120 1.1 christos DEVPATH_DAT_HDR(dp),
121 1.1 christos p->PartitionNumber,
122 1.1 christos p->PartitionStart,
123 1.1 christos p->PartitionSize,
124 1.1 christos uuid_str,
125 1.1 christos name_PartitionFormat,
126 1.1 christos p->PartitionFormat,
127 1.1 christos name_SignatureType,
128 1.1 christos p->SignatureType);
129 1.1 christos }
130 1.1 christos }
131 1.1 christos
132 1.1 christos static void
133 1.1 christos devpath_media_cdrom(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
134 1.1 christos { /* See 10.3.5.2 */
135 1.1 christos struct { /* Sub-Type 2 */
136 1.1 christos devpath_t hdr; /* Length 24 */
137 1.1 christos uint32_t BootEntry;
138 1.1 christos uint64_t PartitionStart;
139 1.1 christos uint64_t PartitionSize;
140 1.1 christos } __packed *p = (void *)dp;
141 1.1 christos __CTASSERT(sizeof(*p) == 24);
142 1.1 christos
143 1.1 christos path->sz = easprintf(&path->cp, "CDROM(0x%x,0x%016tx,0x%016tx)", p->BootEntry,
144 1.1 christos p->PartitionStart, p->PartitionSize);
145 1.1 christos
146 1.1 christos if (dbg != NULL) {
147 1.1 christos dbg->sz = easprintf(&dbg->cp,
148 1.1 christos DEVPATH_FMT_HDR
149 1.1 christos DEVPATH_FMT(BootEntry: 0x%04x\n)
150 1.1 christos DEVPATH_FMT(PartitionStart: 0x%016tx\n)
151 1.1 christos DEVPATH_FMT(PartitionSize: 0x%016tx\n),
152 1.1 christos DEVPATH_DAT_HDR(dp),
153 1.1 christos p->BootEntry,
154 1.1 christos p->PartitionStart,
155 1.1 christos p->PartitionSize);
156 1.1 christos }
157 1.1 christos }
158 1.1 christos
159 1.1 christos static void
160 1.1 christos devpath_media_vendor(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
161 1.1 christos { /* See 10.3.5.3 */
162 1.1 christos
163 1.1 christos struct { /* Sub-Type 3 */
164 1.1 christos devpath_t hdr; /* Length = 20 + n */
165 1.1 christos uuid_t VendorGUID;
166 1.1 christos uint8_t vendorData[];
167 1.1 christos } __packed *p = (void *)dp;
168 1.1 christos __CTASSERT(sizeof(*p) == 20);
169 1.1 christos char uuid_str[UUID_STR_LEN];
170 1.1 christos
171 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->VendorGUID);
172 1.1 christos
173 1.1 christos path->sz = easprintf(&path->cp, "VenMedia(%s)", uuid_str);
174 1.1 christos
175 1.1 christos if (dbg != NULL) {
176 1.1 christos dbg->sz = easprintf(&dbg->cp,
177 1.1 christos DEVPATH_FMT_HDR
178 1.1 christos DEVPATH_FMT(VendorGUID: %s\n),
179 1.1 christos DEVPATH_DAT_HDR(dp),
180 1.1 christos uuid_str);
181 1.1 christos }
182 1.1 christos }
183 1.1 christos
184 1.1 christos static void
185 1.1 christos devpath_media_filepath(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
186 1.1 christos { /* See 10.3.5.4 */
187 1.1 christos struct { /* Sub-Type 4 */
188 1.1 christos devpath_t hdr; /* Length = 4 + n */
189 1.1 christos uint16_t PathName[];
190 1.1 christos } __packed *p = (void *)dp;
191 1.1 christos __CTASSERT(sizeof(*p) == 4);
192 1.1 christos char *PathName;
193 1.1 christos size_t sz = p->hdr.Length - sizeof(*p);
194 1.1 christos
195 1.1 christos PathName = ucs2_to_utf8(p->PathName, sz, NULL, NULL);
196 1.1 christos path->sz = easprintf(&path->cp, "File(%s)", PathName);
197 1.1 christos
198 1.1 christos if (dbg != NULL) {
199 1.1 christos dbg->sz = easprintf(&dbg->cp,
200 1.1 christos DEVPATH_FMT_HDR
201 1.1 christos DEVPATH_FMT(PathName: %s\n),
202 1.1 christos DEVPATH_DAT_HDR(dp),
203 1.1 christos PathName);
204 1.1 christos }
205 1.1 christos free(PathName);
206 1.1 christos }
207 1.1 christos
208 1.1 christos static void
209 1.1 christos devpath_media_protocol(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
210 1.1 christos { /* See 10.3.5.5 */
211 1.1 christos struct { /* Sub-Type 5 */
212 1.1 christos devpath_t hdr; /* Length 20 */
213 1.1 christos uuid_t ProtocolGUID;
214 1.1 christos } __packed *p = (void *)dp;
215 1.1 christos __CTASSERT(sizeof(*p) == 20);
216 1.1 christos char uuid_str[UUID_STR_LEN];
217 1.1 christos
218 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->ProtocolGUID);
219 1.1 christos path->sz = easprintf(&path->cp, "Media(%s)", uuid_str);
220 1.1 christos
221 1.1 christos if (dbg != NULL) {
222 1.1 christos dbg->sz = easprintf(&dbg->cp,
223 1.1 christos DEVPATH_FMT_HDR
224 1.1 christos DEVPATH_FMT(ProtocolGUID: %s\n),
225 1.1 christos DEVPATH_DAT_HDR(dp),
226 1.1 christos uuid_str);
227 1.1 christos }
228 1.1 christos }
229 1.1 christos
230 1.1 christos static void
231 1.1 christos devpath_media_PIWGfwfile(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
232 1.1 christos { /* See 10.3.5.6 */
233 1.1 christos /* See UEFI PI Version 1.8 Errata A (March 5, 2024) II-8.3 */
234 1.1 christos struct { /* Sub-Type 6 */
235 1.1 christos devpath_t hdr; /* Length 20 */
236 1.1 christos uuid_t FWFileName;
237 1.1 christos } __packed *p = (void *)dp;
238 1.1 christos __CTASSERT(sizeof(*p) == 20);
239 1.1 christos char uuid_str[UUID_STR_LEN];
240 1.1 christos
241 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->FWFileName);
242 1.1 christos path->sz = easprintf(&path->cp, "FvFile(%s)", uuid_str);
243 1.1 christos
244 1.1 christos if (dbg != NULL) {
245 1.1 christos dbg->sz = easprintf(&dbg->cp,
246 1.1 christos DEVPATH_FMT_HDR
247 1.1 christos DEVPATH_FMT(FirmwareFileName: %s\n),
248 1.1 christos DEVPATH_DAT_HDR(dp),
249 1.1 christos uuid_str);
250 1.1 christos }
251 1.1 christos }
252 1.1 christos
253 1.1 christos static void
254 1.1 christos devpath_media_PIWGfwvol(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
255 1.1 christos { /* See 10.3.5.7 */
256 1.1 christos /* See UEFI PI Version 1.8 Errata A (March 5, 2024) II-8.2 */
257 1.1 christos struct { /* Sub-Type 7 */
258 1.1 christos devpath_t hdr; /* Length 20 */
259 1.1 christos uuid_t GUID;
260 1.1 christos } __packed *p = (void *)dp;
261 1.1 christos __CTASSERT(sizeof(*p) == 20);
262 1.1 christos char uuid_str[UUID_STR_LEN];
263 1.1 christos
264 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->GUID);
265 1.1 christos path->sz = easprintf(&path->cp, "Fv(%s)", uuid_str);
266 1.1 christos
267 1.1 christos if (dbg != NULL) {
268 1.1 christos dbg->sz = easprintf(&dbg->cp,
269 1.1 christos DEVPATH_FMT_HDR
270 1.1 christos DEVPATH_FMT(GUID: %s\n),
271 1.1 christos DEVPATH_DAT_HDR(dp),
272 1.1 christos uuid_str);
273 1.1 christos }
274 1.1 christos }
275 1.1 christos
276 1.1 christos static void
277 1.1 christos devpath_media_reloff(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
278 1.1 christos { /* See 10.3.5.8 */
279 1.1 christos struct { /* Sub-Type 8 */
280 1.1 christos devpath_t hdr; /* Length 24 */
281 1.1 christos uint32_t Reserved;
282 1.1 christos uint64_t StartingOffset;
283 1.1 christos uint64_t EndingOffset;
284 1.1 christos } __packed *p = (void *)dp;
285 1.1 christos __CTASSERT(sizeof(*p) == 24);
286 1.1 christos
287 1.1 christos path->sz = easprintf(&path->cp, "Offset(0x%016tx,0x%016tx)",
288 1.1 christos p->StartingOffset, p->EndingOffset);
289 1.1 christos
290 1.1 christos if (dbg != NULL) {
291 1.1 christos dbg->sz = easprintf(&dbg->cp,
292 1.1 christos DEVPATH_FMT_HDR
293 1.1 christos DEVPATH_FMT(Reserved: 0x%08x\n)
294 1.1 christos DEVPATH_FMT(StartingOffset: 0x%016tx\n)
295 1.1 christos DEVPATH_FMT(EndingOffset: 0x%016tx\n),
296 1.1 christos DEVPATH_DAT_HDR(dp),
297 1.1 christos p->Reserved,
298 1.1 christos p->StartingOffset,
299 1.1 christos p->EndingOffset);
300 1.1 christos }
301 1.1 christos }
302 1.1 christos
303 1.1 christos static const char *
304 1.1 christos devpath_media_ramdisk_type(uuid_t *uuid)
305 1.1 christos {
306 1.1 christos static struct {
307 1.1 christos uuid_t GUID;
308 1.1 christos const char *type;
309 1.1 christos } tbl[] = {
310 1.1 christos { .GUID = EFI_VIRTUAL_DISK_GUID,
311 1.1 christos .type = "VirtualDisk",
312 1.1 christos },
313 1.1 christos { .GUID = EFI_VIRTUAL_CD_GUID,
314 1.1 christos .type = "VirtualCD",
315 1.1 christos },
316 1.1 christos { .GUID = EFI_PERSISTENT_VIRTUAL_DISK_GUID,
317 1.1 christos .type = "PersistentVirtualDisk",
318 1.1 christos },
319 1.1 christos { .GUID =EFI_PERSISTENT_VIRTUAL_CD_GUID,
320 1.1 christos .type = "PersistentVirtualCD",
321 1.1 christos },
322 1.1 christos };
323 1.1 christos
324 1.1 christos for (size_t i = 0; i < __arraycount(tbl); i++) {
325 1.1 christos if (memcmp(uuid, &tbl[i].GUID, sizeof(*uuid)) == 0) {
326 1.1 christos return tbl[i].type;
327 1.1 christos }
328 1.1 christos }
329 1.1 christos return NULL;
330 1.1 christos }
331 1.1 christos
332 1.1 christos static void
333 1.1 christos devpath_media_ramdisk(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
334 1.1 christos { /* See 10.3.5.9 */
335 1.1 christos struct { /* Sub-Type 9 */
336 1.1 christos devpath_t hdr; /* Length 38 */
337 1.1 christos uint64_t StartingAddress;
338 1.1 christos uint64_t EndingAddress;
339 1.1 christos uuid_t GUID;
340 1.1 christos uint16_t Instance;
341 1.1 christos } __packed *p = (void *)dp;
342 1.1 christos __CTASSERT(sizeof(*p) == 38);
343 1.1 christos char uuid_str[UUID_STR_LEN];
344 1.1 christos const char *type;
345 1.1 christos
346 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->GUID);
347 1.1 christos
348 1.1 christos type = devpath_media_ramdisk_type(&p->GUID);
349 1.1 christos if (type != NULL)
350 1.1 christos path->sz = easprintf(&path->cp, "%s(0x%016tx,0x%016tx,%u)",
351 1.1 christos type,
352 1.1 christos p->StartingAddress, p->EndingAddress, p->Instance);
353 1.1 christos else
354 1.1 christos path->sz = easprintf(&path->cp, "RamDisk(0x%016tx,0x%016tx,%u,%s)",
355 1.1 christos p->StartingAddress, p->EndingAddress, p->Instance,
356 1.1 christos uuid_str);
357 1.1 christos
358 1.1 christos if (dbg != NULL) {
359 1.1 christos dbg->sz = easprintf(&dbg->cp,
360 1.1 christos DEVPATH_FMT_HDR
361 1.1 christos DEVPATH_FMT(StartingAddress: 0x%016tx\n)
362 1.1 christos DEVPATH_FMT(EndingAddress: 0x%016tx\n)
363 1.1 christos DEVPATH_FMT(Instance: 0x%08x\n)
364 1.1 christos DEVPATH_FMT(GUID: %s\n),
365 1.1 christos DEVPATH_DAT_HDR(dp),
366 1.1 christos p->StartingAddress,
367 1.1 christos p->EndingAddress,
368 1.1 christos p->Instance,
369 1.1 christos uuid_str);
370 1.1 christos }
371 1.1 christos }
372 1.1 christos
373 1.1 christos PUBLIC void
374 1.1 christos devpath_media(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
375 1.1 christos {
376 1.1 christos
377 1.1 christos switch (dp->SubType) {
378 1.1 christos case 1: devpath_media_harddisk(dp, path, dbg); return;
379 1.1 christos case 2: devpath_media_cdrom(dp, path, dbg); return;
380 1.1 christos case 3: devpath_media_vendor(dp, path, dbg); return;
381 1.1 christos case 4: devpath_media_filepath(dp, path, dbg); return;
382 1.1 christos case 5: devpath_media_protocol(dp, path, dbg); return;
383 1.1 christos case 6: devpath_media_PIWGfwfile(dp, path, dbg); return;
384 1.1 christos case 7: devpath_media_PIWGfwvol(dp, path, dbg); return;
385 1.1 christos case 8: devpath_media_reloff(dp, path, dbg); return;
386 1.1 christos case 9: devpath_media_ramdisk(dp, path, dbg); return;
387 1.1 christos default: devpath_unsupported(dp, path, dbg); return;
388 1.1 christos }
389 1.1 christos }
390