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