1 /* $NetBSD: dpath.c,v 1.4 2021/09/30 19:02:48 jmcneill Exp $ */
2
3 /*++
4
5 Copyright (c) 1998 Intel Corporation
6
7 Module Name:
8
9 dpath.c
10
11 Abstract:
12 MBR & Device Path functions
13
14
15
16 Revision History
17
18 2014/04 B.Burette - updated device path text representation, conforming to
19 UEFI specification 2.4 (dec. 2013). More specifically:
20 - § 9.3.5: added some media types ie. Sata()
21 - § 9.6.1.2: Acpi(PNP0A03,0) makes more sense when displayed as PciRoot(0)
22 - § 9.6.1.5: use commas (instead of '|') between option specific parameters
23 - § 9.6.1.6: hex values in device paths must be preceded by "0x" or "0X"
24
25 --*/
26
27 #include "lib.h"
28
29 #define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
30
31
32
33 EFI_DEVICE_PATH *
DevicePathFromHandle(IN EFI_HANDLE Handle)34 DevicePathFromHandle (
35 IN EFI_HANDLE Handle
36 )
37 {
38 EFI_STATUS Status;
39 EFI_DEVICE_PATH *DevicePath;
40
41 Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DevicePathProtocol, (VOID*)&DevicePath);
42 if (EFI_ERROR(Status)) {
43 DevicePath = NULL;
44 }
45
46 return DevicePath;
47 }
48
49
50 EFI_DEVICE_PATH *
DevicePathInstance(IN OUT EFI_DEVICE_PATH ** DevicePath,OUT UINTN * Size)51 DevicePathInstance (
52 IN OUT EFI_DEVICE_PATH **DevicePath,
53 OUT UINTN *Size
54 )
55 {
56 EFI_DEVICE_PATH *Start, *Next, *DevPath;
57 UINTN Count;
58
59 DevPath = *DevicePath;
60 Start = DevPath;
61
62 if (!DevPath) {
63 return NULL;
64 }
65
66 //
67 // Check for end of device path type
68 //
69
70 for (Count = 0; ; Count++) {
71 Next = NextDevicePathNode(DevPath);
72
73 if (IsDevicePathEndType(DevPath)) {
74 break;
75 }
76
77 if (Count > 01000) {
78 //
79 // BugBug: Debug code to catch bogus device paths
80 //
81 DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) ));
82 DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
83 break;
84 }
85
86 DevPath = Next;
87 }
88
89 ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE ||
90 DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
91
92 //
93 // Set next position
94 //
95
96 if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
97 Next = NULL;
98 }
99
100 *DevicePath = Next;
101
102 //
103 // Return size and start of device path instance
104 //
105
106 *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start);
107 return Start;
108 }
109
110 UINTN
DevicePathInstanceCount(IN EFI_DEVICE_PATH * DevicePath)111 DevicePathInstanceCount (
112 IN EFI_DEVICE_PATH *DevicePath
113 )
114 {
115 UINTN Count, Size;
116
117 Count = 0;
118 while (DevicePathInstance(&DevicePath, &Size)) {
119 Count += 1;
120 }
121
122 return Count;
123 }
124
125
126 EFI_DEVICE_PATH *
AppendDevicePath(IN EFI_DEVICE_PATH * Src1,IN EFI_DEVICE_PATH * Src2)127 AppendDevicePath (
128 IN EFI_DEVICE_PATH *Src1,
129 IN EFI_DEVICE_PATH *Src2
130 )
131 // Src1 may have multiple "instances" and each instance is appended
132 // Src2 is appended to each instance is Src1. (E.g., it's possible
133 // to append a new instance to the complete device path by passing
134 // it in Src2)
135 {
136 UINTN Src1Size, Src1Inst, Src2Size, Size;
137 EFI_DEVICE_PATH *Dst, *Inst;
138 UINT8 *DstPos;
139
140 //
141 // If there's only 1 path, just duplicate it
142 //
143
144 if (!Src1) {
145 ASSERT (!IsDevicePathUnpacked (Src2));
146 return DuplicateDevicePath (Src2);
147 }
148
149 if (!Src2) {
150 ASSERT (!IsDevicePathUnpacked (Src1));
151 return DuplicateDevicePath (Src1);
152 }
153
154 //
155 // Verify we're not working with unpacked paths
156 //
157
158 // ASSERT (!IsDevicePathUnpacked (Src1));
159 // ASSERT (!IsDevicePathUnpacked (Src2));
160
161 //
162 // Append Src2 to every instance in Src1
163 //
164
165 Src1Size = DevicePathSize(Src1);
166 Src1Inst = DevicePathInstanceCount(Src1);
167 Src2Size = DevicePathSize(Src2);
168 Size = Src1Size * Src1Inst + Src2Size;
169
170 Dst = AllocatePool (Size);
171 if (Dst) {
172 DstPos = (UINT8 *) Dst;
173
174 //
175 // Copy all device path instances
176 //
177
178 while ((Inst = DevicePathInstance (&Src1, &Size))) {
179
180 CopyMem(DstPos, Inst, Size);
181 DstPos += Size;
182
183 CopyMem(DstPos, Src2, Src2Size);
184 DstPos += Src2Size;
185
186 CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
187 DstPos += sizeof(EFI_DEVICE_PATH);
188 }
189
190 // Change last end marker
191 DstPos -= sizeof(EFI_DEVICE_PATH);
192 CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH));
193 }
194
195 return Dst;
196 }
197
198
199 EFI_DEVICE_PATH *
AppendDevicePathNode(IN EFI_DEVICE_PATH * Src1,IN EFI_DEVICE_PATH * Src2)200 AppendDevicePathNode (
201 IN EFI_DEVICE_PATH *Src1,
202 IN EFI_DEVICE_PATH *Src2
203 )
204 // Src1 may have multiple "instances" and each instance is appended
205 // Src2 is a signal device path node (without a terminator) that is
206 // appended to each instance is Src1.
207 {
208 EFI_DEVICE_PATH *Temp, *Eop;
209 UINTN Length;
210
211 //
212 // Build a Src2 that has a terminator on it
213 //
214
215 Length = DevicePathNodeLength(Src2);
216 Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
217 if (!Temp) {
218 return NULL;
219 }
220
221 CopyMem (Temp, Src2, Length);
222 Eop = NextDevicePathNode(Temp);
223 SetDevicePathEndNode(Eop);
224
225 //
226 // Append device paths
227 //
228
229 Src1 = AppendDevicePath (Src1, Temp);
230 FreePool (Temp);
231 return Src1;
232 }
233
234
235 EFI_DEVICE_PATH *
FileDevicePath(IN EFI_HANDLE Device OPTIONAL,IN CHAR16 * FileName)236 FileDevicePath (
237 IN EFI_HANDLE Device OPTIONAL,
238 IN CHAR16 *FileName
239 )
240 /*++
241
242 N.B. Results are allocated from pool. The caller must FreePool
243 the resulting device path structure
244
245 --*/
246 {
247 UINTN Size;
248 FILEPATH_DEVICE_PATH *FilePath;
249 EFI_DEVICE_PATH *Eop, *DevicePath;
250
251 Size = StrSize(FileName);
252 FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
253 DevicePath = NULL;
254
255 if (FilePath) {
256
257 //
258 // Build a file path
259 //
260
261 FilePath->Header.Type = MEDIA_DEVICE_PATH;
262 FilePath->Header.SubType = MEDIA_FILEPATH_DP;
263 SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
264 CopyMem (FilePath->PathName, FileName, Size);
265 Eop = NextDevicePathNode(&FilePath->Header);
266 SetDevicePathEndNode(Eop);
267
268 //
269 // Append file path to device's device path
270 //
271
272 DevicePath = (EFI_DEVICE_PATH *) FilePath;
273 if (Device) {
274 DevicePath = AppendDevicePath (
275 DevicePathFromHandle(Device),
276 DevicePath
277 );
278
279 FreePool(FilePath);
280 }
281 }
282
283 return DevicePath;
284 }
285
286
287
288 UINTN
DevicePathSize(IN EFI_DEVICE_PATH * DevPath)289 DevicePathSize (
290 IN EFI_DEVICE_PATH *DevPath
291 )
292 {
293 EFI_DEVICE_PATH *Start;
294
295 //
296 // Search for the end of the device path structure
297 //
298
299 Start = DevPath;
300 while (!IsDevicePathEnd(DevPath)) {
301 DevPath = NextDevicePathNode(DevPath);
302 }
303
304 //
305 // Compute the size
306 //
307
308 return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH);
309 }
310
311 EFI_DEVICE_PATH *
DuplicateDevicePath(IN EFI_DEVICE_PATH * DevPath)312 DuplicateDevicePath (
313 IN EFI_DEVICE_PATH *DevPath
314 )
315 {
316 EFI_DEVICE_PATH *NewDevPath;
317 UINTN Size;
318
319
320 //
321 // Compute the size
322 //
323
324 Size = DevicePathSize (DevPath);
325
326 //
327 // Make a copy
328 //
329
330 NewDevPath = AllocatePool (Size);
331 if (NewDevPath) {
332 CopyMem (NewDevPath, DevPath, Size);
333 }
334
335 return NewDevPath;
336 }
337
338 EFI_DEVICE_PATH *
UnpackDevicePath(IN EFI_DEVICE_PATH * DevPath)339 UnpackDevicePath (
340 IN EFI_DEVICE_PATH *DevPath
341 )
342 {
343 EFI_DEVICE_PATH *Src, *Dest, *NewPath;
344 UINTN Size;
345
346 //
347 // Walk device path and round sizes to valid boundries
348 //
349
350 Src = DevPath;
351 Size = 0;
352 for (; ;) {
353 Size += DevicePathNodeLength(Src);
354 Size += ALIGN_SIZE(Size);
355
356 if (IsDevicePathEnd(Src)) {
357 break;
358 }
359
360 Src = NextDevicePathNode(Src);
361 }
362
363
364 //
365 // Allocate space for the unpacked path
366 //
367
368 NewPath = AllocateZeroPool (Size);
369 if (NewPath) {
370
371 ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
372
373 //
374 // Copy each node
375 //
376
377 Src = DevPath;
378 Dest = NewPath;
379 for (; ;) {
380 Size = DevicePathNodeLength(Src);
381 CopyMem (Dest, Src, Size);
382 Size += ALIGN_SIZE(Size);
383 SetDevicePathNodeLength (Dest, Size);
384 Dest->Type |= EFI_DP_TYPE_UNPACKED;
385 Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);
386
387 if (IsDevicePathEnd(Src)) {
388 break;
389 }
390
391 Src = NextDevicePathNode(Src);
392 }
393 }
394
395 return NewPath;
396 }
397
398
399 EFI_DEVICE_PATH*
AppendDevicePathInstance(IN EFI_DEVICE_PATH * Src,IN EFI_DEVICE_PATH * Instance)400 AppendDevicePathInstance (
401 IN EFI_DEVICE_PATH *Src,
402 IN EFI_DEVICE_PATH *Instance
403 )
404 {
405 UINT8 *Ptr;
406 EFI_DEVICE_PATH *DevPath;
407 UINTN SrcSize;
408 UINTN InstanceSize;
409
410 if (Src == NULL) {
411 return DuplicateDevicePath (Instance);
412 }
413 SrcSize = DevicePathSize(Src);
414 InstanceSize = DevicePathSize(Instance);
415 Ptr = AllocatePool (SrcSize + InstanceSize);
416 DevPath = (EFI_DEVICE_PATH *)Ptr;
417 ASSERT(DevPath);
418
419 CopyMem (Ptr, Src, SrcSize);
420 // FreePool (Src);
421
422 while (!IsDevicePathEnd(DevPath)) {
423 DevPath = NextDevicePathNode(DevPath);
424 }
425 //
426 // Convert the End to an End Instance, since we are
427 // appending another instacne after this one its a good
428 // idea.
429 //
430 DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
431
432 DevPath = NextDevicePathNode(DevPath);
433 CopyMem (DevPath, Instance, InstanceSize);
434 return (EFI_DEVICE_PATH *)Ptr;
435 }
436
437 EFI_STATUS
LibDevicePathToInterface(IN EFI_GUID * Protocol,IN EFI_DEVICE_PATH * FilePath,OUT VOID ** Interface)438 LibDevicePathToInterface (
439 IN EFI_GUID *Protocol,
440 IN EFI_DEVICE_PATH *FilePath,
441 OUT VOID **Interface
442 )
443 {
444 EFI_STATUS Status;
445 EFI_HANDLE Device;
446
447 Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &FilePath, &Device);
448
449 if (!EFI_ERROR(Status)) {
450
451 // If we didn't get a direct match return not found
452 Status = EFI_NOT_FOUND;
453
454 if (IsDevicePathEnd(FilePath)) {
455
456 //
457 // It was a direct match, lookup the protocol interface
458 //
459
460 Status =uefi_call_wrapper(BS->HandleProtocol, 3, Device, Protocol, Interface);
461 }
462 }
463
464 //
465 // If there was an error, do not return an interface
466 //
467
468 if (EFI_ERROR(Status)) {
469 *Interface = NULL;
470 }
471
472 return Status;
473 }
474
475 static VOID
_DevPathPci(IN OUT POOL_PRINT * Str,IN VOID * DevPath)476 _DevPathPci (
477 IN OUT POOL_PRINT *Str,
478 IN VOID *DevPath
479 )
480 {
481 PCI_DEVICE_PATH *Pci;
482
483 Pci = DevPath;
484 CatPrint(Str, L"Pci(0x%x,0x%x)", Pci->Device, Pci->Function);
485 }
486
487 static VOID
_DevPathPccard(IN OUT POOL_PRINT * Str,IN VOID * DevPath)488 _DevPathPccard (
489 IN OUT POOL_PRINT *Str,
490 IN VOID *DevPath
491 )
492 {
493 PCCARD_DEVICE_PATH *Pccard;
494
495 Pccard = DevPath;
496 CatPrint(Str, L"Pccard(0x%x)", Pccard-> FunctionNumber );
497 }
498
499 static VOID
_DevPathMemMap(IN OUT POOL_PRINT * Str,IN VOID * DevPath)500 _DevPathMemMap (
501 IN OUT POOL_PRINT *Str,
502 IN VOID *DevPath
503 )
504 {
505 MEMMAP_DEVICE_PATH *MemMap;
506
507 MemMap = DevPath;
508 CatPrint(Str, L"MemMap(%d,0x%x,0x%x)",
509 MemMap->MemoryType,
510 MemMap->StartingAddress,
511 MemMap->EndingAddress
512 );
513 }
514
515 static VOID
_DevPathController(IN OUT POOL_PRINT * Str,IN VOID * DevPath)516 _DevPathController (
517 IN OUT POOL_PRINT *Str,
518 IN VOID *DevPath
519 )
520 {
521 CONTROLLER_DEVICE_PATH *Controller;
522
523 Controller = DevPath;
524 CatPrint(Str, L"Ctrl(%d)",
525 Controller->Controller
526 );
527 }
528
529 static VOID
_DevPathVendor(IN OUT POOL_PRINT * Str,IN VOID * DevPath)530 _DevPathVendor (
531 IN OUT POOL_PRINT *Str,
532 IN VOID *DevPath
533 )
534 {
535 VENDOR_DEVICE_PATH *Vendor;
536 CHAR16 *Type;
537 UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevPath;
538
539 Vendor = DevPath;
540 switch (DevicePathType(&Vendor->Header)) {
541 case HARDWARE_DEVICE_PATH: Type = L"Hw"; break;
542 case MESSAGING_DEVICE_PATH: Type = L"Msg"; break;
543 case MEDIA_DEVICE_PATH: Type = L"Media"; break;
544 default: Type = L"?"; break;
545 }
546
547 CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid);
548 if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) {
549 //
550 // GUID used by EFI to enumerate an EDD 1.1 device
551 //
552 UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor;
553 CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
554 } else {
555 CatPrint(Str, L")");
556 }
557 }
558
559
560 /*
561 Type: 2 (ACPI Device Path) SubType: 1 (ACPI Device Path)
562 */
563 static VOID
_DevPathAcpi(IN OUT POOL_PRINT * Str,IN VOID * DevPath)564 _DevPathAcpi (
565 IN OUT POOL_PRINT *Str,
566 IN VOID *DevPath
567 )
568 {
569 ACPI_HID_DEVICE_PATH *Acpi;
570
571 Acpi = DevPath;
572 if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
573 switch ( EISA_ID_TO_NUM( Acpi-> HID ) ) {
574 case 0x301 : {
575 CatPrint( Str , L"Keyboard(%d)" , Acpi-> UID ) ;
576 break ;
577 }
578 case 0x401 : {
579 CatPrint( Str , L"ParallelPort(%d)" , Acpi-> UID ) ;
580 break ;
581 }
582 case 0x501 : {
583 CatPrint( Str , L"Serial(%d)" , Acpi-> UID ) ;
584 break ;
585 }
586 case 0x604 : {
587 CatPrint( Str , L"Floppy(%d)" , Acpi-> UID ) ;
588 break ;
589 }
590 case 0xa03 : {
591 CatPrint( Str , L"PciRoot(%d)" , Acpi-> UID ) ;
592 break ;
593 }
594 case 0xa08 : {
595 CatPrint( Str , L"PcieRoot(%d)" , Acpi-> UID ) ;
596 break ;
597 }
598 default : {
599 CatPrint( Str , L"Acpi(PNP%04x" , EISA_ID_TO_NUM( Acpi-> HID ) ) ;
600 if ( Acpi-> UID ) CatPrint( Str , L",%d" , Acpi-> UID ) ;
601 CatPrint( Str , L")" ) ;
602 break ;
603 }
604 }
605 } else {
606 CatPrint( Str , L"Acpi(0x%X" , Acpi-> HID ) ;
607 if ( Acpi-> UID ) CatPrint( Str , L",%d" , Acpi-> UID ) ;
608 CatPrint( Str , L")" , Acpi-> HID , Acpi-> UID ) ;
609 }
610 }
611
612
613 static VOID
_DevPathAtapi(IN OUT POOL_PRINT * Str,IN VOID * DevPath)614 _DevPathAtapi (
615 IN OUT POOL_PRINT *Str,
616 IN VOID *DevPath
617 )
618 {
619 ATAPI_DEVICE_PATH *Atapi;
620
621 Atapi = DevPath;
622 CatPrint(Str, L"Ata(%s,%s)",
623 Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
624 Atapi->SlaveMaster ? L"Slave" : L"Master"
625 );
626 }
627
628 static VOID
_DevPathScsi(IN OUT POOL_PRINT * Str,IN VOID * DevPath)629 _DevPathScsi (
630 IN OUT POOL_PRINT *Str,
631 IN VOID *DevPath
632 )
633 {
634 SCSI_DEVICE_PATH *Scsi;
635
636 Scsi = DevPath;
637 CatPrint(Str, L"Scsi(%d,%d)", Scsi->Pun, Scsi->Lun);
638 }
639
640
641 static VOID
_DevPathFibre(IN OUT POOL_PRINT * Str,IN VOID * DevPath)642 _DevPathFibre (
643 IN OUT POOL_PRINT *Str,
644 IN VOID *DevPath
645 )
646 {
647 FIBRECHANNEL_DEVICE_PATH *Fibre;
648
649 Fibre = DevPath;
650 CatPrint( Str , L"Fibre%s(0x%016lx,0x%016lx)" ,
651 DevicePathType( & Fibre-> Header ) == MSG_FIBRECHANNEL_DP ? L"" : L"Ex" ,
652 Fibre-> WWN , Fibre-> Lun ) ;
653 }
654
655 static VOID
_DevPath1394(IN OUT POOL_PRINT * Str,IN VOID * DevPath)656 _DevPath1394 (
657 IN OUT POOL_PRINT *Str,
658 IN VOID *DevPath
659 )
660 {
661 F1394_DEVICE_PATH *F1394;
662
663 F1394 = DevPath;
664 // Guid has format of IEEE-EUI64
665 CatPrint(Str, L"I1394(%016lx)", F1394->Guid);
666 }
667
668
669
670 static VOID
_DevPathUsb(IN OUT POOL_PRINT * Str,IN VOID * DevPath)671 _DevPathUsb (
672 IN OUT POOL_PRINT *Str,
673 IN VOID *DevPath
674 )
675 {
676 USB_DEVICE_PATH *Usb;
677
678 Usb = DevPath;
679 CatPrint( Str , L"Usb(0x%x,0x%x)" , Usb-> Port , Usb-> Endpoint ) ;
680 }
681
682
683 static VOID
_DevPathI2O(IN OUT POOL_PRINT * Str,IN VOID * DevPath)684 _DevPathI2O (
685 IN OUT POOL_PRINT *Str,
686 IN VOID *DevPath
687 )
688 {
689 I2O_DEVICE_PATH *I2O;
690
691 I2O = DevPath;
692 CatPrint(Str, L"I2O(0x%X)", I2O->Tid);
693 }
694
695 static VOID
_DevPathMacAddr(IN OUT POOL_PRINT * Str,IN VOID * DevPath)696 _DevPathMacAddr (
697 IN OUT POOL_PRINT *Str,
698 IN VOID *DevPath
699 )
700 {
701 MAC_ADDR_DEVICE_PATH *MAC;
702 UINTN HwAddressSize;
703 UINTN Index;
704
705 MAC = DevPath;
706
707 /* HwAddressSize = sizeof(EFI_MAC_ADDRESS); */
708 HwAddressSize = DevicePathNodeLength( & MAC-> Header ) ;
709 HwAddressSize -= sizeof( MAC-> Header ) ;
710 HwAddressSize -= sizeof( MAC-> IfType ) ;
711 if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
712 HwAddressSize = 6;
713 }
714
715 CatPrint(Str, L"Mac(");
716
717 for(Index = 0; Index < HwAddressSize; Index++) {
718 CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
719 }
720 if ( MAC-> IfType != 0 ) {
721 CatPrint(Str, L",%d" , MAC-> IfType ) ;
722 }
723 CatPrint(Str, L")");
724 }
725
726 static VOID
CatPrintIPv4(IN OUT POOL_PRINT * Str,IN EFI_IPv4_ADDRESS * Address)727 CatPrintIPv4(
728 IN OUT POOL_PRINT * Str ,
729 IN EFI_IPv4_ADDRESS * Address
730 )
731 {
732 CatPrint( Str , L"%d.%d.%d.%d" , Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ,
733 Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ;
734 }
735
736 static BOOLEAN
IsNotNullIPv4(IN EFI_IPv4_ADDRESS * Address)737 IsNotNullIPv4(
738 IN EFI_IPv4_ADDRESS * Address
739 )
740 {
741 UINT8 val ;
742 val = Address-> Addr[ 0 ] | Address-> Addr[ 1 ] ;
743 val |= Address-> Addr[ 2 ] | Address-> Addr[ 3 ] ;
744 return val != 0 ;
745 }
746
747 static VOID
CatPrintNetworkProtocol(IN OUT POOL_PRINT * Str,IN UINT16 Proto)748 CatPrintNetworkProtocol(
749 IN OUT POOL_PRINT * Str ,
750 IN UINT16 Proto
751 )
752 {
753 if ( Proto == 6 ) {
754 CatPrint( Str , L"TCP" ) ;
755 } else if ( Proto == 17 ) {
756 CatPrint( Str , L"UDP" ) ;
757 } else {
758 CatPrint( Str , L"%d" , Proto ) ;
759 }
760 }
761
762 static VOID
_DevPathIPv4(IN OUT POOL_PRINT * Str,IN VOID * DevPath)763 _DevPathIPv4 (
764 IN OUT POOL_PRINT *Str,
765 IN VOID *DevPath
766 )
767 {
768 IPv4_DEVICE_PATH *IP __unused;
769 BOOLEAN show ;
770
771 IP = DevPath;
772 CatPrint( Str , L"IPv4(") ;
773 CatPrintIPv4( Str , & IP-> RemoteIpAddress ) ;
774 CatPrint( Str , L",") ;
775 CatPrintNetworkProtocol( Str , IP-> Protocol ) ;
776 CatPrint( Str , L",%s" , IP-> StaticIpAddress ? L"Static" : L"DHCP" ) ;
777 show = IsNotNullIPv4( & IP-> LocalIpAddress ) ;
778 if ( ! show && DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) {
779 /* only version 2 includes gateway and netmask */
780 show |= IsNotNullIPv4( & IP-> GatewayIpAddress ) ;
781 show |= IsNotNullIPv4( & IP-> SubnetMask ) ;
782 }
783 if ( show ) {
784 CatPrint( Str , L"," ) ;
785 CatPrintIPv4( Str , & IP-> LocalIpAddress ) ;
786 if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) {
787 /* only version 2 includes gateway and netmask */
788 show = IsNotNullIPv4( & IP-> GatewayIpAddress ) ;
789 show |= IsNotNullIPv4( & IP-> SubnetMask ) ;
790 if ( show ) {
791 CatPrint( Str , L",") ;
792 CatPrintIPv4( Str , & IP-> GatewayIpAddress ) ;
793 if ( IsNotNullIPv4( & IP-> SubnetMask ) ) {
794 CatPrint( Str , L",") ;
795 CatPrintIPv4( Str , & IP-> SubnetMask ) ;
796 }
797 }
798 }
799 }
800 CatPrint( Str , L")") ;
801 }
802
803 #define CatPrintIPv6_ADD( x , y ) ( ( (UINT16) ( x ) ) << 8 | ( y ) )
804 static VOID
CatPrintIPv6(IN OUT POOL_PRINT * Str,IN EFI_IPv6_ADDRESS * Address)805 CatPrintIPv6(
806 IN OUT POOL_PRINT * Str ,
807 IN EFI_IPv6_ADDRESS * Address
808 )
809 {
810 CatPrint( Str , L"%x:%x:%x:%x:%x:%x:%x:%x" ,
811 CatPrintIPv6_ADD( Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ) ,
812 CatPrintIPv6_ADD( Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ,
813 CatPrintIPv6_ADD( Address-> Addr[ 4 ] , Address-> Addr[ 5 ] ) ,
814 CatPrintIPv6_ADD( Address-> Addr[ 6 ] , Address-> Addr[ 7 ] ) ,
815 CatPrintIPv6_ADD( Address-> Addr[ 8 ] , Address-> Addr[ 9 ] ) ,
816 CatPrintIPv6_ADD( Address-> Addr[ 10 ] , Address-> Addr[ 11 ] ) ,
817 CatPrintIPv6_ADD( Address-> Addr[ 12 ] , Address-> Addr[ 13 ] ) ,
818 CatPrintIPv6_ADD( Address-> Addr[ 14 ] , Address-> Addr[ 15 ] ) ) ;
819 }
820
821 static VOID
_DevPathIPv6(IN OUT POOL_PRINT * Str,IN VOID * DevPath)822 _DevPathIPv6 (
823 IN OUT POOL_PRINT *Str,
824 IN VOID *DevPath
825 )
826 {
827 IPv6_DEVICE_PATH *IP __unused;
828
829 IP = DevPath;
830 CatPrint( Str , L"IPv6(") ;
831 CatPrintIPv6( Str , & IP-> RemoteIpAddress ) ;
832 CatPrint( Str , L",") ;
833 CatPrintNetworkProtocol( Str, IP-> Protocol ) ;
834 CatPrint( Str , L",%s," , IP-> IPAddressOrigin ?
835 ( IP-> IPAddressOrigin == 1 ? L"StatelessAutoConfigure" :
836 L"StatefulAutoConfigure" ) : L"Static" ) ;
837 CatPrintIPv6( Str , & IP-> LocalIpAddress ) ;
838 if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv6_DEVICE_PATH ) ) {
839 CatPrint( Str , L",") ;
840 CatPrintIPv6( Str , & IP-> GatewayIpAddress ) ;
841 CatPrint( Str , L",") ;
842 CatPrint( Str , L"%d" , & IP-> PrefixLength ) ;
843 }
844 CatPrint( Str , L")") ;
845 }
846
847 static VOID
_DevPathUri(IN OUT POOL_PRINT * Str,IN VOID * DevPath)848 _DevPathUri (
849 IN OUT POOL_PRINT *Str,
850 IN VOID *DevPath
851 )
852 {
853 URI_DEVICE_PATH *Uri;
854
855 Uri = DevPath;
856
857 CatPrint( Str, L"Uri(%a)", Uri->Uri );
858 }
859
860 static VOID
_DevPathInfiniBand(IN OUT POOL_PRINT * Str,IN VOID * DevPath)861 _DevPathInfiniBand (
862 IN OUT POOL_PRINT *Str,
863 IN VOID *DevPath
864 )
865 {
866 INFINIBAND_DEVICE_PATH *InfiniBand __unused;
867
868 InfiniBand = DevPath;
869 CatPrint(Str, L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)",
870 InfiniBand->ResourceFlags, InfiniBand->PortGid, InfiniBand->ServiceId,
871 InfiniBand->TargetPortId, InfiniBand->DeviceId);
872 }
873
874 static VOID
_DevPathUart(IN OUT POOL_PRINT * Str,IN VOID * DevPath)875 _DevPathUart (
876 IN OUT POOL_PRINT *Str,
877 IN VOID *DevPath
878 )
879 {
880 UART_DEVICE_PATH *Uart;
881 CHAR8 Parity;
882
883 Uart = DevPath;
884 switch (Uart->Parity) {
885 case 0 : Parity = 'D'; break;
886 case 1 : Parity = 'N'; break;
887 case 2 : Parity = 'E'; break;
888 case 3 : Parity = 'O'; break;
889 case 4 : Parity = 'M'; break;
890 case 5 : Parity = 'S'; break;
891 default : Parity = 'x'; break;
892 }
893
894 if (Uart->BaudRate == 0) {
895 CatPrint(Str, L"Uart(DEFAULT,");
896 } else {
897 CatPrint(Str, L"Uart(%ld,", Uart->BaudRate);
898 }
899
900 if (Uart->DataBits == 0) {
901 CatPrint(Str, L"DEFAULT,");
902 } else {
903 CatPrint(Str, L"%d,", Uart->DataBits);
904 }
905
906 CatPrint(Str, L"%c,", Parity);
907
908 switch (Uart->StopBits) {
909 case 0 : CatPrint(Str, L"D)"); break;
910 case 1 : CatPrint(Str, L"1)"); break;
911 case 2 : CatPrint(Str, L"1.5)"); break;
912 case 3 : CatPrint(Str, L"2)"); break;
913 default : CatPrint(Str, L"x)"); break;
914 }
915 }
916
917 static VOID
_DevPathSata(IN OUT POOL_PRINT * Str,IN VOID * DevPath)918 _DevPathSata (
919 IN OUT POOL_PRINT *Str,
920 IN VOID *DevPath
921 )
922 {
923 SATA_DEVICE_PATH * Sata ;
924
925 Sata = DevPath;
926 CatPrint( Str , L"Sata(0x%x,0x%x,0x%x)" , Sata-> HBAPortNumber ,
927 Sata-> PortMultiplierPortNumber , Sata-> Lun ) ;
928 }
929
930 static VOID
_DevPathHardDrive(IN OUT POOL_PRINT * Str,IN VOID * DevPath)931 _DevPathHardDrive (
932 IN OUT POOL_PRINT *Str,
933 IN VOID *DevPath
934 )
935 {
936 HARDDRIVE_DEVICE_PATH *Hd;
937
938 Hd = DevPath;
939 switch (Hd->SignatureType) {
940 case SIGNATURE_TYPE_MBR:
941 CatPrint(Str, L"HD(%d,MBR,0x%08x)",
942 Hd->PartitionNumber,
943 *((UINT32 *)(&(Hd->Signature[0])))
944 );
945 break;
946 case SIGNATURE_TYPE_GUID:
947 CatPrint(Str, L"HD(%d,GPT,%g)",
948 Hd->PartitionNumber,
949 (EFI_GUID *) &(Hd->Signature[0])
950 );
951 break;
952 default:
953 CatPrint(Str, L"HD(%d,%d,0)",
954 Hd->PartitionNumber,
955 Hd->SignatureType
956 );
957 break;
958 }
959 }
960
961 static VOID
_DevPathCDROM(IN OUT POOL_PRINT * Str,IN VOID * DevPath)962 _DevPathCDROM (
963 IN OUT POOL_PRINT *Str,
964 IN VOID *DevPath
965 )
966 {
967 CDROM_DEVICE_PATH *Cd;
968
969 Cd = DevPath;
970 CatPrint( Str , L"CDROM(0x%x)" , Cd-> BootEntry ) ;
971 }
972
973 static VOID
_DevPathFilePath(IN OUT POOL_PRINT * Str,IN VOID * DevPath)974 _DevPathFilePath (
975 IN OUT POOL_PRINT *Str,
976 IN VOID *DevPath
977 )
978 {
979 FILEPATH_DEVICE_PATH *Fp;
980
981 Fp = DevPath;
982 CatPrint(Str, L"%s", Fp->PathName);
983 }
984
985 static VOID
_DevPathMediaProtocol(IN OUT POOL_PRINT * Str,IN VOID * DevPath)986 _DevPathMediaProtocol (
987 IN OUT POOL_PRINT *Str,
988 IN VOID *DevPath
989 )
990 {
991 MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
992
993 MediaProt = DevPath;
994 CatPrint(Str, L"%g", &MediaProt->Protocol);
995 }
996
997 static VOID
_DevPathBssBss(IN OUT POOL_PRINT * Str,IN VOID * DevPath)998 _DevPathBssBss (
999 IN OUT POOL_PRINT *Str,
1000 IN VOID *DevPath
1001 )
1002 {
1003 BBS_BBS_DEVICE_PATH *Bss;
1004 CHAR16 *Type;
1005
1006 Bss = DevPath;
1007 switch (Bss->DeviceType) {
1008 case BBS_TYPE_FLOPPY: Type = L"Floppy"; break;
1009 case BBS_TYPE_HARDDRIVE: Type = L"Harddrive"; break;
1010 case BBS_TYPE_CDROM: Type = L"CDROM"; break;
1011 case BBS_TYPE_PCMCIA: Type = L"PCMCIA"; break;
1012 case BBS_TYPE_USB: Type = L"Usb"; break;
1013 case BBS_TYPE_EMBEDDED_NETWORK: Type = L"Net"; break;
1014 default: Type = L"?"; break;
1015 }
1016
1017 CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
1018 }
1019
1020
1021 static VOID
_DevPathEndInstance(IN OUT POOL_PRINT * Str,IN VOID * DevPath EFI_UNUSED)1022 _DevPathEndInstance (
1023 IN OUT POOL_PRINT *Str,
1024 IN VOID *DevPath EFI_UNUSED
1025 )
1026 {
1027 CatPrint(Str, L",");
1028 }
1029
1030 /**
1031 * Print unknown device node.
1032 * UEFI 2.4 § 9.6.1.6 table 89.
1033 */
1034
1035 static VOID
_DevPathNodeUnknown(IN OUT POOL_PRINT * Str,IN VOID * DevPath)1036 _DevPathNodeUnknown (
1037 IN OUT POOL_PRINT *Str,
1038 IN VOID *DevPath
1039 )
1040 {
1041 EFI_DEVICE_PATH * Path ;
1042 UINT8 * value ;
1043 int length , index ;
1044 Path = DevPath ;
1045 value = DevPath ;
1046 value += 4 ;
1047 switch ( Path-> Type ) {
1048 case HARDWARE_DEVICE_PATH : { /* Unknown Hardware Device Path */
1049 CatPrint( Str , L"HardwarePath(%d" , Path-> SubType ) ;
1050 break ;
1051 }
1052 case ACPI_DEVICE_PATH : { /* Unknown ACPI Device Path */
1053 CatPrint( Str , L"AcpiPath(%d" , Path-> SubType ) ;
1054 break ;
1055 }
1056 case MESSAGING_DEVICE_PATH : { /* Unknown Messaging Device Path */
1057 CatPrint( Str , L"Msg(%d" , Path-> SubType ) ;
1058 break ;
1059 }
1060 case MEDIA_DEVICE_PATH : { /* Unknown Media Device Path */
1061 CatPrint( Str , L"MediaPath(%d" , Path-> SubType ) ;
1062 break ;
1063 }
1064 case BBS_DEVICE_PATH : { /* Unknown BIOS Boot Specification Device Path */
1065 CatPrint( Str , L"BbsPath(%d" , Path-> SubType ) ;
1066 break ;
1067 }
1068 default : { /* Unknown Device Path */
1069 CatPrint( Str , L"Path(%d,%d" , Path-> Type , Path-> SubType ) ;
1070 break ;
1071 }
1072 }
1073 length = DevicePathNodeLength( Path ) ;
1074 for ( index = 0 ; index < length ; index ++ ) {
1075 if ( index == 0 ) CatPrint( Str , L",0x" ) ;
1076 CatPrint( Str , L"%02x" , * value ) ;
1077 value ++ ;
1078 }
1079 CatPrint( Str , L")" ) ;
1080 }
1081
1082
1083 /*
1084 * Table to convert "Type" and "SubType" to a "convert to text" function/
1085 * Entries hold "Type" and "SubType" for know values.
1086 * Special "SubType" 0 is used as default for known type with unknown subtype.
1087 */
1088 struct {
1089 UINT8 Type;
1090 UINT8 SubType;
1091 VOID (*Function)(POOL_PRINT *, VOID *);
1092 } DevPathTable[] = {
1093 { HARDWARE_DEVICE_PATH, HW_PCI_DP, _DevPathPci},
1094 { HARDWARE_DEVICE_PATH, HW_PCCARD_DP, _DevPathPccard},
1095 { HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, _DevPathMemMap},
1096 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, _DevPathVendor},
1097 { HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, _DevPathController},
1098 { ACPI_DEVICE_PATH, ACPI_DP, _DevPathAcpi},
1099 { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, _DevPathAtapi},
1100 { MESSAGING_DEVICE_PATH, MSG_SCSI_DP, _DevPathScsi},
1101 { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, _DevPathFibre},
1102 { MESSAGING_DEVICE_PATH, MSG_1394_DP, _DevPath1394},
1103 { MESSAGING_DEVICE_PATH, MSG_USB_DP, _DevPathUsb},
1104 { MESSAGING_DEVICE_PATH, MSG_I2O_DP, _DevPathI2O},
1105 { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, _DevPathMacAddr},
1106 { MESSAGING_DEVICE_PATH, MSG_IPv4_DP, _DevPathIPv4},
1107 { MESSAGING_DEVICE_PATH, MSG_IPv6_DP, _DevPathIPv6},
1108 { MESSAGING_DEVICE_PATH, MSG_URI_DP, _DevPathUri},
1109 { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, _DevPathInfiniBand},
1110 { MESSAGING_DEVICE_PATH, MSG_UART_DP, _DevPathUart},
1111 { MESSAGING_DEVICE_PATH , MSG_SATA_DP , _DevPathSata } ,
1112 { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, _DevPathVendor},
1113 { MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, _DevPathHardDrive},
1114 { MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, _DevPathCDROM},
1115 { MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, _DevPathVendor},
1116 { MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, _DevPathFilePath},
1117 { MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, _DevPathMediaProtocol},
1118 { BBS_DEVICE_PATH, BBS_BBS_DP, _DevPathBssBss},
1119 { END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
1120 { 0, 0, NULL}
1121 };
1122
1123
1124 CHAR16 *
DevicePathToStr(EFI_DEVICE_PATH * DevPath)1125 DevicePathToStr (
1126 EFI_DEVICE_PATH *DevPath
1127 )
1128 /*++
1129
1130 Turns the Device Path into a printable string. Allcoates
1131 the string from pool. The caller must FreePool the returned
1132 string.
1133
1134 --*/
1135 {
1136 POOL_PRINT Str;
1137 EFI_DEVICE_PATH *DevPathNode;
1138 VOID (*DumpNode)(POOL_PRINT *, VOID *);
1139 UINTN Index, NewSize;
1140
1141 ZeroMem(&Str, sizeof(Str));
1142
1143 //
1144 // Unpacked the device path
1145 //
1146
1147 DevPath = UnpackDevicePath(DevPath);
1148 ASSERT (DevPath);
1149
1150
1151 //
1152 // Process each device path node
1153 //
1154
1155 DevPathNode = DevPath;
1156 while (!IsDevicePathEnd(DevPathNode)) {
1157 //
1158 // Find the handler to dump this device path node
1159 //
1160
1161 DumpNode = NULL;
1162 for (Index = 0; DevPathTable[Index].Function; Index += 1) {
1163
1164 if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
1165 DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
1166 DumpNode = DevPathTable[Index].Function;
1167 break;
1168 }
1169 }
1170
1171 //
1172 // If not found, use a generic function
1173 //
1174
1175 if (!DumpNode) {
1176 DumpNode = _DevPathNodeUnknown;
1177 }
1178
1179 //
1180 // Put a path seperator in if needed
1181 //
1182
1183 if (Str.len && DumpNode != _DevPathEndInstance) {
1184 CatPrint (&Str, L"/");
1185 }
1186
1187 //
1188 // Print this node of the device path
1189 //
1190
1191 DumpNode (&Str, DevPathNode);
1192
1193 //
1194 // Next device path node
1195 //
1196
1197 DevPathNode = NextDevicePathNode(DevPathNode);
1198 }
1199
1200 //
1201 // Shrink pool used for string allocation
1202 //
1203
1204 FreePool (DevPath);
1205 NewSize = (Str.len + 1) * sizeof(CHAR16);
1206 Str.str = ReallocatePool (Str.str, NewSize, NewSize);
1207 Str.str[Str.len] = 0;
1208 return Str.str;
1209 }
1210
1211 BOOLEAN
LibMatchDevicePaths(IN EFI_DEVICE_PATH * Multi,IN EFI_DEVICE_PATH * Single)1212 LibMatchDevicePaths (
1213 IN EFI_DEVICE_PATH *Multi,
1214 IN EFI_DEVICE_PATH *Single
1215 )
1216 {
1217 EFI_DEVICE_PATH *DevicePath, *DevicePathInst;
1218 UINTN Size;
1219
1220 if (!Multi || !Single) {
1221 return FALSE;
1222 }
1223
1224 DevicePath = Multi;
1225 while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
1226 if (CompareMem (Single, DevicePathInst, Size) == 0) {
1227 return TRUE;
1228 }
1229 }
1230 return FALSE;
1231 }
1232
1233 EFI_DEVICE_PATH *
LibDuplicateDevicePathInstance(IN EFI_DEVICE_PATH * DevPath)1234 LibDuplicateDevicePathInstance (
1235 IN EFI_DEVICE_PATH *DevPath
1236 )
1237 {
1238 EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp;
1239 UINTN Size = 0;
1240
1241 //
1242 // get the size of an instance from the input
1243 //
1244
1245 Temp = DevPath;
1246 DevicePathInst = DevicePathInstance (&Temp, &Size);
1247
1248 //
1249 // Make a copy and set proper end type
1250 //
1251 NewDevPath = NULL;
1252 if (Size) {
1253 NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
1254 }
1255
1256 if (NewDevPath) {
1257 CopyMem (NewDevPath, DevicePathInst, Size);
1258 Temp = NextDevicePathNode(NewDevPath);
1259 SetDevicePathEndNode(Temp);
1260 }
1261
1262 return NewDevPath;
1263 }
1264
1265