SHEL19
[efi/shell/.git] / Library / DPath.c
1 /*++
2
3 Copyright (c) 2005 - 2008, Intel Corporation                                                         
4 All rights reserved. This program and the accompanying materials                          
5 are licensed and made available under the terms and conditions of the BSD License         
6 which accompanies this distribution. The full text of the license may be found at         
7 http://opensource.org/licenses/bsd-license.php                                            
8                                                                                           
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
11
12 Module Name:
13
14     DPath.c
15
16 Abstract:
17     Device Path functions
18
19 Revision History
20
21 --*/
22
23 #include "EfiShelllib.h"
24
25 EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid = DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL;
26
27 EFI_GUID mEfiDevicePathMessagingSASGuid = DEVICE_PATH_MESSAGING_SAS;
28
29 EFI_DEVICE_PATH_PROTOCOL *
30 DevicePathInstance (
31   IN OUT EFI_DEVICE_PATH_PROTOCOL             **DevicePath,
32   OUT UINTN                                   *Size
33   )
34 /*++
35
36 Routine Description:
37   Function retrieves the next device path instance from a device path data structure.
38
39 Arguments:
40   DevicePath           - A pointer to a device path data structure.
41
42   Size                 - A pointer to the size of a device path instance in bytes.
43
44 Returns:
45
46   This function returns a pointer to the current device path instance.  
47   In addition, it returns the size in bytes of the current device path instance in Size, 
48   and a pointer to the next device path instance in DevicePath.  
49   If there are no more device path instances in DevicePath, then DevicePath will be set to NULL.
50
51 --*/
52 {
53   EFI_DEVICE_PATH_PROTOCOL  *Start;
54   EFI_DEVICE_PATH_PROTOCOL  *Next;
55   EFI_DEVICE_PATH_PROTOCOL  *DevPath;
56   UINTN                     Count;
57
58   ASSERT (Size);
59
60   DevPath = *DevicePath;
61   Start   = DevPath;
62
63   if (!DevPath) {
64     return NULL;
65   }
66   //
67   // Check for end of device path type
68   //
69   for (Count = 0;; Count++) {
70     Next = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevPath);
71
72     if (IsDevicePathEndType (DevPath)) {
73       break;
74     }
75
76     if (Count > 01000) {
77       DEBUG (
78         (
79         EFI_D_ERROR, "DevicePathInstance Too Long : DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) -
80         ((UINT8 *) Start)
81         )
82         );
83       DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
84       break;
85     }
86
87     DevPath = Next;
88   }
89
90   ASSERT (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE || DevicePathSubType (DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
91
92   //
93   // Set next position
94   //
95   if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
96     Next = NULL;
97   }
98
99   *DevicePath = Next;
100
101   //
102   // Return size and start of device path instance
103   //
104   *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
105   return Start;
106 }
107
108 UINTN
109 DevicePathInstanceCount (
110   IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath
111   )
112 /*++
113
114 Routine Description:
115   Function is used to determine the number of device path instances that exist in a device path.
116
117 Arguments:
118   DevicePath           - A pointer to a device path data structure.
119
120 Returns:
121
122   This function counts and returns the number of device path instances in DevicePath.
123
124 --*/
125 {
126   UINTN Count;
127   UINTN Size;
128
129   Count = 0;
130   while (DevicePathInstance (&DevicePath, &Size)) {
131     Count += 1;
132   }
133
134   return Count;
135 }
136
137 EFI_DEVICE_PATH_PROTOCOL *
138 AppendDevicePath (
139   IN EFI_DEVICE_PATH_PROTOCOL  *Src1,
140   IN EFI_DEVICE_PATH_PROTOCOL  *Src2
141   )
142 /*++
143
144 Routine Description:
145   Function is used to append a device path to all the instances in another device path.
146
147 Arguments:
148   Src1           - A pointer to a device path data structure.
149
150   Src2           - A pointer to a device path data structure.
151
152 Returns:
153
154   A pointer to the new device path is returned.  
155   NULL is returned if space for the new device path could not be allocated from pool. 
156   It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
157
158   Src1 may have multiple "instances" and each instance is appended
159   Src2 is appended to each instance is Src1.  (E.g., it's possible
160   to append a new instance to the complete device path by passing 
161   it in Src2)
162
163 --*/
164 {
165   UINTN                     Src1Size;
166   UINTN                     Src1Inst;
167   UINTN                     Src2Size;
168   UINTN                     Size;
169   EFI_DEVICE_PATH_PROTOCOL  *Dst;
170   EFI_DEVICE_PATH_PROTOCOL  *Inst;
171   UINT8                     *DstPos;
172
173   //
174   // If there's only 1 path, just duplicate it
175   //
176   if (!Src1) {
177     ASSERT (!IsDevicePathUnpacked (Src2));
178     return DuplicateDevicePath (Src2);
179   }
180
181   if (!Src2) {
182     ASSERT (!IsDevicePathUnpacked (Src1));
183     return DuplicateDevicePath (Src1);
184   }
185   //
186   // Verify we're not working with unpacked paths
187   //
188   //
189   // Append Src2 to every instance in Src1
190   //
191   Src1Size  = DevicePathSize (Src1);
192   Src1Inst  = DevicePathInstanceCount (Src1);
193   Src2Size  = DevicePathSize (Src2);
194   Size      = Src2Size * Src1Inst + Src1Size;
195   Size -= Src1Inst * sizeof (EFI_DEVICE_PATH_PROTOCOL);
196
197   Dst = AllocatePool (Size);
198   if (Dst) {
199     DstPos = (UINT8 *) Dst;
200
201     //
202     // Copy all device path instances
203     //
204     Inst = DevicePathInstance (&Src1, &Size);
205     while (Inst) {
206
207       CopyMem (DstPos, Inst, Size);
208       DstPos += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);
209
210       CopyMem (DstPos, Src2, Src2Size);
211       DstPos += Src2Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);
212
213       SetDevicePathEndNode ((EFI_DEVICE_PATH_PROTOCOL *)DstPos);
214       ((EFI_DEVICE_PATH_PROTOCOL *)DstPos)->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; 
215       DstPos += sizeof (EFI_DEVICE_PATH_PROTOCOL);
216
217       Inst = DevicePathInstance (&Src1, &Size);
218     }
219     //
220     // Change last end marker
221     //
222     DstPos -= sizeof (EFI_DEVICE_PATH_PROTOCOL);
223     SetDevicePathEndNode ((EFI_DEVICE_PATH_PROTOCOL *)DstPos);
224   }
225
226   return Dst;
227 }
228
229 UINTN
230 DevicePathSize (
231   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
232   )
233 /*++
234
235 Routine Description:
236   Function returns the size of a device path in bytes.
237
238 Arguments:
239   DevPath        - A pointer to a device path data structure
240
241 Returns:
242
243   Size is returned.
244
245 --*/
246 {
247   EFI_DEVICE_PATH_PROTOCOL  *Start;
248
249   ASSERT (DevPath != NULL);
250
251   //
252   // Search for the end of the device path structure
253   //
254   Start = DevPath;
255   while (!IsDevicePathEnd (DevPath)) {
256     DevPath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevPath);
257   }
258   //
259   // Compute the size
260   //
261   return ((UINTN) DevPath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
262 }
263
264 EFI_DEVICE_PATH_PROTOCOL *
265 DevicePathFromHandle (
266   IN EFI_HANDLE       Handle
267   )
268 /*++
269
270 Routine Description:
271   Function retrieves the device path for the specified handle.  
272
273 Arguments:
274   Handle           - Handle of the device
275
276 Returns:
277
278   If Handle is valid, then a pointer to the device path is returned.  
279   If Handle is not valid, then NULL is returned.
280
281 --*/
282 {
283   EFI_STATUS                Status;
284   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
285
286   Status = BS->HandleProtocol (
287                 Handle,
288                 &gEfiDevicePathProtocolGuid,
289                 (VOID *) &DevicePath
290                 );
291
292   if (EFI_ERROR (Status)) {
293     DevicePath = NULL;
294   }
295
296   return DevicePath;
297 }
298
299 EFI_DEVICE_PATH_PROTOCOL *
300 DuplicateDevicePath (
301   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
302   )
303 /*++
304
305 Routine Description:
306   Function creates a duplicate copy of an existing device path.
307
308 Arguments:
309   DevPath        - A pointer to a device path data structure
310
311 Returns:
312
313   If the memory is successfully allocated, then the contents of DevPath are copied 
314   to the newly allocated buffer, and a pointer to that buffer is returned.  
315   Otherwise, NULL is returned.
316
317 --*/
318 {
319   EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;
320   UINTN                     Size;
321
322   ASSERT (DevPath);
323
324   //
325   // Compute the size
326   //
327   Size = DevicePathSize (DevPath);
328
329   //
330   // Make a copy
331   //
332   NewDevPath = AllocatePool (Size);
333   if (NewDevPath != NULL) {
334     CopyMem (NewDevPath, DevPath, Size);
335   }
336
337   return NewDevPath;
338 }
339
340 EFI_DEVICE_PATH_PROTOCOL *
341 UnpackDevicePath (
342   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
343   )
344 /*++
345
346 Routine Description:
347   Function unpacks a device path data structure so that all the nodes of a device path 
348   are naturally aligned.
349
350 Arguments:
351   DevPath        - A pointer to a device path data structure
352
353 Returns:
354
355   If the memory for the device path is successfully allocated, then a pointer to the 
356   new device path is returned.  Otherwise, NULL is returned.
357
358 --*/
359 {
360   EFI_DEVICE_PATH_PROTOCOL  *Src;
361   EFI_DEVICE_PATH_PROTOCOL  *Dest;
362   EFI_DEVICE_PATH_PROTOCOL  *NewPath;
363   UINTN                     Size;
364
365   if (DevPath == NULL) {
366     return NULL;
367   }
368   //
369   // Walk device path and round sizes to valid boundries
370   //
371   Src   = DevPath;
372   Size  = 0;
373   for (;;) {
374     Size += DevicePathNodeLength (Src);
375     Size += ALIGN_SIZE (Size);
376
377     if (IsDevicePathEnd (Src)) {
378       break;
379     }
380
381     Src = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (Src);
382   }
383   //
384   // Allocate space for the unpacked path
385   //
386   NewPath = AllocateZeroPool (Size);
387   if (NewPath != NULL) {
388
389     ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);
390
391     //
392     // Copy each node
393     //
394     Src   = DevPath;
395     Dest  = NewPath;
396     for (;;) {
397       Size = DevicePathNodeLength (Src);
398       CopyMem (Dest, Src, Size);
399       Size += ALIGN_SIZE (Size);
400       SetDevicePathNodeLength (Dest, Size);
401       Dest->Type |= EFI_DP_TYPE_UNPACKED;
402       Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);
403
404       if (IsDevicePathEnd (Src)) {
405         break;
406       }
407
408       Src = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (Src);
409     }
410   }
411
412   return NewPath;
413 }
414
415 VOID
416 _DevPathPci (
417   IN OUT POOL_PRINT       *Str,
418   IN VOID                 *DevPath
419   )
420 {
421   PCI_DEVICE_PATH *Pci;
422
423   ASSERT (Str != NULL);
424   ASSERT (DevPath != NULL);
425
426   Pci = DevPath;
427   CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);
428 }
429
430 VOID
431 _DevPathPccard (
432   IN OUT POOL_PRINT       *Str,
433   IN VOID                 *DevPath
434   )
435 {
436   PCCARD_DEVICE_PATH  *Pccard;
437
438   ASSERT (Str != NULL);
439   ASSERT (DevPath != NULL);
440
441   Pccard = DevPath;
442   CatPrint (Str, L"Pccard(Function%x)", (UINTN) Pccard->FunctionNumber);
443 }
444
445 VOID
446 _DevPathMemMap (
447   IN OUT POOL_PRINT       *Str,
448   IN VOID                 *DevPath
449   )
450 {
451   MEMMAP_DEVICE_PATH  *MemMap;
452
453   ASSERT (Str != NULL);
454   ASSERT (DevPath != NULL);
455
456   MemMap = DevPath;
457   CatPrint (
458     Str,
459     L"MemMap(%d:%lx-%lx)",
460     (UINTN) MemMap->MemoryType,
461     MemMap->StartingAddress,
462     MemMap->EndingAddress
463     );
464 }
465
466 VOID
467 _DevPathController (
468   IN OUT POOL_PRINT       *Str,
469   IN VOID                 *DevPath
470   )
471 {
472   CONTROLLER_DEVICE_PATH  *Controller;
473
474   ASSERT (Str != NULL);
475   ASSERT (DevPath != NULL);
476
477   Controller = DevPath;
478   CatPrint (
479     Str,
480     L"Ctrl(%d)",
481     (UINTN) Controller->Controller
482     );
483 }
484
485 VOID
486 _DevPathVendor (
487   IN OUT POOL_PRINT       *Str,
488   IN VOID                 *DevPath
489   )
490 {
491   VENDOR_DEVICE_PATH  *Vendor;
492   CHAR16              *Type;
493   UINTN               DataLength;
494   UINTN               Index;
495   UINT32              FlowControlMap;
496   UINT16              Info;
497
498   ASSERT (Str != NULL);
499   ASSERT (DevPath != NULL);
500
501   Vendor = DevPath;
502   switch (DevicePathType (&Vendor->Header)) {
503   case HARDWARE_DEVICE_PATH:
504     Type = L"Hw";
505     break;
506
507   case MESSAGING_DEVICE_PATH:
508     Type = L"Msg";
509     if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid) == 0) {
510       CatPrint (Str, L"VenPcAnsi()");
511       return ;
512     } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid) == 0) {
513       CatPrint (Str, L"VenVt100()");
514       return ;
515     } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid) == 0) {
516       CatPrint (Str, L"VenVt100Plus()");
517       return ;
518     } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid) == 0) {
519       CatPrint (Str, L"VenUft8()");
520       return ;
521     } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingUartFlowControlGuid) == 0) {
522       FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);
523       switch (FlowControlMap & 0x00000003) {
524       case 0:
525         CatPrint (Str, L"UartFlowCtrl(%s)", L"None");
526         break;
527
528       case 1:
529         CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");
530         break;
531
532       case 2:
533         CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");
534         break;
535
536       default:
537         break;
538       }
539
540       return ;
541     } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingSASGuid) == 0) {
542       CatPrint (
543         Str,
544         L"SAS(%lx,%lx,%x,",
545         ((SAS_DEVICE_PATH *) Vendor)->SasAddress,
546         ((SAS_DEVICE_PATH *) Vendor)->Lun,
547         (UINTN) ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
548         );
549       Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
550       if ((Info & 0x0f) == 0) {
551         CatPrint (Str, L"NoTopology,0,0,0,");
552       } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {
553         CatPrint (
554           Str,
555           L"%s,%s,%s,",
556           (Info & (0x1 << 4)) ? L"SATA" : L"SAS",
557           (Info & (0x1 << 5)) ? L"External" : L"Internal",
558           (Info & (0x1 << 6)) ? L"Expanded" : L"Direct"
559           );
560         if ((Info & 0x0f) == 1) {
561           CatPrint (Str, L"0,");
562         } else {
563           CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff));
564         }
565       } else {
566         CatPrint (Str, L"0,0,0,0,");
567       }
568
569       CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);
570       return ;
571     } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid) == 0) {
572       CatPrint (Str, L"DebugPort()");
573       return ;
574     }
575     break;
576
577   case MEDIA_DEVICE_PATH:
578     Type = L"Media";
579     break;
580
581   default:
582     Type = L"?";
583     break;
584   }
585
586   CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);
587   DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);
588   if (DataLength > 0) {
589     CatPrint (Str, L",");
590     for (Index = 0; Index < DataLength; Index++) {
591       CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);
592     }
593   }
594   CatPrint (Str, L")");
595 }
596
597 VOID
598 _DevPathAcpi (
599   IN OUT POOL_PRINT       *Str,
600   IN VOID                 *DevPath
601   )
602 {
603   ACPI_HID_DEVICE_PATH  *Acpi;
604
605   ASSERT (Str != NULL);
606   ASSERT (DevPath != NULL);
607
608   Acpi = DevPath;
609   if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
610     CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN) EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);
611   } else {
612     CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);
613   }
614 }
615
616 VOID
617 _DevPathExtendedAcpi (
618   IN OUT POOL_PRINT       *Str,
619   IN VOID                 *DevPath
620   )
621 {
622   ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR   *ExtendedAcpi;
623   //
624   // HID, UID and CID strings
625   //
626   CHAR8     *HIDString;
627   CHAR8     *UIDString;
628   CHAR8     *CIDString;
629
630
631   ASSERT (Str != NULL);
632   ASSERT (DevPath != NULL);
633   ASSERT (DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) DevPath) >=
634           sizeof (ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR));
635
636   ExtendedAcpi = (ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *) DevPath;
637
638   HIDString = ExtendedAcpi->HidUidCidStr;
639   UIDString = NextStrA (HIDString);
640   CIDString = NextStrA (UIDString);
641
642   CatPrint (Str, L"AcpiEx(");
643   if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
644     CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));
645   } else {
646     CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);
647   }
648   if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
649     CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));
650   } else {
651     CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);
652   }
653   CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID);
654
655   if (*HIDString != '\0') {
656     CatPrint (Str, L"%a,", HIDString);
657   } else {
658     CatPrint (Str, L"NULL,");
659   }
660   if (*CIDString != '\0') {
661     CatPrint (Str, L"%a,", CIDString);
662   } else {
663     CatPrint (Str, L"NULL,");
664   }
665   if (*UIDString != '\0') {
666     CatPrint (Str, L"%a)", UIDString);
667   } else {
668     CatPrint (Str, L"NULL)");
669   }
670 }
671
672 VOID
673 _DevPathAdrAcpi (
674   IN OUT POOL_PRINT       *Str,
675   IN VOID                 *DevPath
676   )
677 {
678   ACPI_ADR_DEVICE_PATH    *AcpiAdr;
679   UINT16                  Index;
680   UINT16                  Length;
681   UINT16                  AdditionalAdrCount;
682
683   AcpiAdr            = DevPath;
684   Length             = DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);
685   AdditionalAdrCount = (Length - 8) / 4;
686
687   CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR);
688   for (Index = 0; Index < AdditionalAdrCount; Index++) {
689     CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));
690   }
691   CatPrint (Str, L")");
692 }
693
694 VOID
695 _DevPathAtapi (
696   IN OUT POOL_PRINT       *Str,
697   IN VOID                 *DevPath
698   )
699 {
700   ATAPI_DEVICE_PATH *Atapi;
701
702   ASSERT (Str != NULL);
703   ASSERT (DevPath != NULL);
704
705   Atapi = DevPath;
706   CatPrint (
707     Str,
708     L"Ata(%s,%s)",
709     Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
710     Atapi->SlaveMaster ? L"Slave" : L"Master"
711     );
712 }
713
714 VOID
715 _DevPathScsi (
716   IN OUT POOL_PRINT       *Str,
717   IN VOID                 *DevPath
718   )
719 {
720   SCSI_DEVICE_PATH  *Scsi;
721
722   ASSERT (Str != NULL);
723   ASSERT (DevPath != NULL);
724
725   Scsi = DevPath;
726   CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);
727 }
728
729 VOID
730 _DevPathFibre (
731   IN OUT POOL_PRINT       *Str,
732   IN VOID                 *DevPath
733   )
734 {
735   FIBRECHANNEL_DEVICE_PATH  *Fibre;
736
737   ASSERT (Str != NULL);
738   ASSERT (DevPath != NULL);
739
740   Fibre = DevPath;
741   CatPrint (Str, L"Fibre(Wwn%lx,Lun%lx)", Fibre->WWN, Fibre->Lun);
742 }
743
744 VOID
745 _DevPath1394 (
746   IN OUT POOL_PRINT       *Str,
747   IN VOID                 *DevPath
748   )
749 {
750   F1394_DEVICE_PATH *F1394;
751   
752   ASSERT (Str != NULL);
753   ASSERT (DevPath != NULL);
754
755   F1394 = DevPath;
756   CatPrint (Str, L"1394(%lx)", &F1394->Guid);
757 }
758
759 VOID
760 _DevPathUsb (
761   IN OUT POOL_PRINT       *Str,
762   IN VOID                 *DevPath
763   )
764 {
765   USB_DEVICE_PATH *Usb;
766
767   ASSERT (Str != NULL);
768   ASSERT (DevPath != NULL);
769
770   Usb = DevPath;
771   CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber);
772 }
773
774 VOID
775 _DevPathUsbWWID (
776   IN OUT POOL_PRINT       *Str,
777   IN VOID                 *DevPath
778   )
779 {
780   USB_WWID_DEVICE_PATH  *UsbWWId;
781
782   ASSERT (Str != NULL);
783   ASSERT (DevPath != NULL);
784
785   UsbWWId = DevPath;
786   CatPrint (
787     Str,
788     L"UsbWwid(%x,%x,%x,\"WWID\")",
789     (UINTN) UsbWWId->VendorId,
790     (UINTN) UsbWWId->ProductId,
791     (UINTN) UsbWWId->InterfaceNumber
792     );
793 }
794
795 VOID
796 _DevPathLogicalUnit (
797   IN OUT POOL_PRINT       *Str,
798   IN VOID                 *DevPath
799   )
800 {
801   DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
802
803   ASSERT (Str != NULL);
804   ASSERT (DevPath != NULL);
805
806   LogicalUnit = DevPath;
807   CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun);
808 }
809
810 VOID
811 _DevPathUsbClass (
812   IN OUT POOL_PRINT       *Str,
813   IN VOID                 *DevPath
814   )
815 {
816   USB_CLASS_DEVICE_PATH *UsbClass;
817
818   ASSERT (Str != NULL);
819   ASSERT (DevPath != NULL);
820
821   UsbClass = DevPath;
822   CatPrint (
823     Str,
824     L"Usb Class(%x,%x,%x,%x,%x)",
825     (UINTN) UsbClass->VendorId,
826     (UINTN) UsbClass->ProductId,
827     (UINTN) UsbClass->DeviceClass,
828     (UINTN) UsbClass->DeviceSubClass,
829     (UINTN) UsbClass->DeviceProtocol
830     );
831 }
832
833 VOID
834 _DevPathSata (
835   IN OUT POOL_PRINT       *Str,
836   IN VOID                 *DevPath
837   )
838 {
839   SATA_DEVICE_PATH *Sata;
840
841   ASSERT (Str != NULL);
842   ASSERT (DevPath != NULL);
843
844   Sata = DevPath;
845   if (Sata->PortMultiplierPortNumber & SATA_HBA_DIRECT_CONNECT_FLAG) {
846     CatPrint (
847       Str,
848       L"Sata(%x,%x)",
849       (UINTN) Sata->HBAPortNumber,
850       (UINTN) Sata->Lun
851       );
852   } else {
853     CatPrint (
854       Str,
855       L"Sata(%x,%x,%x)",
856       (UINTN) Sata->HBAPortNumber,
857       (UINTN) Sata->PortMultiplierPortNumber,
858       (UINTN) Sata->Lun
859       );
860   }
861 }
862
863 VOID
864 _DevPathI2O (
865   IN OUT POOL_PRINT       *Str,
866   IN VOID                 *DevPath
867   )
868 {
869   I2O_DEVICE_PATH *I2O;
870
871   ASSERT (Str != NULL);
872   ASSERT (DevPath != NULL);
873
874   I2O = DevPath;
875   CatPrint (Str, L"I2O(%x)", (UINTN) I2O->Tid);
876 }
877
878 VOID
879 _DevPathMacAddr (
880   IN OUT POOL_PRINT       *Str,
881   IN VOID                 *DevPath
882   )
883 {
884   MAC_ADDR_DEVICE_PATH  *MAC;
885   UINTN                 HwAddressSize;
886   UINTN                 Index;
887
888   ASSERT (Str != NULL);
889   ASSERT (DevPath != NULL);
890
891   MAC           = DevPath;
892
893   HwAddressSize = sizeof (EFI_MAC_ADDRESS);
894   if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
895     HwAddressSize = 6;
896   }
897
898   CatPrint (Str, L"Mac(");
899
900   for (Index = 0; Index < HwAddressSize; Index++) {
901     CatPrint (Str, L"%02x", (UINTN) MAC->MacAddress.Addr[Index]);
902   }
903
904   CatPrint (Str, L")");
905 }
906
907 VOID
908 _DevPathIPv4 (
909   IN OUT POOL_PRINT       *Str,
910   IN VOID                 *DevPath
911   )
912 {
913   IPv4_DEVICE_PATH  *IP;
914
915   ASSERT (Str != NULL);
916   ASSERT (DevPath != NULL);
917
918   IP = DevPath;
919   CatPrint (
920     Str,
921     L"IPv4(%d.%d.%d.%d:%d)",
922     (UINTN) IP->RemoteIpAddress.Addr[0],
923     (UINTN) IP->RemoteIpAddress.Addr[1],
924     (UINTN) IP->RemoteIpAddress.Addr[2],
925     (UINTN) IP->RemoteIpAddress.Addr[3],
926     (UINTN) IP->RemotePort
927     );
928 }
929
930 VOID
931 _DevPathIPv6 (
932   IN OUT POOL_PRINT       *Str,
933   IN VOID                 *DevPath
934   )
935 {
936   IPv6_DEVICE_PATH  *IP;
937
938   ASSERT (Str != NULL);
939
940   IP = DevPath;
941   CatPrint (
942     Str,
943     L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",
944     (UINTN) IP->RemoteIpAddress.Addr[0],
945     (UINTN) IP->RemoteIpAddress.Addr[1],
946     (UINTN) IP->RemoteIpAddress.Addr[2],
947     (UINTN) IP->RemoteIpAddress.Addr[3],
948     (UINTN) IP->RemoteIpAddress.Addr[4],
949     (UINTN) IP->RemoteIpAddress.Addr[5],
950     (UINTN) IP->RemoteIpAddress.Addr[6],
951     (UINTN) IP->RemoteIpAddress.Addr[7],
952     (UINTN) IP->RemoteIpAddress.Addr[8],
953     (UINTN) IP->RemoteIpAddress.Addr[9],
954     (UINTN) IP->RemoteIpAddress.Addr[10],
955     (UINTN) IP->RemoteIpAddress.Addr[11],
956     (UINTN) IP->RemoteIpAddress.Addr[12],
957     (UINTN) IP->RemoteIpAddress.Addr[13],
958     (UINTN) IP->RemoteIpAddress.Addr[14],
959     (UINTN) IP->RemoteIpAddress.Addr[15]
960     );
961 }
962
963 VOID
964 _DevPathInfiniBand (
965   IN OUT POOL_PRINT       *Str,
966   IN VOID                 *DevPath
967   )
968 {
969   INFINIBAND_DEVICE_PATH  *InfiniBand;
970
971   ASSERT (Str != NULL);
972
973   InfiniBand = DevPath;
974   CatPrint (
975     Str,
976     L"Infiniband(%x,%g,%lx,%lx,%lx)",
977     (UINTN) InfiniBand->ResourceFlags,
978     InfiniBand->PortGid,
979     InfiniBand->ServiceId,
980     InfiniBand->TargetPortId,
981     InfiniBand->DeviceId
982     );
983 }
984
985 VOID
986 _DevPathUart (
987   IN OUT POOL_PRINT       *Str,
988   IN VOID                 *DevPath
989   )
990 {
991   UART_DEVICE_PATH  *Uart;
992   CHAR8             Parity;
993
994   ASSERT (Str != NULL);
995   ASSERT (DevPath != NULL);
996
997   Uart = DevPath;
998   switch (Uart->Parity) {
999   case 0:
1000     Parity = 'D';
1001     break;
1002
1003   case 1:
1004     Parity = 'N';
1005     break;
1006
1007   case 2:
1008     Parity = 'E';
1009     break;
1010
1011   case 3:
1012     Parity = 'O';
1013     break;
1014
1015   case 4:
1016     Parity = 'M';
1017     break;
1018
1019   case 5:
1020     Parity = 'S';
1021     break;
1022
1023   default:
1024     Parity = 'x';
1025     break;
1026   }
1027
1028   if (Uart->BaudRate == 0) {
1029     CatPrint (Str, L"Uart(DEFAULT,%c,", Parity);
1030   } else {
1031     CatPrint (Str, L"Uart(%ld,%c,", Uart->BaudRate, Parity);
1032   }
1033
1034   if (Uart->DataBits == 0) {
1035     CatPrint (Str, L"D,");
1036   } else {
1037     CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);
1038   }
1039
1040   switch (Uart->StopBits) {
1041   case 0:
1042     CatPrint (Str, L"D)");
1043     break;
1044
1045   case 1:
1046     CatPrint (Str, L"1)");
1047     break;
1048
1049   case 2:
1050     CatPrint (Str, L"1.5)");
1051     break;
1052
1053   case 3:
1054     CatPrint (Str, L"2)");
1055     break;
1056
1057   default:
1058     CatPrint (Str, L"x)");
1059     break;
1060   }
1061 }
1062
1063 VOID
1064 _DevPathiSCSI (
1065   IN OUT POOL_PRINT       *Str,
1066   IN VOID                 *DevPath
1067   )
1068 {
1069   ISCSI_DEVICE_PATH_WITH_NAME *iSCSI;
1070   UINT16                      Options;
1071
1072   ASSERT (Str != NULL);
1073   ASSERT (DevPath != NULL);
1074
1075   iSCSI = DevPath;
1076   CatPrint (
1077     Str,
1078     L"iSCSI(%a,%x,%lx,",
1079     iSCSI->iSCSITargetName,
1080     (UINTN) iSCSI->TargetPortalGroupTag,
1081     iSCSI->Lun
1082     );
1083
1084   Options = iSCSI->LoginOption;
1085   CatPrint (Str, L"%s,", ((Options >> 1) & 0x0001) ? L"CRC32C" : L"None");
1086   CatPrint (Str, L"%s,", ((Options >> 3) & 0x0001) ? L"CRC32C" : L"None");
1087   if ((Options >> 11) & 0x0001) {
1088     CatPrint (Str, L"%s,", L"None");
1089   } else if ((Options >> 12) & 0x0001) {
1090     CatPrint (Str, L"%s,", L"CHAP_UNI");
1091   } else {
1092     CatPrint (Str, L"%s,", L"CHAP_BI");
1093
1094   }
1095
1096   CatPrint (Str, L"%s)", (iSCSI->NetworkProtocol == 0) ? L"TCP" : L"reserved");
1097 }
1098
1099 VOID
1100 _DevPathHardDrive (
1101   IN OUT POOL_PRINT       *Str,
1102   IN VOID                 *DevPath
1103   )
1104 {
1105   HARDDRIVE_DEVICE_PATH *Hd;
1106
1107   ASSERT (Str != NULL);
1108   ASSERT (DevPath != NULL);
1109
1110   Hd = DevPath;
1111   switch (Hd->SignatureType) {
1112   case SIGNATURE_TYPE_MBR:
1113     CatPrint (
1114       Str,
1115       L"HD(Part%d,Sig%08x)",
1116       (UINTN) Hd->PartitionNumber,
1117       (UINTN) *((UINT32 *) (&(Hd->Signature[0])))
1118       );
1119     break;
1120
1121   case SIGNATURE_TYPE_GUID:
1122     CatPrint (
1123       Str,
1124       L"HD(Part%d,Sig%g)",
1125       (UINTN) Hd->PartitionNumber,
1126       (EFI_GUID *) &(Hd->Signature[0])
1127       );
1128     break;
1129
1130   default:
1131     CatPrint (
1132       Str,
1133       L"HD(Part%d,MBRType=%02x,SigType=%02x)",
1134       (UINTN) Hd->PartitionNumber,
1135       (UINTN) Hd->MBRType,
1136       (UINTN) Hd->SignatureType
1137       );
1138     break;
1139   }
1140 }
1141
1142 VOID
1143 _DevPathCDROM (
1144   IN OUT POOL_PRINT       *Str,
1145   IN VOID                 *DevPath
1146   )
1147 {
1148   CDROM_DEVICE_PATH *Cd;
1149
1150   ASSERT (Str != NULL);
1151   ASSERT (DevPath != NULL);
1152
1153   Cd = DevPath;
1154   CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry);
1155 }
1156
1157 VOID
1158 _DevPathFilePath (
1159   IN OUT POOL_PRINT       *Str,
1160   IN VOID                 *DevPath
1161   )
1162 {
1163   FILEPATH_DEVICE_PATH  *Fp;
1164   UINTN                 Length;
1165   CHAR16                *NewPath;
1166
1167   ASSERT (Str != NULL);
1168   ASSERT (DevPath != NULL);
1169
1170   Fp      = DevPath;
1171   Length  = EfiDevicePathNodeLength (((EFI_DEVICE_PATH_PROTOCOL *) DevPath)) - 4;
1172   NewPath = AllocateZeroPool (Length + sizeof (CHAR16));
1173   CopyMem (NewPath, Fp->PathName, Length);
1174   StrTrim (NewPath, L' ');
1175   CatPrint (Str, L"%s", NewPath);
1176   FreePool (NewPath);
1177 }
1178
1179 VOID
1180 _DevPathMediaProtocol (
1181   IN OUT POOL_PRINT       *Str,
1182   IN VOID                 *DevPath
1183   )
1184 {
1185   MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
1186
1187   ASSERT (Str != NULL);
1188   ASSERT (DevPath != NULL);
1189
1190   MediaProt = DevPath;
1191   CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);
1192 }
1193
1194 VOID
1195 _DevPathFvFilePath (
1196   IN OUT POOL_PRINT       *Str,
1197   IN VOID                 *DevPath
1198   )
1199 {
1200   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
1201
1202   ASSERT (Str != NULL);
1203   ASSERT (DevPath != NULL);
1204
1205   FvFilePath = DevPath;
1206   CatPrint (Str, L"%g", &FvFilePath->NameGuid);
1207 }
1208
1209 VOID
1210 _DevPathRelativeOffsetRange (
1211   IN OUT POOL_PRINT       *Str,
1212   IN VOID                 *DevPath
1213   )
1214 {
1215   MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
1216
1217   ASSERT (Str != NULL);
1218   ASSERT (DevPath != NULL);
1219
1220   Offset = DevPath;
1221   CatPrint (
1222     Str,
1223     L"Offset(%lx,%lx)",
1224     Offset->StartingOffset,
1225     Offset->EndingOffset
1226     );
1227   
1228 }
1229
1230
1231 VOID
1232 _DevPathBssBss (
1233   IN OUT POOL_PRINT       *Str,
1234   IN VOID                 *DevPath
1235   )
1236 {
1237   BBS_BBS_DEVICE_PATH *BBS;
1238   CHAR16              *Type;
1239
1240   ASSERT (Str != NULL);
1241   ASSERT (DevPath != NULL);
1242
1243   BBS = DevPath;
1244   switch (BBS->DeviceType) {
1245   case BBS_TYPE_FLOPPY:
1246     Type = L"Floppy";
1247     break;
1248
1249   case BBS_TYPE_HARDDRIVE:
1250     Type = L"Harddrive";
1251     break;
1252
1253   case BBS_TYPE_CDROM:
1254     Type = L"CDROM";
1255     break;
1256
1257   case BBS_TYPE_PCMCIA:
1258     Type = L"PCMCIA";
1259     break;
1260
1261   case BBS_TYPE_USB:
1262     Type = L"Usb";
1263     break;
1264
1265   case BBS_TYPE_EMBEDDED_NETWORK:
1266     Type = L"Net";
1267     break;
1268
1269   case BBS_TYPE_BEV:
1270     Type = L"BEV";
1271     break;
1272
1273   default:
1274     Type = L"?";
1275     break;
1276   }
1277
1278   CatPrint (Str, L"BBS-%s(%a)", Type, BBS->String);
1279 }
1280
1281 VOID
1282 _DevPathEndInstance (
1283   IN OUT POOL_PRINT       *Str,
1284   IN VOID                 *DevPath
1285   )
1286 {
1287   ASSERT (Str != NULL);
1288
1289   CatPrint (Str, L",");
1290 }
1291
1292 VOID
1293 _DevPathNodeUnknown (
1294   IN OUT POOL_PRINT       *Str,
1295   IN VOID                 *DevPath
1296   )
1297 {
1298   ASSERT (Str != NULL);
1299
1300   CatPrint (Str, L"?");
1301 }
1302
1303 VOID
1304 _DevPathFvPath (
1305   IN OUT POOL_PRINT       *Str,
1306   IN VOID                 *DevPath
1307   )
1308 {
1309   MEDIA_FW_VOL_DEVICE_PATH *FvPath;
1310
1311   ASSERT (Str != NULL);
1312   ASSERT (DevPath != NULL);
1313
1314   FvPath = DevPath;
1315   CatPrint (Str, L"Fv(%g)", &FvPath->NameGuid);
1316 }
1317
1318 struct {
1319   UINT8 Type;
1320   UINT8 SubType;
1321   VOID (*Function) (POOL_PRINT *, VOID *);
1322
1323 DevPathTable[] = {
1324   HARDWARE_DEVICE_PATH,
1325   HW_PCI_DP,
1326   _DevPathPci,
1327   HARDWARE_DEVICE_PATH,
1328   HW_PCCARD_DP,
1329   _DevPathPccard,
1330   HARDWARE_DEVICE_PATH,
1331   HW_MEMMAP_DP,
1332   _DevPathMemMap,
1333   HARDWARE_DEVICE_PATH,
1334   HW_VENDOR_DP,
1335   _DevPathVendor,
1336   HARDWARE_DEVICE_PATH,
1337   HW_CONTROLLER_DP,
1338   _DevPathController,
1339   ACPI_DEVICE_PATH,
1340   ACPI_DP,
1341   _DevPathAcpi,
1342   ACPI_DEVICE_PATH,
1343   ACPI_EXTENDED_DP,
1344   _DevPathExtendedAcpi,
1345   ACPI_DEVICE_PATH,
1346   ACPI_ADR_DP,
1347   _DevPathAdrAcpi,
1348   MESSAGING_DEVICE_PATH,
1349   MSG_ATAPI_DP,
1350   _DevPathAtapi,
1351   MESSAGING_DEVICE_PATH,
1352   MSG_SCSI_DP,
1353   _DevPathScsi,
1354   MESSAGING_DEVICE_PATH,
1355   MSG_FIBRECHANNEL_DP,
1356   _DevPathFibre,
1357   MESSAGING_DEVICE_PATH,
1358   MSG_1394_DP,
1359   _DevPath1394,
1360   MESSAGING_DEVICE_PATH,
1361   MSG_USB_DP,
1362   _DevPathUsb,
1363   MESSAGING_DEVICE_PATH,
1364   MSG_USB_WWID_DP,
1365   _DevPathUsbWWID,
1366   MESSAGING_DEVICE_PATH,
1367   MSG_DEVICE_LOGICAL_UNIT_DP,
1368   _DevPathLogicalUnit,
1369   MESSAGING_DEVICE_PATH,
1370   MSG_USB_CLASS_DP,
1371   _DevPathUsbClass,
1372   MESSAGING_DEVICE_PATH,
1373   MSG_SATA_DP,
1374   _DevPathSata,
1375   MESSAGING_DEVICE_PATH,
1376   MSG_I2O_DP,
1377   _DevPathI2O,
1378   MESSAGING_DEVICE_PATH,
1379   MSG_MAC_ADDR_DP,
1380   _DevPathMacAddr,
1381   MESSAGING_DEVICE_PATH,
1382   MSG_IPv4_DP,
1383   _DevPathIPv4,
1384   MESSAGING_DEVICE_PATH,
1385   MSG_IPv6_DP,
1386   _DevPathIPv6,
1387   MESSAGING_DEVICE_PATH,
1388   MSG_INFINIBAND_DP,
1389   _DevPathInfiniBand,
1390   MESSAGING_DEVICE_PATH,
1391   MSG_UART_DP,
1392   _DevPathUart,
1393   MESSAGING_DEVICE_PATH,
1394   MSG_VENDOR_DP,
1395   _DevPathVendor,
1396   MESSAGING_DEVICE_PATH,
1397   MSG_ISCSI_DP,
1398   _DevPathiSCSI,
1399   MEDIA_DEVICE_PATH,
1400   MEDIA_HARDDRIVE_DP,
1401   _DevPathHardDrive,
1402   MEDIA_DEVICE_PATH,
1403   MEDIA_CDROM_DP,
1404   _DevPathCDROM,
1405   MEDIA_DEVICE_PATH,
1406   MEDIA_VENDOR_DP,
1407   _DevPathVendor,
1408   MEDIA_DEVICE_PATH,
1409   MEDIA_FILEPATH_DP,
1410   _DevPathFilePath,
1411   MEDIA_DEVICE_PATH,
1412   MEDIA_PROTOCOL_DP,
1413   _DevPathMediaProtocol,
1414   MEDIA_DEVICE_PATH,
1415   MEDIA_FV_DP,
1416   _DevPathFvPath,
1417   MEDIA_DEVICE_PATH,
1418   MEDIA_FV_FILEPATH_DP,
1419   _DevPathFvFilePath,
1420   MEDIA_DEVICE_PATH,
1421   MEDIA_RELATIVE_OFFSET_RANGE_DP,
1422   _DevPathRelativeOffsetRange,
1423   BBS_DEVICE_PATH,
1424   BBS_BBS_DP,
1425   _DevPathBssBss,
1426   END_DEVICE_PATH_TYPE,
1427   END_INSTANCE_DEVICE_PATH_SUBTYPE,
1428   _DevPathEndInstance,
1429   0,
1430   0,
1431   NULL
1432 };
1433
1434 CHAR16 *
1435 LibDevicePathToStr (
1436   IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
1437   )
1438 /*++
1439 Routine Description:
1440     Turns the Device Path into a printable string.  Allcoates
1441     the string from pool.  The caller must FreePool the returned
1442     string.
1443     
1444 Arguments:
1445     Devpath      -  The devices
1446     
1447 Returns:
1448     The name of the devpath
1449
1450 --*/
1451 {
1452   POOL_PRINT                Str;
1453   EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
1454   VOID (*DumpNode) (POOL_PRINT *, VOID *);
1455
1456   UINTN Index;
1457   UINTN NewSize;
1458
1459   EFI_STATUS                       Status;
1460   CHAR16                           *ToText;
1461   EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
1462
1463   ZeroMem (&Str, sizeof (Str));
1464
1465   if (DevPath == NULL) {
1466     goto Done;
1467   }
1468   
1469   Status = LibLocateProtocol (
1470              &gEfiDevicePathToTextProtocolGuid,
1471              &DevPathToText
1472              );
1473   if (!EFI_ERROR (Status)) {
1474     ToText = DevPathToText->ConvertDevicePathToText (
1475                               DevPath,
1476                               FALSE,
1477                               TRUE
1478                               );
1479     ASSERT (ToText != NULL);
1480     return ToText;
1481   }
1482
1483   //
1484   // Unpacked the device path
1485   //
1486   DevPath = UnpackDevicePath (DevPath);
1487   ASSERT (DevPath);
1488
1489   //
1490   // Process each device path node
1491   //
1492   DevPathNode = DevPath;
1493   while (!IsDevicePathEnd (DevPathNode)) {
1494     //
1495     // Find the handler to dump this device path node
1496     //
1497     DumpNode = NULL;
1498     for (Index = 0; DevPathTable[Index].Function; Index += 1) {
1499
1500       if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&
1501           DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType
1502           ) {
1503         DumpNode = DevPathTable[Index].Function;
1504         break;
1505       }
1506     }
1507     //
1508     // If not found, use a generic function
1509     //
1510     if (!DumpNode) {
1511       DumpNode = _DevPathNodeUnknown;
1512     }
1513     //
1514     //  Put a path seperator in if needed
1515     //
1516     if (Str.len && DumpNode != _DevPathEndInstance) {
1517       CatPrint (&Str, L"/");
1518     }
1519     //
1520     // Print this node of the device path
1521     //
1522     DumpNode (&Str, DevPathNode);
1523
1524     //
1525     // Next device path node
1526     //
1527     DevPathNode = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevPathNode);
1528   }
1529   //
1530   // Shrink pool used for string allocation
1531   //
1532   FreePool (DevPath);
1533 Done:
1534   NewSize           = (Str.len + 1) * sizeof (CHAR16);
1535   Str.str           = ReallocatePool (Str.str, NewSize, NewSize);
1536   ASSERT(Str.str != NULL);
1537   Str.str[Str.len]  = 0;
1538   return Str.str;
1539 }
1540
1541 EFI_DEVICE_PATH_PROTOCOL *
1542 AppendDevicePathNode (
1543   IN EFI_DEVICE_PATH_PROTOCOL  *Src1,
1544   IN EFI_DEVICE_PATH_PROTOCOL  *Src2
1545   )
1546 /*++
1547
1548 Routine Description:
1549   Function is used to append a device path node to all the instances in another device path.
1550
1551 Arguments:
1552   Src1           - A pointer to a device path data structure.
1553
1554   Src2           - A pointer to a device path data structure.
1555
1556 Returns:
1557
1558   This function returns a pointer to the new device path.  
1559   If there is not enough temporary pool memory available to complete this function, 
1560   then NULL is returned.
1561
1562   Src1 may have multiple "instances" and each instance is appended
1563   Src2 is a signal device path node (without a terminator) that is
1564   appended to each instance is Src1.
1565
1566 --*/
1567 {
1568   EFI_DEVICE_PATH_PROTOCOL  *Temp;
1569
1570   EFI_DEVICE_PATH_PROTOCOL  *Eop;
1571   UINTN                     Length;
1572   
1573   ASSERT (Src1);
1574   ASSERT (Src2);
1575   //
1576   // Build a Src2 that has a terminator on it
1577   //
1578   Length  = DevicePathNodeLength (Src2);
1579   Temp    = AllocatePool (Length + sizeof (EFI_DEVICE_PATH_PROTOCOL));
1580   if (!Temp) {
1581     return NULL;
1582   }
1583
1584   CopyMem (Temp, Src2, Length);
1585   Eop = NextDevicePathNode (Temp);
1586   SetDevicePathEndNode (Eop);
1587
1588   //
1589   // Append device paths
1590   //
1591   Src1 = AppendDevicePath (Src1, Temp);
1592   FreePool (Temp);
1593   return Src1;
1594 }
1595
1596 EFI_DEVICE_PATH_PROTOCOL *
1597 FileDevicePath (
1598   IN EFI_HANDLE                 Device  OPTIONAL,
1599   IN CHAR16                     *FileName
1600   )
1601 /*++
1602
1603 Routine Description:
1604   Function allocates a device path for a file and appends it to an existing device path.
1605
1606 Arguments:
1607   Device         - A pointer to a device handle.
1608
1609   FileName       - A pointer to a Null-terminated Unicode string.
1610
1611 Returns:
1612
1613   If Device is not a valid device handle, then a device path for the file specified 
1614   by FileName is allocated and returned.
1615
1616   Results are allocated from pool.  The caller must FreePool the resulting device path 
1617   structure
1618
1619 --*/
1620 {
1621   UINTN                     Size;
1622   FILEPATH_DEVICE_PATH      *FilePath;
1623   EFI_DEVICE_PATH_PROTOCOL  *Eop;
1624   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
1625
1626   ASSERT (FileName);
1627
1628   Size        = StrSize (FileName);
1629   FilePath    = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL));
1630   DevicePath  = NULL;
1631
1632   if (FilePath != NULL) {
1633     //
1634     // Build a file path
1635     //
1636     FilePath->Header.Type     = MEDIA_DEVICE_PATH;
1637     FilePath->Header.SubType  = MEDIA_FILEPATH_DP;
1638     SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
1639     CopyMem (FilePath->PathName, FileName, Size);
1640     Eop = NextDevicePathNode (&FilePath->Header);
1641     SetDevicePathEndNode (Eop);
1642
1643     //
1644     // Append file path to device's device path
1645     //
1646     DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) FilePath;
1647     if (Device) {
1648       DevicePath = AppendDevicePath (
1649                     DevicePathFromHandle (Device),
1650                     DevicePath
1651                     );
1652       FreePool (FilePath);
1653
1654       ASSERT (DevicePath);
1655     }
1656   }
1657
1658   return DevicePath;
1659 }
1660
1661 EFI_DEVICE_PATH_PROTOCOL *
1662 AppendDevicePathInstance (
1663   IN EFI_DEVICE_PATH_PROTOCOL  *Src,
1664   IN EFI_DEVICE_PATH_PROTOCOL  *Instance
1665   )
1666 /*++
1667
1668 Routine Description:
1669   Function is used to add a device path instance to a device path.
1670
1671 Arguments:
1672   Src          - A pointer to a device path data structure
1673
1674   Instance     - A pointer to a device path instance.
1675
1676 Returns:
1677
1678   This function returns a pointer to the new device path. 
1679   If there is not enough temporary pool memory available to complete this function, 
1680   then NULL is returned. It is up to the caller to free the memory used by Src and 
1681   Instance if they are no longer needed.
1682
1683 --*/
1684 {
1685   UINT8                     *Ptr;
1686   EFI_DEVICE_PATH_PROTOCOL  *DevPath;
1687   UINTN                     SrcSize;
1688   UINTN                     InstanceSize;
1689
1690   ASSERT (Instance);
1691
1692   if (Src == NULL) {
1693     return DuplicateDevicePath (Instance);
1694   }
1695
1696   SrcSize       = DevicePathSize (Src);
1697   InstanceSize  = DevicePathSize (Instance);
1698   Ptr           = AllocatePool (SrcSize + InstanceSize);
1699   DevPath       = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
1700   ASSERT (DevPath);
1701
1702   CopyMem (Ptr, Src, SrcSize);
1703   while (!IsDevicePathEnd (DevPath)) {
1704     DevPath = NextDevicePathNode (DevPath);
1705   }
1706   //
1707   // Convert the End to an End Instance, since we are
1708   //  appending another instacne after this one its a good
1709   //  idea.
1710   //
1711   DevPath->SubType  = END_INSTANCE_DEVICE_PATH_SUBTYPE;
1712
1713   DevPath           = NextDevicePathNode (DevPath);
1714   CopyMem (DevPath, Instance, InstanceSize);
1715   return (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
1716 }
1717
1718 EFI_STATUS
1719 LibDevicePathToInterface (
1720   IN EFI_GUID                   *Protocol,
1721   IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,
1722   OUT VOID                      **Interface
1723   )
1724 /*++
1725
1726 Routine Description:
1727   Function retrieves a protocol interface for a device.
1728
1729 Arguments:
1730   Protocol     - The published unique identifier of the protocol.
1731
1732   FilePath     - A pointer to a device path data structure.
1733
1734   Interface    - Supplies and address where a pointer to the requested 
1735                  Protocol interface is returned.
1736
1737 Returns:
1738
1739   If a match is found, then the protocol interface of that device is 
1740   returned in Interface.  Otherwise, Interface is set to NULL.
1741
1742 --*/
1743 {
1744   EFI_STATUS  Status;
1745   EFI_HANDLE  Device;
1746   
1747   ASSERT (FilePath != NULL);
1748   ASSERT (Interface != NULL);
1749
1750   Status = BS->LocateDevicePath (
1751                 Protocol,
1752                 &FilePath,
1753                 &Device
1754                 );
1755
1756   if (!EFI_ERROR (Status)) {
1757     //
1758     // If we didn't get a direct match return not found
1759     //
1760     Status = EFI_NOT_FOUND;
1761
1762     if (IsDevicePathEnd (FilePath)) {
1763       //
1764       // It was a direct match, lookup the protocol interface
1765       //
1766       Status = BS->HandleProtocol (
1767                     Device,
1768                     Protocol,
1769                     Interface
1770                     );
1771     }
1772   }
1773   //
1774   // If there was an error, do not return an interface
1775   //
1776   if (EFI_ERROR (Status)) {
1777     *Interface = NULL;
1778   }
1779
1780   return Status;
1781 }
1782
1783 BOOLEAN
1784 LibMatchDevicePaths (
1785   IN  EFI_DEVICE_PATH_PROTOCOL *Multi,
1786   IN  EFI_DEVICE_PATH_PROTOCOL *Single
1787   )
1788 /*++
1789
1790 Routine Description:
1791   Function compares a device path data structure to that of all the nodes of a 
1792   second device path instance.
1793
1794 Arguments:
1795   Multi        - A pointer to a multi-instance device path data structure.
1796
1797   Single       - A pointer to a single-instance device path data structure.
1798
1799 Returns:
1800
1801   The function returns TRUE if the Single is contained within Multi.  
1802   Otherwise, FALSE is returned.
1803
1804 --*/
1805 {
1806   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
1807
1808   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
1809   UINTN                     Size;
1810
1811   if (!Multi || !Single) {
1812     return FALSE;
1813   }
1814
1815   DevicePath      = Multi;
1816   DevicePathInst  = DevicePathInstance (&DevicePath, &Size);
1817   while (DevicePathInst) {
1818     if (CompareMem (Single, DevicePathInst, Size - sizeof (EFI_DEVICE_PATH_PROTOCOL)) == 0) {
1819       return TRUE;
1820     }
1821
1822     DevicePathInst = DevicePathInstance (&DevicePath, &Size);
1823   }
1824
1825   return FALSE;
1826 }
1827
1828 EFI_DEVICE_PATH_PROTOCOL *
1829 LibDuplicateDevicePathInstance (
1830   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
1831   )
1832 /*++
1833
1834 Routine Description:
1835   Function creates a device path data structure that identically matches the 
1836   device path passed in.
1837
1838 Arguments:
1839   DevPath      - A pointer to a device path data structure.
1840
1841 Returns:
1842
1843   The new copy of DevPath is created to identically match the input.  
1844   Otherwise, NULL is returned.
1845
1846 --*/
1847 {
1848   EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;
1849
1850   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
1851
1852   EFI_DEVICE_PATH_PROTOCOL  *Temp;
1853   UINTN                     Size;
1854
1855   ASSERT (DevPath != NULL);
1856   //
1857   // get the size of an instance from the input
1858   //
1859   Temp            = DevPath;
1860   DevicePathInst  = DevicePathInstance (&Temp, &Size);
1861
1862   //
1863   // Make a copy
1864   //
1865   NewDevPath = NULL;
1866   if (Size != 0) {
1867     NewDevPath = AllocatePool (Size);
1868   }
1869
1870   if (NewDevPath != NULL) {
1871     CopyMem (NewDevPath, DevicePathInst, Size);
1872   }
1873
1874   return NewDevPath;
1875 }
1876
1877 INTN
1878 DevicePathCompare (
1879   IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
1880   IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath2
1881   )
1882 /*++
1883
1884 Routine Description:
1885   Function compares two device pathes.
1886
1887 Arguments:
1888   DevicePath1  - A pointer to a device path data structure.
1889
1890   DevicePath2  - A pointer to a device path data structure.
1891
1892 Returns:
1893
1894   The function returns 0 if the two device paths are equal.
1895   Otherwise, other value is returned.
1896
1897 --*/
1898 {
1899   UINTN DevPathSize1;
1900   UINTN DevPathSize2;
1901   
1902   ASSERT (DevicePath1);
1903   ASSERT (DevicePath2);
1904
1905   DevPathSize1  = DevicePathSize (DevicePath1);
1906   DevPathSize2  = DevicePathSize (DevicePath2);
1907
1908   if (DevPathSize1 > DevPathSize2) {
1909     return 1;
1910   } else if (DevPathSize1 < DevPathSize2) {
1911     return -1;
1912   } else {
1913     return CompareMem (DevicePath1, DevicePath2, DevPathSize1);
1914   }
1915 }
1916
1917 VOID
1918 EFIAPI
1919 InitializeFwVolDevicepathNode (
1920   IN  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH     *FvDevicePathNode,
1921   IN EFI_GUID                               *NameGuid
1922   )
1923 /*++
1924
1925 Routine Description:
1926   Initialize a Firmware Volume (FV) Media Device Path node.
1927   
1928 Arguments:
1929   FvDevicePathNode  - Pointer to a FV device path node to initialize
1930   NameGuid          - FV file name to use in FvDevicePathNode
1931
1932 Returns:
1933
1934 --*/
1935 {
1936   FvDevicePathNode->Header.Type     = MEDIA_DEVICE_PATH;
1937   FvDevicePathNode->Header.SubType  = MEDIA_FV_FILEPATH_DP;
1938   SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
1939
1940   CopyMem (&FvDevicePathNode->NameGuid, NameGuid, sizeof(EFI_GUID));
1941 }
1942
1943 EFI_GUID *
1944 EFIAPI
1945 GetNameGuidFromFwVolDevicePathNode (
1946   IN  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   *FvDevicePathNode
1947   )
1948 /*++
1949
1950 Routine Description:
1951   Check to see if the Firmware Volume (FV) Media Device Path is valid.
1952   
1953 Arguments:
1954   FvDevicePathNode  - Pointer to FV device path to check
1955
1956 Returns:
1957   NULL  -  FvDevicePathNode is not valid.
1958   Other -  FvDevicePathNode is valid and pointer to NameGuid was returned.
1959
1960 --*/
1961 {
1962   if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&
1963       DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) {
1964     return &FvDevicePathNode->NameGuid;
1965   }
1966
1967   return NULL;
1968 }