acadc8402bbad20a1de7f2b83b716828ef3fca30
[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 _DevPathBssBss (
1211   IN OUT POOL_PRINT       *Str,
1212   IN VOID                 *DevPath
1213   )
1214 {
1215   BBS_BBS_DEVICE_PATH *BBS;
1216   CHAR16              *Type;
1217
1218   ASSERT (Str != NULL);
1219   ASSERT (DevPath != NULL);
1220
1221   BBS = DevPath;
1222   switch (BBS->DeviceType) {
1223   case BBS_TYPE_FLOPPY:
1224     Type = L"Floppy";
1225     break;
1226
1227   case BBS_TYPE_HARDDRIVE:
1228     Type = L"Harddrive";
1229     break;
1230
1231   case BBS_TYPE_CDROM:
1232     Type = L"CDROM";
1233     break;
1234
1235   case BBS_TYPE_PCMCIA:
1236     Type = L"PCMCIA";
1237     break;
1238
1239   case BBS_TYPE_USB:
1240     Type = L"Usb";
1241     break;
1242
1243   case BBS_TYPE_EMBEDDED_NETWORK:
1244     Type = L"Net";
1245     break;
1246
1247   case BBS_TYPE_BEV:
1248     Type = L"BEV";
1249     break;
1250
1251   default:
1252     Type = L"?";
1253     break;
1254   }
1255
1256   CatPrint (Str, L"BBS-%s(%a)", Type, BBS->String);
1257 }
1258
1259 VOID
1260 _DevPathEndInstance (
1261   IN OUT POOL_PRINT       *Str,
1262   IN VOID                 *DevPath
1263   )
1264 {
1265   ASSERT (Str != NULL);
1266
1267   CatPrint (Str, L",");
1268 }
1269
1270 VOID
1271 _DevPathNodeUnknown (
1272   IN OUT POOL_PRINT       *Str,
1273   IN VOID                 *DevPath
1274   )
1275 {
1276   ASSERT (Str != NULL);
1277
1278   CatPrint (Str, L"?");
1279 }
1280
1281 VOID
1282 _DevPathFvPath (
1283   IN OUT POOL_PRINT       *Str,
1284   IN VOID                 *DevPath
1285   )
1286 {
1287   MEDIA_FW_VOL_DEVICE_PATH *FvPath;
1288
1289   ASSERT (Str != NULL);
1290   ASSERT (DevPath != NULL);
1291
1292   FvPath = DevPath;
1293   CatPrint (Str, L"Fv(%g)", &FvPath->NameGuid);
1294 }
1295
1296 struct {
1297   UINT8 Type;
1298   UINT8 SubType;
1299   VOID (*Function) (POOL_PRINT *, VOID *);
1300
1301 DevPathTable[] = {
1302   HARDWARE_DEVICE_PATH,
1303   HW_PCI_DP,
1304   _DevPathPci,
1305   HARDWARE_DEVICE_PATH,
1306   HW_PCCARD_DP,
1307   _DevPathPccard,
1308   HARDWARE_DEVICE_PATH,
1309   HW_MEMMAP_DP,
1310   _DevPathMemMap,
1311   HARDWARE_DEVICE_PATH,
1312   HW_VENDOR_DP,
1313   _DevPathVendor,
1314   HARDWARE_DEVICE_PATH,
1315   HW_CONTROLLER_DP,
1316   _DevPathController,
1317   ACPI_DEVICE_PATH,
1318   ACPI_DP,
1319   _DevPathAcpi,
1320   ACPI_DEVICE_PATH,
1321   ACPI_EXTENDED_DP,
1322   _DevPathExtendedAcpi,
1323   ACPI_DEVICE_PATH,
1324   ACPI_ADR_DP,
1325   _DevPathAdrAcpi,
1326   MESSAGING_DEVICE_PATH,
1327   MSG_ATAPI_DP,
1328   _DevPathAtapi,
1329   MESSAGING_DEVICE_PATH,
1330   MSG_SCSI_DP,
1331   _DevPathScsi,
1332   MESSAGING_DEVICE_PATH,
1333   MSG_FIBRECHANNEL_DP,
1334   _DevPathFibre,
1335   MESSAGING_DEVICE_PATH,
1336   MSG_1394_DP,
1337   _DevPath1394,
1338   MESSAGING_DEVICE_PATH,
1339   MSG_USB_DP,
1340   _DevPathUsb,
1341   MESSAGING_DEVICE_PATH,
1342   MSG_USB_WWID_DP,
1343   _DevPathUsbWWID,
1344   MESSAGING_DEVICE_PATH,
1345   MSG_DEVICE_LOGICAL_UNIT_DP,
1346   _DevPathLogicalUnit,
1347   MESSAGING_DEVICE_PATH,
1348   MSG_USB_CLASS_DP,
1349   _DevPathUsbClass,
1350   MESSAGING_DEVICE_PATH,
1351   MSG_SATA_DP,
1352   _DevPathSata,
1353   MESSAGING_DEVICE_PATH,
1354   MSG_I2O_DP,
1355   _DevPathI2O,
1356   MESSAGING_DEVICE_PATH,
1357   MSG_MAC_ADDR_DP,
1358   _DevPathMacAddr,
1359   MESSAGING_DEVICE_PATH,
1360   MSG_IPv4_DP,
1361   _DevPathIPv4,
1362   MESSAGING_DEVICE_PATH,
1363   MSG_IPv6_DP,
1364   _DevPathIPv6,
1365   MESSAGING_DEVICE_PATH,
1366   MSG_INFINIBAND_DP,
1367   _DevPathInfiniBand,
1368   MESSAGING_DEVICE_PATH,
1369   MSG_UART_DP,
1370   _DevPathUart,
1371   MESSAGING_DEVICE_PATH,
1372   MSG_VENDOR_DP,
1373   _DevPathVendor,
1374   MESSAGING_DEVICE_PATH,
1375   MSG_ISCSI_DP,
1376   _DevPathiSCSI,
1377   MEDIA_DEVICE_PATH,
1378   MEDIA_HARDDRIVE_DP,
1379   _DevPathHardDrive,
1380   MEDIA_DEVICE_PATH,
1381   MEDIA_CDROM_DP,
1382   _DevPathCDROM,
1383   MEDIA_DEVICE_PATH,
1384   MEDIA_VENDOR_DP,
1385   _DevPathVendor,
1386   MEDIA_DEVICE_PATH,
1387   MEDIA_FILEPATH_DP,
1388   _DevPathFilePath,
1389   MEDIA_DEVICE_PATH,
1390   MEDIA_PROTOCOL_DP,
1391   _DevPathMediaProtocol,
1392   MEDIA_DEVICE_PATH,
1393   MEDIA_FV_DP,
1394   _DevPathFvPath,
1395   MEDIA_DEVICE_PATH,
1396   MEDIA_FV_FILEPATH_DP,
1397   _DevPathFvFilePath,
1398   BBS_DEVICE_PATH,
1399   BBS_BBS_DP,
1400   _DevPathBssBss,
1401   END_DEVICE_PATH_TYPE,
1402   END_INSTANCE_DEVICE_PATH_SUBTYPE,
1403   _DevPathEndInstance,
1404   0,
1405   0,
1406   NULL
1407 };
1408
1409 CHAR16 *
1410 LibDevicePathToStr (
1411   IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
1412   )
1413 /*++
1414 Routine Description:
1415     Turns the Device Path into a printable string.  Allcoates
1416     the string from pool.  The caller must FreePool the returned
1417     string.
1418     
1419 Arguments:
1420     Devpath      -  The devices
1421     
1422 Returns:
1423     The name of the devpath
1424
1425 --*/
1426 {
1427   POOL_PRINT                Str;
1428   EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
1429   VOID (*DumpNode) (POOL_PRINT *, VOID *);
1430
1431   UINTN Index;
1432   UINTN NewSize;
1433
1434   EFI_STATUS                       Status;
1435   CHAR16                           *ToText;
1436   EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
1437
1438   ZeroMem (&Str, sizeof (Str));
1439
1440   if (DevPath == NULL) {
1441     goto Done;
1442   }
1443   
1444   Status = LibLocateProtocol (
1445              &gEfiDevicePathToTextProtocolGuid,
1446              &DevPathToText
1447              );
1448   if (!EFI_ERROR (Status)) {
1449     ToText = DevPathToText->ConvertDevicePathToText (
1450                               DevPath,
1451                               FALSE,
1452                               TRUE
1453                               );
1454     ASSERT (ToText != NULL);
1455     return ToText;
1456   }
1457
1458   //
1459   // Unpacked the device path
1460   //
1461   DevPath = UnpackDevicePath (DevPath);
1462   ASSERT (DevPath);
1463
1464   //
1465   // Process each device path node
1466   //
1467   DevPathNode = DevPath;
1468   while (!IsDevicePathEnd (DevPathNode)) {
1469     //
1470     // Find the handler to dump this device path node
1471     //
1472     DumpNode = NULL;
1473     for (Index = 0; DevPathTable[Index].Function; Index += 1) {
1474
1475       if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&
1476           DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType
1477           ) {
1478         DumpNode = DevPathTable[Index].Function;
1479         break;
1480       }
1481     }
1482     //
1483     // If not found, use a generic function
1484     //
1485     if (!DumpNode) {
1486       DumpNode = _DevPathNodeUnknown;
1487     }
1488     //
1489     //  Put a path seperator in if needed
1490     //
1491     if (Str.len && DumpNode != _DevPathEndInstance) {
1492       CatPrint (&Str, L"/");
1493     }
1494     //
1495     // Print this node of the device path
1496     //
1497     DumpNode (&Str, DevPathNode);
1498
1499     //
1500     // Next device path node
1501     //
1502     DevPathNode = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevPathNode);
1503   }
1504   //
1505   // Shrink pool used for string allocation
1506   //
1507   FreePool (DevPath);
1508 Done:
1509   NewSize           = (Str.len + 1) * sizeof (CHAR16);
1510   Str.str           = ReallocatePool (Str.str, NewSize, NewSize);
1511   ASSERT(Str.str != NULL);
1512   Str.str[Str.len]  = 0;
1513   return Str.str;
1514 }
1515
1516 EFI_DEVICE_PATH_PROTOCOL *
1517 AppendDevicePathNode (
1518   IN EFI_DEVICE_PATH_PROTOCOL  *Src1,
1519   IN EFI_DEVICE_PATH_PROTOCOL  *Src2
1520   )
1521 /*++
1522
1523 Routine Description:
1524   Function is used to append a device path node to all the instances in another device path.
1525
1526 Arguments:
1527   Src1           - A pointer to a device path data structure.
1528
1529   Src2           - A pointer to a device path data structure.
1530
1531 Returns:
1532
1533   This function returns a pointer to the new device path.  
1534   If there is not enough temporary pool memory available to complete this function, 
1535   then NULL is returned.
1536
1537   Src1 may have multiple "instances" and each instance is appended
1538   Src2 is a signal device path node (without a terminator) that is
1539   appended to each instance is Src1.
1540
1541 --*/
1542 {
1543   EFI_DEVICE_PATH_PROTOCOL  *Temp;
1544
1545   EFI_DEVICE_PATH_PROTOCOL  *Eop;
1546   UINTN                     Length;
1547   
1548   ASSERT (Src1);
1549   ASSERT (Src2);
1550   //
1551   // Build a Src2 that has a terminator on it
1552   //
1553   Length  = DevicePathNodeLength (Src2);
1554   Temp    = AllocatePool (Length + sizeof (EFI_DEVICE_PATH_PROTOCOL));
1555   if (!Temp) {
1556     return NULL;
1557   }
1558
1559   CopyMem (Temp, Src2, Length);
1560   Eop = NextDevicePathNode (Temp);
1561   SetDevicePathEndNode (Eop);
1562
1563   //
1564   // Append device paths
1565   //
1566   Src1 = AppendDevicePath (Src1, Temp);
1567   FreePool (Temp);
1568   return Src1;
1569 }
1570
1571 EFI_DEVICE_PATH_PROTOCOL *
1572 FileDevicePath (
1573   IN EFI_HANDLE                 Device  OPTIONAL,
1574   IN CHAR16                     *FileName
1575   )
1576 /*++
1577
1578 Routine Description:
1579   Function allocates a device path for a file and appends it to an existing device path.
1580
1581 Arguments:
1582   Device         - A pointer to a device handle.
1583
1584   FileName       - A pointer to a Null-terminated Unicode string.
1585
1586 Returns:
1587
1588   If Device is not a valid device handle, then a device path for the file specified 
1589   by FileName is allocated and returned.
1590
1591   Results are allocated from pool.  The caller must FreePool the resulting device path 
1592   structure
1593
1594 --*/
1595 {
1596   UINTN                     Size;
1597   FILEPATH_DEVICE_PATH      *FilePath;
1598   EFI_DEVICE_PATH_PROTOCOL  *Eop;
1599   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
1600
1601   ASSERT (FileName);
1602
1603   Size        = StrSize (FileName);
1604   FilePath    = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL));
1605   DevicePath  = NULL;
1606
1607   if (FilePath != NULL) {
1608     //
1609     // Build a file path
1610     //
1611     FilePath->Header.Type     = MEDIA_DEVICE_PATH;
1612     FilePath->Header.SubType  = MEDIA_FILEPATH_DP;
1613     SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
1614     CopyMem (FilePath->PathName, FileName, Size);
1615     Eop = NextDevicePathNode (&FilePath->Header);
1616     SetDevicePathEndNode (Eop);
1617
1618     //
1619     // Append file path to device's device path
1620     //
1621     DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) FilePath;
1622     if (Device) {
1623       DevicePath = AppendDevicePath (
1624                     DevicePathFromHandle (Device),
1625                     DevicePath
1626                     );
1627       FreePool (FilePath);
1628
1629       ASSERT (DevicePath);
1630     }
1631   }
1632
1633   return DevicePath;
1634 }
1635
1636 EFI_DEVICE_PATH_PROTOCOL *
1637 AppendDevicePathInstance (
1638   IN EFI_DEVICE_PATH_PROTOCOL  *Src,
1639   IN EFI_DEVICE_PATH_PROTOCOL  *Instance
1640   )
1641 /*++
1642
1643 Routine Description:
1644   Function is used to add a device path instance to a device path.
1645
1646 Arguments:
1647   Src          - A pointer to a device path data structure
1648
1649   Instance     - A pointer to a device path instance.
1650
1651 Returns:
1652
1653   This function returns a pointer to the new device path. 
1654   If there is not enough temporary pool memory available to complete this function, 
1655   then NULL is returned. It is up to the caller to free the memory used by Src and 
1656   Instance if they are no longer needed.
1657
1658 --*/
1659 {
1660   UINT8                     *Ptr;
1661   EFI_DEVICE_PATH_PROTOCOL  *DevPath;
1662   UINTN                     SrcSize;
1663   UINTN                     InstanceSize;
1664
1665   ASSERT (Instance);
1666
1667   if (Src == NULL) {
1668     return DuplicateDevicePath (Instance);
1669   }
1670
1671   SrcSize       = DevicePathSize (Src);
1672   InstanceSize  = DevicePathSize (Instance);
1673   Ptr           = AllocatePool (SrcSize + InstanceSize);
1674   DevPath       = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
1675   ASSERT (DevPath);
1676
1677   CopyMem (Ptr, Src, SrcSize);
1678   while (!IsDevicePathEnd (DevPath)) {
1679     DevPath = NextDevicePathNode (DevPath);
1680   }
1681   //
1682   // Convert the End to an End Instance, since we are
1683   //  appending another instacne after this one its a good
1684   //  idea.
1685   //
1686   DevPath->SubType  = END_INSTANCE_DEVICE_PATH_SUBTYPE;
1687
1688   DevPath           = NextDevicePathNode (DevPath);
1689   CopyMem (DevPath, Instance, InstanceSize);
1690   return (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
1691 }
1692
1693 EFI_STATUS
1694 LibDevicePathToInterface (
1695   IN EFI_GUID                   *Protocol,
1696   IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,
1697   OUT VOID                      **Interface
1698   )
1699 /*++
1700
1701 Routine Description:
1702   Function retrieves a protocol interface for a device.
1703
1704 Arguments:
1705   Protocol     - The published unique identifier of the protocol.
1706
1707   FilePath     - A pointer to a device path data structure.
1708
1709   Interface    - Supplies and address where a pointer to the requested 
1710                  Protocol interface is returned.
1711
1712 Returns:
1713
1714   If a match is found, then the protocol interface of that device is 
1715   returned in Interface.  Otherwise, Interface is set to NULL.
1716
1717 --*/
1718 {
1719   EFI_STATUS  Status;
1720   EFI_HANDLE  Device;
1721   
1722   ASSERT (FilePath != NULL);
1723   ASSERT (Interface != NULL);
1724
1725   Status = BS->LocateDevicePath (
1726                 Protocol,
1727                 &FilePath,
1728                 &Device
1729                 );
1730
1731   if (!EFI_ERROR (Status)) {
1732     //
1733     // If we didn't get a direct match return not found
1734     //
1735     Status = EFI_NOT_FOUND;
1736
1737     if (IsDevicePathEnd (FilePath)) {
1738       //
1739       // It was a direct match, lookup the protocol interface
1740       //
1741       Status = BS->HandleProtocol (
1742                     Device,
1743                     Protocol,
1744                     Interface
1745                     );
1746     }
1747   }
1748   //
1749   // If there was an error, do not return an interface
1750   //
1751   if (EFI_ERROR (Status)) {
1752     *Interface = NULL;
1753   }
1754
1755   return Status;
1756 }
1757
1758 BOOLEAN
1759 LibMatchDevicePaths (
1760   IN  EFI_DEVICE_PATH_PROTOCOL *Multi,
1761   IN  EFI_DEVICE_PATH_PROTOCOL *Single
1762   )
1763 /*++
1764
1765 Routine Description:
1766   Function compares a device path data structure to that of all the nodes of a 
1767   second device path instance.
1768
1769 Arguments:
1770   Multi        - A pointer to a multi-instance device path data structure.
1771
1772   Single       - A pointer to a single-instance device path data structure.
1773
1774 Returns:
1775
1776   The function returns TRUE if the Single is contained within Multi.  
1777   Otherwise, FALSE is returned.
1778
1779 --*/
1780 {
1781   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
1782
1783   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
1784   UINTN                     Size;
1785
1786   if (!Multi || !Single) {
1787     return FALSE;
1788   }
1789
1790   DevicePath      = Multi;
1791   DevicePathInst  = DevicePathInstance (&DevicePath, &Size);
1792   while (DevicePathInst) {
1793     if (CompareMem (Single, DevicePathInst, Size - sizeof (EFI_DEVICE_PATH_PROTOCOL)) == 0) {
1794       return TRUE;
1795     }
1796
1797     DevicePathInst = DevicePathInstance (&DevicePath, &Size);
1798   }
1799
1800   return FALSE;
1801 }
1802
1803 EFI_DEVICE_PATH_PROTOCOL *
1804 LibDuplicateDevicePathInstance (
1805   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
1806   )
1807 /*++
1808
1809 Routine Description:
1810   Function creates a device path data structure that identically matches the 
1811   device path passed in.
1812
1813 Arguments:
1814   DevPath      - A pointer to a device path data structure.
1815
1816 Returns:
1817
1818   The new copy of DevPath is created to identically match the input.  
1819   Otherwise, NULL is returned.
1820
1821 --*/
1822 {
1823   EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;
1824
1825   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
1826
1827   EFI_DEVICE_PATH_PROTOCOL  *Temp;
1828   UINTN                     Size;
1829
1830   ASSERT (DevPath != NULL);
1831   //
1832   // get the size of an instance from the input
1833   //
1834   Temp            = DevPath;
1835   DevicePathInst  = DevicePathInstance (&Temp, &Size);
1836
1837   //
1838   // Make a copy
1839   //
1840   NewDevPath = NULL;
1841   if (Size != 0) {
1842     NewDevPath = AllocatePool (Size);
1843   }
1844
1845   if (NewDevPath != NULL) {
1846     CopyMem (NewDevPath, DevicePathInst, Size);
1847   }
1848
1849   return NewDevPath;
1850 }
1851
1852 INTN
1853 DevicePathCompare (
1854   IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
1855   IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath2
1856   )
1857 /*++
1858
1859 Routine Description:
1860   Function compares two device pathes.
1861
1862 Arguments:
1863   DevicePath1  - A pointer to a device path data structure.
1864
1865   DevicePath2  - A pointer to a device path data structure.
1866
1867 Returns:
1868
1869   The function returns 0 if the two device paths are equal.
1870   Otherwise, other value is returned.
1871
1872 --*/
1873 {
1874   UINTN DevPathSize1;
1875   UINTN DevPathSize2;
1876   
1877   ASSERT (DevicePath1);
1878   ASSERT (DevicePath2);
1879
1880   DevPathSize1  = DevicePathSize (DevicePath1);
1881   DevPathSize2  = DevicePathSize (DevicePath2);
1882
1883   if (DevPathSize1 > DevPathSize2) {
1884     return 1;
1885   } else if (DevPathSize1 < DevPathSize2) {
1886     return -1;
1887   } else {
1888     return CompareMem (DevicePath1, DevicePath2, DevPathSize1);
1889   }
1890 }
1891
1892 VOID
1893 EFIAPI
1894 InitializeFwVolDevicepathNode (
1895   IN  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH     *FvDevicePathNode,
1896   IN EFI_GUID                               *NameGuid
1897   )
1898 /*++
1899
1900 Routine Description:
1901   Initialize a Firmware Volume (FV) Media Device Path node.
1902   
1903 Arguments:
1904   FvDevicePathNode  - Pointer to a FV device path node to initialize
1905   NameGuid          - FV file name to use in FvDevicePathNode
1906
1907 Returns:
1908
1909 --*/
1910 {
1911   FvDevicePathNode->Header.Type     = MEDIA_DEVICE_PATH;
1912   FvDevicePathNode->Header.SubType  = MEDIA_FV_FILEPATH_DP;
1913   SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
1914
1915   CopyMem (&FvDevicePathNode->NameGuid, NameGuid, sizeof(EFI_GUID));
1916 }
1917
1918 EFI_GUID *
1919 EFIAPI
1920 GetNameGuidFromFwVolDevicePathNode (
1921   IN  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   *FvDevicePathNode
1922   )
1923 /*++
1924
1925 Routine Description:
1926   Check to see if the Firmware Volume (FV) Media Device Path is valid.
1927   
1928 Arguments:
1929   FvDevicePathNode  - Pointer to FV device path to check
1930
1931 Returns:
1932   NULL  -  FvDevicePathNode is not valid.
1933   Other -  FvDevicePathNode is valid and pointer to NameGuid was returned.
1934
1935 --*/
1936 {
1937   if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&
1938       DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) {
1939     return &FvDevicePathNode->NameGuid;
1940   }
1941
1942   return NULL;
1943 }