xref: /netbsd-src/sys/external/bsd/gnu-efi/dist/lib/dpath.c (revision 95b39c65ca575fb40c6bb7083e0eb7ec28eabef1)
1 /*	$NetBSD: dpath.c,v 1.1.1.1 2014/04/01 16:16:06 jakllsch 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 --*/
19 
20 #include "lib.h"
21 
22 #define ALIGN_SIZE(a)   ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
23 
24 
25 
26 EFI_DEVICE_PATH *
27 DevicePathFromHandle (
28     IN EFI_HANDLE       Handle
29     )
30 {
31     EFI_STATUS          Status;
32     EFI_DEVICE_PATH     *DevicePath;
33 
34     Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DevicePathProtocol, (VOID*)&DevicePath);
35     if (EFI_ERROR(Status)) {
36         DevicePath = NULL;
37     }
38 
39     return DevicePath;
40 }
41 
42 
43 EFI_DEVICE_PATH *
44 DevicePathInstance (
45     IN OUT EFI_DEVICE_PATH  **DevicePath,
46     OUT UINTN               *Size
47     )
48 {
49     EFI_DEVICE_PATH         *Start, *Next, *DevPath;
50     UINTN                   Count;
51 
52     DevPath = *DevicePath;
53     Start = DevPath;
54 
55     if (!DevPath) {
56         return NULL;
57     }
58 
59     //
60     // Check for end of device path type
61     //
62 
63     for (Count = 0; ; Count++) {
64         Next = NextDevicePathNode(DevPath);
65 
66         if (IsDevicePathEndType(DevPath)) {
67             break;
68         }
69 
70         if (Count > 01000) {
71             //
72             // BugBug: Debug code to catch bogus device paths
73             //
74             DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) ));
75             DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
76             break;
77         }
78 
79         DevPath = Next;
80     }
81 
82     ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE ||
83             DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
84 
85     //
86     // Set next position
87     //
88 
89     if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
90         Next = NULL;
91     }
92 
93     *DevicePath = Next;
94 
95     //
96     // Return size and start of device path instance
97     //
98 
99     *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start);
100     return Start;
101 }
102 
103 UINTN
104 DevicePathInstanceCount (
105     IN EFI_DEVICE_PATH      *DevicePath
106     )
107 {
108     UINTN       Count, Size;
109 
110     Count = 0;
111     while (DevicePathInstance(&DevicePath, &Size)) {
112         Count += 1;
113     }
114 
115     return Count;
116 }
117 
118 
119 EFI_DEVICE_PATH *
120 AppendDevicePath (
121     IN EFI_DEVICE_PATH  *Src1,
122     IN EFI_DEVICE_PATH  *Src2
123     )
124 // Src1 may have multiple "instances" and each instance is appended
125 // Src2 is appended to each instance is Src1.  (E.g., it's possible
126 // to append a new instance to the complete device path by passing
127 // it in Src2)
128 {
129     UINTN               Src1Size, Src1Inst, Src2Size, Size;
130     EFI_DEVICE_PATH     *Dst, *Inst;
131     UINT8               *DstPos;
132 
133     //
134     // If there's only 1 path, just duplicate it
135     //
136 
137     if (!Src1) {
138         ASSERT (!IsDevicePathUnpacked (Src2));
139         return DuplicateDevicePath (Src2);
140     }
141 
142     if (!Src2) {
143         ASSERT (!IsDevicePathUnpacked (Src1));
144         return DuplicateDevicePath (Src1);
145     }
146 
147     //
148     // Verify we're not working with unpacked paths
149     //
150 
151 //    ASSERT (!IsDevicePathUnpacked (Src1));
152 //    ASSERT (!IsDevicePathUnpacked (Src2));
153 
154     //
155     // Append Src2 to every instance in Src1
156     //
157 
158     Src1Size = DevicePathSize(Src1);
159     Src1Inst = DevicePathInstanceCount(Src1);
160     Src2Size = DevicePathSize(Src2);
161     Size = Src1Size * Src1Inst + Src2Size;
162 
163     Dst = AllocatePool (Size);
164     if (Dst) {
165         DstPos = (UINT8 *) Dst;
166 
167         //
168         // Copy all device path instances
169         //
170 
171         while ((Inst = DevicePathInstance (&Src1, &Size))) {
172 
173             CopyMem(DstPos, Inst, Size);
174             DstPos += Size;
175 
176             CopyMem(DstPos, Src2, Src2Size);
177             DstPos += Src2Size;
178 
179             CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
180             DstPos += sizeof(EFI_DEVICE_PATH);
181         }
182 
183         // Change last end marker
184         DstPos -= sizeof(EFI_DEVICE_PATH);
185         CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH));
186     }
187 
188     return Dst;
189 }
190 
191 
192 EFI_DEVICE_PATH *
193 AppendDevicePathNode (
194     IN EFI_DEVICE_PATH  *Src1,
195     IN EFI_DEVICE_PATH  *Src2
196     )
197 // Src1 may have multiple "instances" and each instance is appended
198 // Src2 is a signal device path node (without a terminator) that is
199 // appended to each instance is Src1.
200 {
201     EFI_DEVICE_PATH     *Temp, *Eop;
202     UINTN               Length;
203 
204     //
205     // Build a Src2 that has a terminator on it
206     //
207 
208     Length = DevicePathNodeLength(Src2);
209     Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
210     if (!Temp) {
211         return NULL;
212     }
213 
214     CopyMem (Temp, Src2, Length);
215     Eop = NextDevicePathNode(Temp);
216     SetDevicePathEndNode(Eop);
217 
218     //
219     // Append device paths
220     //
221 
222     Src1 = AppendDevicePath (Src1, Temp);
223     FreePool (Temp);
224     return Src1;
225 }
226 
227 
228 EFI_DEVICE_PATH *
229 FileDevicePath (
230     IN EFI_HANDLE       Device  OPTIONAL,
231     IN CHAR16           *FileName
232     )
233 /*++
234 
235     N.B. Results are allocated from pool.  The caller must FreePool
236     the resulting device path structure
237 
238 --*/
239 {
240     UINTN                   Size;
241     FILEPATH_DEVICE_PATH    *FilePath;
242     EFI_DEVICE_PATH         *Eop, *DevicePath;
243 
244     Size = StrSize(FileName);
245     FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
246     DevicePath = NULL;
247 
248     if (FilePath) {
249 
250         //
251         // Build a file path
252         //
253 
254         FilePath->Header.Type = MEDIA_DEVICE_PATH;
255         FilePath->Header.SubType = MEDIA_FILEPATH_DP;
256         SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
257         CopyMem (FilePath->PathName, FileName, Size);
258         Eop = NextDevicePathNode(&FilePath->Header);
259         SetDevicePathEndNode(Eop);
260 
261         //
262         // Append file path to device's device path
263         //
264 
265         DevicePath = (EFI_DEVICE_PATH *) FilePath;
266         if (Device) {
267             DevicePath = AppendDevicePath (
268                             DevicePathFromHandle(Device),
269                             DevicePath
270                             );
271 
272             FreePool(FilePath);
273         }
274     }
275 
276     return DevicePath;
277 }
278 
279 
280 
281 UINTN
282 DevicePathSize (
283     IN EFI_DEVICE_PATH  *DevPath
284     )
285 {
286     EFI_DEVICE_PATH     *Start;
287 
288     //
289     // Search for the end of the device path structure
290     //
291 
292     Start = DevPath;
293     while (!IsDevicePathEnd(DevPath)) {
294         DevPath = NextDevicePathNode(DevPath);
295     }
296 
297     //
298     // Compute the size
299     //
300 
301     return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH);
302 }
303 
304 EFI_DEVICE_PATH *
305 DuplicateDevicePath (
306     IN EFI_DEVICE_PATH  *DevPath
307     )
308 {
309     EFI_DEVICE_PATH     *NewDevPath;
310     UINTN               Size;
311 
312 
313     //
314     // Compute the size
315     //
316 
317     Size = DevicePathSize (DevPath);
318 
319     //
320     // Make a copy
321     //
322 
323     NewDevPath = AllocatePool (Size);
324     if (NewDevPath) {
325         CopyMem (NewDevPath, DevPath, Size);
326     }
327 
328     return NewDevPath;
329 }
330 
331 EFI_DEVICE_PATH *
332 UnpackDevicePath (
333     IN EFI_DEVICE_PATH  *DevPath
334     )
335 {
336     EFI_DEVICE_PATH     *Src, *Dest, *NewPath;
337     UINTN               Size;
338 
339     //
340     // Walk device path and round sizes to valid boundries
341     //
342 
343     Src = DevPath;
344     Size = 0;
345     for (; ;) {
346         Size += DevicePathNodeLength(Src);
347         Size += ALIGN_SIZE(Size);
348 
349         if (IsDevicePathEnd(Src)) {
350             break;
351         }
352 
353         Src = NextDevicePathNode(Src);
354     }
355 
356 
357     //
358     // Allocate space for the unpacked path
359     //
360 
361     NewPath = AllocateZeroPool (Size);
362     if (NewPath) {
363 
364         ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
365 
366         //
367         // Copy each node
368         //
369 
370         Src = DevPath;
371         Dest = NewPath;
372         for (; ;) {
373             Size = DevicePathNodeLength(Src);
374             CopyMem (Dest, Src, Size);
375             Size += ALIGN_SIZE(Size);
376             SetDevicePathNodeLength (Dest, Size);
377             Dest->Type |= EFI_DP_TYPE_UNPACKED;
378             Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);
379 
380             if (IsDevicePathEnd(Src)) {
381                 break;
382             }
383 
384             Src = NextDevicePathNode(Src);
385         }
386     }
387 
388     return NewPath;
389 }
390 
391 
392 EFI_DEVICE_PATH*
393 AppendDevicePathInstance (
394     IN EFI_DEVICE_PATH  *Src,
395     IN EFI_DEVICE_PATH  *Instance
396     )
397 {
398     UINT8           *Ptr;
399     EFI_DEVICE_PATH *DevPath;
400     UINTN           SrcSize;
401     UINTN           InstanceSize;
402 
403     if (Src == NULL) {
404         return DuplicateDevicePath (Instance);
405     }
406     SrcSize = DevicePathSize(Src);
407     InstanceSize = DevicePathSize(Instance);
408     Ptr = AllocatePool (SrcSize + InstanceSize);
409     DevPath = (EFI_DEVICE_PATH *)Ptr;
410     ASSERT(DevPath);
411 
412     CopyMem (Ptr, Src, SrcSize);
413 //    FreePool (Src);
414 
415     while (!IsDevicePathEnd(DevPath)) {
416         DevPath = NextDevicePathNode(DevPath);
417     }
418     //
419     // Convert the End to an End Instance, since we are
420     //  appending another instacne after this one its a good
421     //  idea.
422     //
423     DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
424 
425     DevPath = NextDevicePathNode(DevPath);
426     CopyMem (DevPath, Instance, InstanceSize);
427     return (EFI_DEVICE_PATH *)Ptr;
428 }
429 
430 EFI_STATUS
431 LibDevicePathToInterface (
432     IN EFI_GUID             *Protocol,
433     IN EFI_DEVICE_PATH      *FilePath,
434     OUT VOID                **Interface
435     )
436 {
437     EFI_STATUS              Status;
438     EFI_HANDLE              Device;
439 
440     Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &FilePath, &Device);
441 
442     if (!EFI_ERROR(Status)) {
443 
444         // If we didn't get a direct match return not found
445         Status = EFI_NOT_FOUND;
446 
447         if (IsDevicePathEnd(FilePath)) {
448 
449             //
450             // It was a direct match, lookup the protocol interface
451             //
452 
453             Status =uefi_call_wrapper(BS->HandleProtocol, 3, Device, Protocol, Interface);
454         }
455     }
456 
457     //
458     // If there was an error, do not return an interface
459     //
460 
461     if (EFI_ERROR(Status)) {
462         *Interface = NULL;
463     }
464 
465     return Status;
466 }
467 
468 VOID
469 _DevPathPci (
470     IN OUT POOL_PRINT       *Str,
471     IN VOID                 *DevPath
472     )
473 {
474     PCI_DEVICE_PATH         *Pci;
475 
476     Pci = DevPath;
477     CatPrint(Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);
478 }
479 
480 VOID
481 _DevPathPccard (
482     IN OUT POOL_PRINT       *Str,
483     IN VOID                 *DevPath
484     )
485 {
486     PCCARD_DEVICE_PATH      *Pccard;
487 
488     Pccard = DevPath;
489     CatPrint(Str, L"Pccard(Socket%x)", Pccard->SocketNumber);
490 }
491 
492 VOID
493 _DevPathMemMap (
494     IN OUT POOL_PRINT       *Str,
495     IN VOID                 *DevPath
496     )
497 {
498     MEMMAP_DEVICE_PATH      *MemMap;
499 
500     MemMap = DevPath;
501     CatPrint(Str, L"MemMap(%d:%x-%x)",
502         MemMap->MemoryType,
503         MemMap->StartingAddress,
504         MemMap->EndingAddress
505         );
506 }
507 
508 VOID
509 _DevPathController (
510     IN OUT POOL_PRINT       *Str,
511     IN VOID                 *DevPath
512     )
513 {
514     CONTROLLER_DEVICE_PATH  *Controller;
515 
516     Controller = DevPath;
517     CatPrint(Str, L"Ctrl(%d)",
518         Controller->Controller
519         );
520 }
521 
522 VOID
523 _DevPathVendor (
524     IN OUT POOL_PRINT       *Str,
525     IN VOID                 *DevPath
526     )
527 {
528     VENDOR_DEVICE_PATH                  *Vendor;
529     CHAR16                              *Type;
530     UNKNOWN_DEVICE_VENDOR_DEVICE_PATH   *UnknownDevPath;
531 
532     Vendor = DevPath;
533     switch (DevicePathType(&Vendor->Header)) {
534     case HARDWARE_DEVICE_PATH:  Type = L"Hw";        break;
535     case MESSAGING_DEVICE_PATH: Type = L"Msg";       break;
536     case MEDIA_DEVICE_PATH:     Type = L"Media";     break;
537     default:                    Type = L"?";         break;
538     }
539 
540     CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid);
541     if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) {
542         //
543         // GUID used by EFI to enumerate an EDD 1.1 device
544         //
545         UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor;
546         CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
547     } else {
548         CatPrint(Str, L")");
549     }
550 }
551 
552 
553 VOID
554 _DevPathAcpi (
555     IN OUT POOL_PRINT       *Str,
556     IN VOID                 *DevPath
557     )
558 {
559     ACPI_HID_DEVICE_PATH        *Acpi;
560 
561     Acpi = DevPath;
562     if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
563         CatPrint(Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
564     } else {
565         CatPrint(Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);
566     }
567 }
568 
569 
570 VOID
571 _DevPathAtapi (
572     IN OUT POOL_PRINT       *Str,
573     IN VOID                 *DevPath
574     )
575 {
576     ATAPI_DEVICE_PATH       *Atapi;
577 
578     Atapi = DevPath;
579     CatPrint(Str, L"Ata(%s,%s)",
580         Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
581         Atapi->SlaveMaster ? L"Slave" : L"Master"
582         );
583 }
584 
585 VOID
586 _DevPathScsi (
587     IN OUT POOL_PRINT       *Str,
588     IN VOID                 *DevPath
589     )
590 {
591     SCSI_DEVICE_PATH        *Scsi;
592 
593     Scsi = DevPath;
594     CatPrint(Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);
595 }
596 
597 
598 VOID
599 _DevPathFibre (
600     IN OUT POOL_PRINT       *Str,
601     IN VOID                 *DevPath
602     )
603 {
604     FIBRECHANNEL_DEVICE_PATH    *Fibre;
605 
606     Fibre = DevPath;
607     CatPrint(Str, L"Fibre(%lx)", Fibre->WWN);
608 }
609 
610 VOID
611 _DevPath1394 (
612     IN OUT POOL_PRINT       *Str,
613     IN VOID                 *DevPath
614     )
615 {
616     F1394_DEVICE_PATH       *F1394;
617 
618     F1394 = DevPath;
619     CatPrint(Str, L"1394(%g)", &F1394->Guid);
620 }
621 
622 
623 
624 VOID
625 _DevPathUsb (
626     IN OUT POOL_PRINT       *Str,
627     IN VOID                 *DevPath
628     )
629 {
630     USB_DEVICE_PATH         *Usb;
631 
632     Usb = DevPath;
633     CatPrint(Str, L"Usb(%x)", Usb->Port);
634 }
635 
636 
637 VOID
638 _DevPathI2O (
639     IN OUT POOL_PRINT       *Str,
640     IN VOID                 *DevPath
641     )
642 {
643     I2O_DEVICE_PATH         *I2O;
644 
645     I2O = DevPath;
646     CatPrint(Str, L"I2O(%x)", I2O->Tid);
647 }
648 
649 VOID
650 _DevPathMacAddr (
651     IN OUT POOL_PRINT       *Str,
652     IN VOID                 *DevPath
653     )
654 {
655     MAC_ADDR_DEVICE_PATH    *MAC;
656     UINTN                   HwAddressSize;
657     UINTN                   Index;
658 
659     MAC = DevPath;
660 
661     HwAddressSize = sizeof(EFI_MAC_ADDRESS);
662     if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
663         HwAddressSize = 6;
664     }
665 
666     CatPrint(Str, L"Mac(");
667 
668     for(Index = 0; Index < HwAddressSize; Index++) {
669         CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
670     }
671     CatPrint(Str, L")");
672 }
673 
674 VOID
675 _DevPathIPv4 (
676     IN OUT POOL_PRINT       *Str,
677     IN VOID                 *DevPath
678     )
679 {
680     IPv4_DEVICE_PATH     *IP;
681 
682     IP = DevPath;
683     CatPrint(Str, L"IPv4(not-done)");
684 }
685 
686 VOID
687 _DevPathIPv6 (
688     IN OUT POOL_PRINT       *Str,
689     IN VOID                 *DevPath
690     )
691 {
692     IPv6_DEVICE_PATH     *IP;
693 
694     IP = DevPath;
695     CatPrint(Str, L"IP-v6(not-done)");
696 }
697 
698 VOID
699 _DevPathInfiniBand (
700     IN OUT POOL_PRINT       *Str,
701     IN VOID                 *DevPath
702     )
703 {
704     INFINIBAND_DEVICE_PATH  *InfiniBand;
705 
706     InfiniBand = DevPath;
707     CatPrint(Str, L"InfiniBand(not-done)");
708 }
709 
710 VOID
711 _DevPathUart (
712     IN OUT POOL_PRINT       *Str,
713     IN VOID                 *DevPath
714     )
715 {
716     UART_DEVICE_PATH  *Uart;
717     CHAR8             Parity;
718 
719     Uart = DevPath;
720     switch (Uart->Parity) {
721         case 0  : Parity = 'D'; break;
722         case 1  : Parity = 'N'; break;
723         case 2  : Parity = 'E'; break;
724         case 3  : Parity = 'O'; break;
725         case 4  : Parity = 'M'; break;
726         case 5  : Parity = 'S'; break;
727         default : Parity = 'x'; break;
728     }
729 
730     if (Uart->BaudRate == 0) {
731         CatPrint(Str, L"Uart(DEFAULT %c",Uart->BaudRate,Parity);
732     } else {
733         CatPrint(Str, L"Uart(%d %c",Uart->BaudRate,Parity);
734     }
735 
736     if (Uart->DataBits == 0) {
737         CatPrint(Str, L"D");
738     } else {
739         CatPrint(Str, L"%d",Uart->DataBits);
740     }
741 
742     switch (Uart->StopBits) {
743         case 0  : CatPrint(Str, L"D)");   break;
744         case 1  : CatPrint(Str, L"1)");   break;
745         case 2  : CatPrint(Str, L"1.5)"); break;
746         case 3  : CatPrint(Str, L"2)");   break;
747         default : CatPrint(Str, L"x)");   break;
748     }
749 }
750 
751 
752 VOID
753 _DevPathHardDrive (
754     IN OUT POOL_PRINT       *Str,
755     IN VOID                 *DevPath
756     )
757 {
758     HARDDRIVE_DEVICE_PATH   *Hd;
759 
760     Hd = DevPath;
761     switch (Hd->SignatureType) {
762         case SIGNATURE_TYPE_MBR:
763             CatPrint(Str, L"HD(Part%d,Sig%08X)",
764                 Hd->PartitionNumber,
765                 *((UINT32 *)(&(Hd->Signature[0])))
766                 );
767             break;
768         case SIGNATURE_TYPE_GUID:
769             CatPrint(Str, L"HD(Part%d,Sig%g)",
770                 Hd->PartitionNumber,
771                 (EFI_GUID *) &(Hd->Signature[0])
772                 );
773             break;
774         default:
775             CatPrint(Str, L"HD(Part%d,MBRType=%02x,SigType=%02x)",
776                 Hd->PartitionNumber,
777                 Hd->MBRType,
778                 Hd->SignatureType
779                 );
780             break;
781     }
782 }
783 
784 VOID
785 _DevPathCDROM (
786     IN OUT POOL_PRINT       *Str,
787     IN VOID                 *DevPath
788     )
789 {
790     CDROM_DEVICE_PATH       *Cd;
791 
792     Cd = DevPath;
793     CatPrint(Str, L"CDROM(Entry%x)", Cd->BootEntry);
794 }
795 
796 VOID
797 _DevPathFilePath (
798     IN OUT POOL_PRINT       *Str,
799     IN VOID                 *DevPath
800     )
801 {
802     FILEPATH_DEVICE_PATH    *Fp;
803 
804     Fp = DevPath;
805     CatPrint(Str, L"%s", Fp->PathName);
806 }
807 
808 VOID
809 _DevPathMediaProtocol (
810     IN OUT POOL_PRINT       *Str,
811     IN VOID                 *DevPath
812     )
813 {
814     MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
815 
816     MediaProt = DevPath;
817     CatPrint(Str, L"%g", &MediaProt->Protocol);
818 }
819 
820 VOID
821 _DevPathBssBss (
822     IN OUT POOL_PRINT       *Str,
823     IN VOID                 *DevPath
824     )
825 {
826     BBS_BBS_DEVICE_PATH     *Bss;
827     CHAR16                  *Type;
828 
829     Bss = DevPath;
830     switch (Bss->DeviceType) {
831     case BBS_TYPE_FLOPPY:               Type = L"Floppy";       break;
832     case BBS_TYPE_HARDDRIVE:            Type = L"Harddrive";    break;
833     case BBS_TYPE_CDROM:                Type = L"CDROM";        break;
834     case BBS_TYPE_PCMCIA:               Type = L"PCMCIA";       break;
835     case BBS_TYPE_USB:                  Type = L"Usb";          break;
836     case BBS_TYPE_EMBEDDED_NETWORK:     Type = L"Net";          break;
837     default:                            Type = L"?";            break;
838     }
839 
840     CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
841 }
842 
843 
844 VOID
845 _DevPathEndInstance (
846     IN OUT POOL_PRINT       *Str,
847     IN VOID                 *DevPath
848     )
849 {
850     CatPrint(Str, L",");
851 }
852 
853 VOID
854 _DevPathNodeUnknown (
855     IN OUT POOL_PRINT       *Str,
856     IN VOID                 *DevPath
857     )
858 {
859     CatPrint(Str, L"?");
860 }
861 
862 
863 struct {
864     UINT8   Type;
865     UINT8   SubType;
866     VOID    (*Function)(POOL_PRINT *, VOID *);
867 } DevPathTable[] = {
868 	{ HARDWARE_DEVICE_PATH,   HW_PCI_DP,                        _DevPathPci},
869 	{ HARDWARE_DEVICE_PATH,   HW_PCCARD_DP,                     _DevPathPccard},
870 	{ HARDWARE_DEVICE_PATH,   HW_MEMMAP_DP,                     _DevPathMemMap},
871 	{ HARDWARE_DEVICE_PATH,   HW_VENDOR_DP,                     _DevPathVendor},
872 	{ HARDWARE_DEVICE_PATH,   HW_CONTROLLER_DP,                 _DevPathController},
873 	{ ACPI_DEVICE_PATH,       ACPI_DP,                          _DevPathAcpi},
874 	{ MESSAGING_DEVICE_PATH,  MSG_ATAPI_DP,                     _DevPathAtapi},
875 	{ MESSAGING_DEVICE_PATH,  MSG_SCSI_DP,                      _DevPathScsi},
876 	{ MESSAGING_DEVICE_PATH,  MSG_FIBRECHANNEL_DP,              _DevPathFibre},
877 	{ MESSAGING_DEVICE_PATH,  MSG_1394_DP,                      _DevPath1394},
878 	{ MESSAGING_DEVICE_PATH,  MSG_USB_DP,                       _DevPathUsb},
879 	{ MESSAGING_DEVICE_PATH,  MSG_I2O_DP,                       _DevPathI2O},
880 	{ MESSAGING_DEVICE_PATH,  MSG_MAC_ADDR_DP,                  _DevPathMacAddr},
881 	{ MESSAGING_DEVICE_PATH,  MSG_IPv4_DP,                      _DevPathIPv4},
882 	{ MESSAGING_DEVICE_PATH,  MSG_IPv6_DP,                      _DevPathIPv6},
883 	{ MESSAGING_DEVICE_PATH,  MSG_INFINIBAND_DP,                _DevPathInfiniBand},
884 	{ MESSAGING_DEVICE_PATH,  MSG_UART_DP,                      _DevPathUart},
885 	{ MESSAGING_DEVICE_PATH,  MSG_VENDOR_DP,                    _DevPathVendor},
886 	{ MEDIA_DEVICE_PATH,      MEDIA_HARDDRIVE_DP,               _DevPathHardDrive},
887 	{ MEDIA_DEVICE_PATH,      MEDIA_CDROM_DP,                   _DevPathCDROM},
888 	{ MEDIA_DEVICE_PATH,      MEDIA_VENDOR_DP,                  _DevPathVendor},
889 	{ MEDIA_DEVICE_PATH,      MEDIA_FILEPATH_DP,                _DevPathFilePath},
890 	{ MEDIA_DEVICE_PATH,      MEDIA_PROTOCOL_DP,                _DevPathMediaProtocol},
891 	{ BBS_DEVICE_PATH,        BBS_BBS_DP,                       _DevPathBssBss},
892 	{ END_DEVICE_PATH_TYPE,   END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
893 	{ 0,                      0,                          NULL}
894 };
895 
896 
897 CHAR16 *
898 DevicePathToStr (
899     EFI_DEVICE_PATH     *DevPath
900     )
901 /*++
902 
903     Turns the Device Path into a printable string.  Allcoates
904     the string from pool.  The caller must FreePool the returned
905     string.
906 
907 --*/
908 {
909     POOL_PRINT          Str;
910     EFI_DEVICE_PATH     *DevPathNode;
911     VOID                (*DumpNode)(POOL_PRINT *, VOID *);
912     UINTN               Index, NewSize;
913 
914     ZeroMem(&Str, sizeof(Str));
915 
916     //
917     // Unpacked the device path
918     //
919 
920     DevPath = UnpackDevicePath(DevPath);
921     ASSERT (DevPath);
922 
923 
924     //
925     // Process each device path node
926     //
927 
928     DevPathNode = DevPath;
929     while (!IsDevicePathEnd(DevPathNode)) {
930         //
931         // Find the handler to dump this device path node
932         //
933 
934         DumpNode = NULL;
935         for (Index = 0; DevPathTable[Index].Function; Index += 1) {
936 
937             if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
938                 DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
939                 DumpNode = DevPathTable[Index].Function;
940                 break;
941             }
942         }
943 
944         //
945         // If not found, use a generic function
946         //
947 
948         if (!DumpNode) {
949             DumpNode = _DevPathNodeUnknown;
950         }
951 
952         //
953         //  Put a path seperator in if needed
954         //
955 
956         if (Str.len  &&  DumpNode != _DevPathEndInstance) {
957             CatPrint (&Str, L"/");
958         }
959 
960         //
961         // Print this node of the device path
962         //
963 
964         DumpNode (&Str, DevPathNode);
965 
966         //
967         // Next device path node
968         //
969 
970         DevPathNode = NextDevicePathNode(DevPathNode);
971     }
972 
973     //
974     // Shrink pool used for string allocation
975     //
976 
977     FreePool (DevPath);
978     NewSize = (Str.len + 1) * sizeof(CHAR16);
979     Str.str = ReallocatePool (Str.str, NewSize, NewSize);
980     Str.str[Str.len] = 0;
981     return Str.str;
982 }
983 
984 BOOLEAN
985 LibMatchDevicePaths (
986     IN  EFI_DEVICE_PATH *Multi,
987     IN  EFI_DEVICE_PATH *Single
988     )
989 {
990     EFI_DEVICE_PATH     *DevicePath, *DevicePathInst;
991     UINTN               Size;
992 
993     if (!Multi || !Single) {
994         return FALSE;
995     }
996 
997     DevicePath = Multi;
998     while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
999         if (CompareMem (Single, DevicePathInst, Size) == 0) {
1000             return TRUE;
1001         }
1002     }
1003     return FALSE;
1004 }
1005 
1006 EFI_DEVICE_PATH *
1007 LibDuplicateDevicePathInstance (
1008     IN EFI_DEVICE_PATH  *DevPath
1009     )
1010 {
1011     EFI_DEVICE_PATH     *NewDevPath,*DevicePathInst,*Temp;
1012     UINTN               Size;
1013 
1014     //
1015     // get the size of an instance from the input
1016     //
1017 
1018     Temp = DevPath;
1019     DevicePathInst = DevicePathInstance (&Temp, &Size);
1020 
1021     //
1022     // Make a copy and set proper end type
1023     //
1024     NewDevPath = NULL;
1025     if (Size) {
1026         NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
1027     }
1028 
1029     if (NewDevPath) {
1030         CopyMem (NewDevPath, DevicePathInst, Size);
1031         Temp = NextDevicePathNode(NewDevPath);
1032         SetDevicePathEndNode(Temp);
1033     }
1034 
1035     return NewDevPath;
1036 }
1037 
1038