Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[mirror_edk2.git] / EdkModulePkg / Universal / DevicePath / Dxe / DevicePathToText.c
1 /*++
2
3 Copyright (c) 2006, 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 DevicePathToText.c
15
16 Abstract:
17
18 DevicePathToText protocol as defined in the UEFI 2.0 specification.
19
20 --*/
21
22 #include "DevicePath.h"
23
24 STATIC
25 EFI_DEVICE_PATH_PROTOCOL *
26 UnpackDevicePath (
27 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
28 )
29 /*++
30
31 Routine Description:
32 Function unpacks a device path data structure so that all the nodes of a device path
33 are naturally aligned.
34
35 Arguments:
36 DevPath - A pointer to a device path data structure
37
38 Returns:
39 If the memory for the device path is successfully allocated, then a pointer to the
40 new device path is returned. Otherwise, NULL is returned.
41
42 --*/
43 {
44 EFI_DEVICE_PATH_PROTOCOL *Src;
45 EFI_DEVICE_PATH_PROTOCOL *Dest;
46 EFI_DEVICE_PATH_PROTOCOL *NewPath;
47 UINTN Size;
48
49 if (DevPath == NULL) {
50 return NULL;
51 }
52 //
53 // Walk device path and round sizes to valid boundries
54 //
55 Src = DevPath;
56 Size = 0;
57 for (;;) {
58 Size += DevicePathNodeLength (Src);
59 Size += ALIGN_SIZE (Size);
60
61 if (IsDevicePathEnd (Src)) {
62 break;
63 }
64
65 Src = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (Src);
66 }
67 //
68 // Allocate space for the unpacked path
69 //
70 NewPath = AllocateZeroPool (Size);
71 if (NewPath != NULL) {
72
73 ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);
74
75 //
76 // Copy each node
77 //
78 Src = DevPath;
79 Dest = NewPath;
80 for (;;) {
81 Size = DevicePathNodeLength (Src);
82 CopyMem (Dest, Src, Size);
83 Size += ALIGN_SIZE (Size);
84 SetDevicePathNodeLength (Dest, Size);
85 Dest->Type |= EFI_DP_TYPE_UNPACKED;
86 Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);
87
88 if (IsDevicePathEnd (Src)) {
89 break;
90 }
91
92 Src = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (Src);
93 }
94 }
95
96 return NewPath;
97 }
98
99 STATIC
100 VOID *
101 ReallocatePool (
102 IN VOID *OldPool,
103 IN UINTN OldSize,
104 IN UINTN NewSize
105 )
106 /*++
107
108 Routine Description:
109 Adjusts the size of a previously allocated buffer.
110
111 Arguments:
112 OldPool - A pointer to the buffer whose size is being adjusted.
113 OldSize - The size of the current buffer.
114 NewSize - The size of the new buffer.
115
116 Returns:
117 EFI_SUCEESS - The requested number of bytes were allocated.
118 EFI_OUT_OF_RESOURCES - The pool requested could not be allocated.
119 EFI_INVALID_PARAMETER - The buffer was invalid.
120
121 --*/
122 {
123 VOID *NewPool;
124
125 NewPool = NULL;
126 if (NewSize) {
127 NewPool = AllocateZeroPool (NewSize);
128 }
129
130 if (OldPool) {
131 if (NewPool) {
132 CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
133 }
134
135 gBS->FreePool (OldPool);
136 }
137
138 return NewPool;
139 }
140
141 STATIC
142 CHAR16 *
143 CatPrint (
144 IN OUT POOL_PRINT *Str,
145 IN CHAR16 *Fmt,
146 ...
147 )
148 /*++
149
150 Routine Description:
151 Concatenates a formatted unicode string to allocated pool.
152 The caller must free the resulting buffer.
153
154 Arguments:
155 Str - Tracks the allocated pool, size in use, and
156 amount of pool allocated.
157 Fmt - The format string
158
159 Returns:
160 Allocated buffer with the formatted string printed in it.
161 The caller must free the allocated buffer. The buffer
162 allocation is not packed.
163
164 --*/
165 {
166 UINT16 *AppendStr;
167 VA_LIST Args;
168 UINTN Size;
169
170 AppendStr = AllocateZeroPool (0x1000);
171 if (AppendStr == NULL) {
172 return Str->Str;
173 }
174
175 VA_START (Args, Fmt);
176 UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);
177 VA_END (Args);
178 if (NULL == Str->Str) {
179 Size = StrSize (AppendStr);
180 Str->Str = AllocateZeroPool (Size);
181 ASSERT (Str->Str != NULL);
182 } else {
183 Size = StrSize (AppendStr) - sizeof (UINT16);
184 Size = Size + StrSize (Str->Str);
185 Str->Str = ReallocatePool (
186 Str->Str,
187 StrSize (Str->Str),
188 Size
189 );
190 ASSERT (Str->Str != NULL);
191 }
192
193 Str->MaxLen = MAX_CHAR * sizeof (UINT16);
194 if (Size < Str->MaxLen) {
195 StrCat (Str->Str, AppendStr);
196 Str->Len = Size - sizeof (UINT16);
197 }
198
199 gBS->FreePool (AppendStr);
200 return Str->Str;
201 }
202
203 STATIC
204 VOID
205 DevPathToTextPci (
206 IN OUT POOL_PRINT *Str,
207 IN VOID *DevPath,
208 IN BOOLEAN DisplayOnly,
209 IN BOOLEAN AllowShortcuts
210 )
211 {
212 PCI_DEVICE_PATH *Pci;
213
214 Pci = DevPath;
215 CatPrint (Str, L"Pci(%x,%x)", Pci->Function, Pci->Device);
216 }
217
218 STATIC
219 VOID
220 DevPathToTextPccard (
221 IN OUT POOL_PRINT *Str,
222 IN VOID *DevPath,
223 IN BOOLEAN DisplayOnly,
224 IN BOOLEAN AllowShortcuts
225 )
226 {
227 PCCARD_DEVICE_PATH *Pccard;
228
229 Pccard = DevPath;
230 CatPrint (Str, L"PcCard(%x)", Pccard->FunctionNumber);
231 }
232
233 STATIC
234 VOID
235 DevPathToTextMemMap (
236 IN OUT POOL_PRINT *Str,
237 IN VOID *DevPath,
238 IN BOOLEAN DisplayOnly,
239 IN BOOLEAN AllowShortcuts
240 )
241 {
242 MEMMAP_DEVICE_PATH *MemMap;
243
244 MemMap = DevPath;
245 CatPrint (
246 Str,
247 L"MemoryMapped(%lx,%lx)",
248 MemMap->StartingAddress,
249 MemMap->EndingAddress
250 );
251 }
252
253 STATIC
254 VOID
255 DevPathToTextVendor (
256 IN OUT POOL_PRINT *Str,
257 IN VOID *DevPath,
258 IN BOOLEAN DisplayOnly,
259 IN BOOLEAN AllowShortcuts
260 )
261 {
262 VENDOR_DEVICE_PATH *Vendor;
263 CHAR16 *Type;
264 UINTN Index;
265 UINT32 FlowControlMap;
266 UINT16 Info;
267
268 Vendor = (VENDOR_DEVICE_PATH *) DevPath;
269 switch (DevicePathType (&Vendor->Header)) {
270 case HARDWARE_DEVICE_PATH:
271 Type = L"Hw";
272 break;
273
274 case MESSAGING_DEVICE_PATH:
275 Type = L"Msg";
276 if (AllowShortcuts) {
277 if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {
278 CatPrint (Str, L"VenPcAnsi()");
279 return ;
280 } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {
281 CatPrint (Str, L"VenVt100()");
282 return ;
283 } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {
284 CatPrint (Str, L"VenVt100Plus()");
285 return ;
286 } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {
287 CatPrint (Str, L"VenUft8()");
288 return ;
289 } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingUartFlowControlGuid)) {
290 FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);
291 switch (FlowControlMap & 0x00000003) {
292 case 0:
293 CatPrint (Str, L"UartFlowCtrl(%s)", L"None");
294 break;
295
296 case 1:
297 CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");
298 break;
299
300 case 2:
301 CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");
302 break;
303
304 default:
305 break;
306 }
307
308 return ;
309 } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingSASGuid)) {
310 CatPrint (
311 Str,
312 L"SAS(%lx,%lx,%x,",
313 ((SAS_DEVICE_PATH *) Vendor)->SasAddress,
314 ((SAS_DEVICE_PATH *) Vendor)->Lun,
315 ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
316 );
317 Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
318 if ((Info & 0x0f) == 0) {
319 CatPrint (Str, L"NoTopology,0,0,0,");
320 } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {
321 CatPrint (
322 Str,
323 L"%s,%s,%s,",
324 (Info & (0x1 << 4)) ? L"SATA" : L"SAS",
325 (Info & (0x1 << 5)) ? L"External" : L"Internal",
326 (Info & (0x1 << 6)) ? L"Expanded" : L"Direct"
327 );
328 if ((Info & 0x0f) == 1) {
329 CatPrint (Str, L"0,");
330 } else {
331 CatPrint (Str, L"%x,", (Info >> 8) & 0xff);
332 }
333 } else {
334 CatPrint (Str, L"0,0,0,0,");
335 }
336
337 CatPrint (Str, L"%x)", ((SAS_DEVICE_PATH *) Vendor)->Reserved);
338 return ;
339 } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {
340 CatPrint (Str, L"DebugPort()");
341 return ;
342 } else {
343 return ;
344 //
345 // reserved
346 //
347 }
348 }
349 break;
350
351 case MEDIA_DEVICE_PATH:
352 Type = L"Media";
353 break;
354
355 default:
356 Type = L"?";
357 break;
358 }
359
360 CatPrint (Str, L"Ven%s(%g,", Type, &Vendor->Guid);
361 for (Index = 0; Index < DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH); Index++) {
362 CatPrint (Str, L"%02x", ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);
363 }
364
365 CatPrint (Str, L")");
366 }
367
368 STATIC
369 VOID
370 DevPathToTextController (
371 IN OUT POOL_PRINT *Str,
372 IN VOID *DevPath,
373 IN BOOLEAN DisplayOnly,
374 IN BOOLEAN AllowShortcuts
375 )
376 {
377 CONTROLLER_DEVICE_PATH *Controller;
378
379 Controller = DevPath;
380 CatPrint (
381 Str,
382 L"Ctrl(%x)",
383 Controller->ControllerNumber
384 );
385 }
386
387 STATIC
388 VOID
389 DevPathToTextAcpi (
390 IN OUT POOL_PRINT *Str,
391 IN VOID *DevPath,
392 IN BOOLEAN DisplayOnly,
393 IN BOOLEAN AllowShortcuts
394 )
395 {
396 ACPI_HID_DEVICE_PATH *Acpi;
397
398 Acpi = DevPath;
399 if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
400 if (AllowShortcuts) {
401 switch (EISA_ID_TO_NUM (Acpi->HID)) {
402 case 0x0a03:
403 CatPrint (Str, L"PciRoot(%x)", Acpi->UID);
404 break;
405
406 case 0x0604:
407 CatPrint (Str, L"Floppy(%x)", Acpi->UID);
408 break;
409
410 case 0x0301:
411 CatPrint (Str, L"Keyboard(%x)", Acpi->UID);
412 break;
413
414 case 0x0501:
415 CatPrint (Str, L"Serial(%x)", Acpi->UID);
416 break;
417
418 case 0x0401:
419 CatPrint (Str, L"ParallelPort(%x)", Acpi->UID);
420 break;
421
422 default:
423 break;
424 }
425
426 return ;
427 }
428
429 CatPrint (Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
430 } else {
431 CatPrint (Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);
432 }
433 }
434
435 #define NextStrA(a) ((UINT8 *) (((UINT8 *) (a)) + AsciiStrLen ((CHAR8 *) (a)) + 1))
436
437 STATIC
438 VOID
439 DevPathToTextExtAcpi (
440 IN OUT POOL_PRINT *Str,
441 IN VOID *DevPath,
442 IN BOOLEAN DisplayOnly,
443 IN BOOLEAN AllowShortcuts
444 )
445 {
446 ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *AcpiExt;
447 UINT8 *NextString;
448
449 AcpiExt = DevPath;
450
451 if (AllowShortcuts) {
452 NextString = NextStrA (AcpiExt->HidUidCidStr);
453 if ((*(AcpiExt->HidUidCidStr) == '\0') &&
454 (*(NextStrA (NextString)) == '\0') &&
455 (AcpiExt->UID == 0)
456 ) {
457 if ((AcpiExt->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
458 CatPrint (
459 Str,
460 L"AcpiExp(PNP%04x,%x,%a)",
461 EISA_ID_TO_NUM (AcpiExt->HID),
462 AcpiExt->CID,
463 NextStrA (AcpiExt->HidUidCidStr)
464 );
465 } else {
466 CatPrint (
467 Str,
468 L"AcpiExp(%08x,%x,%a)",
469 AcpiExt->HID,
470 AcpiExt->CID,
471 NextStrA (AcpiExt->HidUidCidStr)
472 );
473 }
474 }
475 return ;
476 }
477
478 NextString = NextStrA (AcpiExt->HidUidCidStr);
479 NextString = NextStrA (NextString);
480 if ((AcpiExt->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
481 CatPrint (
482 Str,
483 L"AcpiEx(PNP%04x,%x,%x,%a,%a,%a)",
484 EISA_ID_TO_NUM (AcpiExt->HID),
485 AcpiExt->CID,
486 AcpiExt->UID,
487 AcpiExt->HidUidCidStr,
488 NextString,
489 NextStrA (AcpiExt->HidUidCidStr)
490 );
491 } else {
492 CatPrint (
493 Str,
494 L"AcpiEx(%08x,%x,%x,%a,%a,%a)",
495 AcpiExt->HID,
496 AcpiExt->CID,
497 AcpiExt->UID,
498 AcpiExt->HidUidCidStr,
499 NextString,
500 NextStrA (AcpiExt->HidUidCidStr)
501 );
502 }
503 }
504
505 STATIC
506 VOID
507 DevPathToTextAtapi (
508 IN OUT POOL_PRINT *Str,
509 IN VOID *DevPath,
510 IN BOOLEAN DisplayOnly,
511 IN BOOLEAN AllowShortcuts
512 )
513 {
514 ATAPI_DEVICE_PATH *Atapi;
515
516 Atapi = DevPath;
517
518 if (DisplayOnly) {
519 CatPrint (Str, L"Ata(%x)", Atapi->Lun);
520 } else {
521 CatPrint (
522 Str,
523 L"Ata(%s,%s,%x)",
524 Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
525 Atapi->SlaveMaster ? L"Slave" : L"Master",
526 Atapi->Lun
527 );
528 }
529 }
530
531 STATIC
532 VOID
533 DevPathToTextScsi (
534 IN OUT POOL_PRINT *Str,
535 IN VOID *DevPath,
536 IN BOOLEAN DisplayOnly,
537 IN BOOLEAN AllowShortcuts
538 )
539 {
540 SCSI_DEVICE_PATH *Scsi;
541
542 Scsi = DevPath;
543 CatPrint (Str, L"Scsi(%x,%x)", Scsi->Pun, Scsi->Lun);
544 }
545
546 STATIC
547 VOID
548 DevPathToTextFibre (
549 IN OUT POOL_PRINT *Str,
550 IN VOID *DevPath,
551 IN BOOLEAN DisplayOnly,
552 IN BOOLEAN AllowShortcuts
553 )
554 {
555 FIBRECHANNEL_DEVICE_PATH *Fibre;
556
557 Fibre = DevPath;
558 CatPrint (Str, L"Fibre(%lx,%lx)", Fibre->WWN, Fibre->Lun);
559 }
560
561 STATIC
562 VOID
563 DevPathToText1394 (
564 IN OUT POOL_PRINT *Str,
565 IN VOID *DevPath,
566 IN BOOLEAN DisplayOnly,
567 IN BOOLEAN AllowShortcuts
568 )
569 {
570 F1394_DEVICE_PATH *F1394;
571
572 F1394 = DevPath;
573 CatPrint (Str, L"I1394(%lx)", F1394->Guid);
574 }
575
576 STATIC
577 VOID
578 DevPathToTextUsb (
579 IN OUT POOL_PRINT *Str,
580 IN VOID *DevPath,
581 IN BOOLEAN DisplayOnly,
582 IN BOOLEAN AllowShortcuts
583 )
584 {
585 USB_DEVICE_PATH *Usb;
586
587 Usb = DevPath;
588 CatPrint (Str, L"USB(%x,%x)", Usb->ParentPortNumber, Usb->InterfaceNumber);
589 }
590
591 STATIC
592 VOID
593 DevPathToTextUsbWWID (
594 IN OUT POOL_PRINT *Str,
595 IN VOID *DevPath,
596 IN BOOLEAN DisplayOnly,
597 IN BOOLEAN AllowShortcuts
598 )
599 {
600 USB_WWID_DEVICE_PATH *UsbWWId;
601
602 UsbWWId = DevPath;
603 CatPrint (
604 Str,
605 L"UsbWwid(%x,%x,%x,\"WWID\")",
606 UsbWWId->VendorId,
607 UsbWWId->ProductId,
608 UsbWWId->InterfaceNumber
609 );
610 }
611
612 STATIC
613 VOID
614 DevPathToTextLogicalUnit (
615 IN OUT POOL_PRINT *Str,
616 IN VOID *DevPath,
617 IN BOOLEAN DisplayOnly,
618 IN BOOLEAN AllowShortcuts
619 )
620 {
621 DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
622
623 LogicalUnit = DevPath;
624 CatPrint (Str, L"Unit(%x)", LogicalUnit->Lun);
625 }
626
627 STATIC
628 VOID
629 DevPathToTextUsbClass (
630 IN OUT POOL_PRINT *Str,
631 IN VOID *DevPath,
632 IN BOOLEAN DisplayOnly,
633 IN BOOLEAN AllowShortcuts
634 )
635 {
636 USB_CLASS_DEVICE_PATH *UsbClass;
637
638 UsbClass = DevPath;
639
640 if (AllowShortcuts == TRUE) {
641 switch (UsbClass->DeviceClass) {
642 case 1:
643 CatPrint (
644 Str,
645 L"UsbAudio(%x,%x,%x,%x)",
646 UsbClass->VendorId,
647 UsbClass->ProductId,
648 UsbClass->DeviceSubClass,
649 UsbClass->DeviceProtocol
650 );
651 break;
652
653 case 2:
654 CatPrint (
655 Str,
656 L"UsbCDCControl(%x,%x,%x,%x)",
657 UsbClass->VendorId,
658 UsbClass->ProductId,
659 UsbClass->DeviceSubClass,
660 UsbClass->DeviceProtocol
661 );
662 break;
663
664 case 3:
665 CatPrint (
666 Str,
667 L"UsbHID(%x,%x,%x,%x)",
668 UsbClass->VendorId,
669 UsbClass->ProductId,
670 UsbClass->DeviceSubClass,
671 UsbClass->DeviceProtocol
672 );
673 break;
674
675 case 6:
676 CatPrint (
677 Str,
678 L"UsbImage(%x,%x,%x,%x)",
679 UsbClass->VendorId,
680 UsbClass->ProductId,
681 UsbClass->DeviceSubClass,
682 UsbClass->DeviceProtocol
683 );
684 break;
685
686 case 7:
687 CatPrint (
688 Str,
689 L"UsbPrinter(%x,%x,%x,%x)",
690 UsbClass->VendorId,
691 UsbClass->ProductId,
692 UsbClass->DeviceSubClass,
693 UsbClass->DeviceProtocol
694 );
695 break;
696
697 case 8:
698 CatPrint (
699 Str,
700 L"UsbMassStorage(%x,%x,%x,%x)",
701 UsbClass->VendorId,
702 UsbClass->ProductId,
703 UsbClass->DeviceSubClass,
704 UsbClass->DeviceProtocol
705 );
706 break;
707
708 case 9:
709 CatPrint (
710 Str,
711 L"UsbHub(%x,%x,%x,%x)",
712 UsbClass->VendorId,
713 UsbClass->ProductId,
714 UsbClass->DeviceSubClass,
715 UsbClass->DeviceProtocol
716 );
717 break;
718
719 case 10:
720 CatPrint (
721 Str,
722 L"UsbCDCData(%x,%x,%x,%x)",
723 UsbClass->VendorId,
724 UsbClass->ProductId,
725 UsbClass->DeviceSubClass,
726 UsbClass->DeviceProtocol
727 );
728 break;
729
730 case 11:
731 CatPrint (
732 Str,
733 L"UsbSmartCard(%x,%x,%x,%x)",
734 UsbClass->VendorId,
735 UsbClass->ProductId,
736 UsbClass->DeviceSubClass,
737 UsbClass->DeviceProtocol
738 );
739 break;
740
741 case 14:
742 CatPrint (
743 Str,
744 L"UsbVideo(%x,%x,%x,%x)",
745 UsbClass->VendorId,
746 UsbClass->ProductId,
747 UsbClass->DeviceSubClass,
748 UsbClass->DeviceProtocol
749 );
750 break;
751
752 case 220:
753 CatPrint (
754 Str,
755 L"UsbDiagnostic(%x,%x,%x,%x)",
756 UsbClass->VendorId,
757 UsbClass->ProductId,
758 UsbClass->DeviceSubClass,
759 UsbClass->DeviceProtocol
760 );
761 break;
762
763 case 224:
764 CatPrint (
765 Str,
766 L"UsbWireless(%x,%x,%x,%x)",
767 UsbClass->VendorId,
768 UsbClass->ProductId,
769 UsbClass->DeviceSubClass,
770 UsbClass->DeviceProtocol
771 );
772 break;
773
774 case 254:
775 if (UsbClass->DeviceSubClass == 1) {
776 CatPrint (
777 Str,
778 L"UsbDeviceFirmwareUpdate(%x,%x,%x)",
779 UsbClass->VendorId,
780 UsbClass->ProductId,
781 UsbClass->DeviceProtocol
782 );
783 } else if (UsbClass->DeviceSubClass == 2) {
784 CatPrint (
785 Str,
786 L"UsbIrdaBridge(%x,%x,%x)",
787 UsbClass->VendorId,
788 UsbClass->ProductId,
789 UsbClass->DeviceProtocol
790 );
791 } else if (UsbClass->DeviceSubClass == 3) {
792 CatPrint (
793 Str,
794 L"UsbTestAndMeasurement(%x,%x,%x)",
795 UsbClass->VendorId,
796 UsbClass->ProductId,
797 UsbClass->DeviceProtocol
798 );
799 }
800 break;
801
802 default:
803 break;
804 }
805
806 return ;
807 }
808
809 CatPrint (
810 Str,
811 L"UsbClass(%x,%x,%x,%x,%x)",
812 UsbClass->VendorId,
813 UsbClass->ProductId,
814 UsbClass->DeviceClass,
815 UsbClass->DeviceSubClass,
816 UsbClass->DeviceProtocol
817 );
818 }
819
820 STATIC
821 VOID
822 DevPathToTextI2O (
823 IN OUT POOL_PRINT *Str,
824 IN VOID *DevPath,
825 IN BOOLEAN DisplayOnly,
826 IN BOOLEAN AllowShortcuts
827 )
828 {
829 I2O_DEVICE_PATH *I2O;
830
831 I2O = DevPath;
832 CatPrint (Str, L"I2O(%x)", I2O->Tid);
833 }
834
835 STATIC
836 VOID
837 DevPathToTextMacAddr (
838 IN OUT POOL_PRINT *Str,
839 IN VOID *DevPath,
840 IN BOOLEAN DisplayOnly,
841 IN BOOLEAN AllowShortcuts
842 )
843 {
844 MAC_ADDR_DEVICE_PATH *MAC;
845 UINTN HwAddressSize;
846 UINTN Index;
847
848 MAC = DevPath;
849
850 HwAddressSize = sizeof (EFI_MAC_ADDRESS);
851 if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
852 HwAddressSize = 6;
853 }
854
855 CatPrint (Str, L"MAC(");
856
857 for (Index = 0; Index < HwAddressSize; Index++) {
858 CatPrint (Str, L"%02x", MAC->MacAddress.Addr[Index]);
859 }
860
861 CatPrint (Str, L",%x)", MAC->IfType);
862 }
863
864 STATIC
865 VOID
866 DevPathToTextIPv4 (
867 IN OUT POOL_PRINT *Str,
868 IN VOID *DevPath,
869 IN BOOLEAN DisplayOnly,
870 IN BOOLEAN AllowShortcuts
871 )
872 {
873 IPv4_DEVICE_PATH *IP;
874
875 IP = DevPath;
876 if (DisplayOnly == TRUE) {
877 CatPrint (
878 Str,
879 L"IPv4(%d.%d.%d.%d)",
880 IP->RemoteIpAddress.Addr[0],
881 IP->RemoteIpAddress.Addr[1],
882 IP->RemoteIpAddress.Addr[2],
883 IP->RemoteIpAddress.Addr[3]
884 );
885 return ;
886 }
887
888 CatPrint (
889 Str,
890 L"IPv4(%d.%d.%d.%d,%s,%s,%d.%d.%d.%d)",
891 IP->RemoteIpAddress.Addr[0],
892 IP->RemoteIpAddress.Addr[1],
893 IP->RemoteIpAddress.Addr[2],
894 IP->RemoteIpAddress.Addr[3],
895 IP->Protocol ? L"TCP" : L"UDP",
896 (IP->StaticIpAddress == TRUE) ? L"Static" : L"DHCP",
897 IP->LocalIpAddress.Addr[0],
898 IP->LocalIpAddress.Addr[1],
899 IP->LocalIpAddress.Addr[2],
900 IP->LocalIpAddress.Addr[3]
901 );
902 }
903
904 STATIC
905 VOID
906 DevPathToTextIPv6 (
907 IN OUT POOL_PRINT *Str,
908 IN VOID *DevPath,
909 IN BOOLEAN DisplayOnly,
910 IN BOOLEAN AllowShortcuts
911 )
912 {
913 IPv6_DEVICE_PATH *IP;
914
915 IP = DevPath;
916 if (DisplayOnly == TRUE) {
917 CatPrint (
918 Str,
919 L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",
920 IP->RemoteIpAddress.Addr[0],
921 IP->RemoteIpAddress.Addr[1],
922 IP->RemoteIpAddress.Addr[2],
923 IP->RemoteIpAddress.Addr[3],
924 IP->RemoteIpAddress.Addr[4],
925 IP->RemoteIpAddress.Addr[5],
926 IP->RemoteIpAddress.Addr[6],
927 IP->RemoteIpAddress.Addr[7],
928 IP->RemoteIpAddress.Addr[8],
929 IP->RemoteIpAddress.Addr[9],
930 IP->RemoteIpAddress.Addr[10],
931 IP->RemoteIpAddress.Addr[11],
932 IP->RemoteIpAddress.Addr[12],
933 IP->RemoteIpAddress.Addr[13],
934 IP->RemoteIpAddress.Addr[14],
935 IP->RemoteIpAddress.Addr[15]
936 );
937 return ;
938 }
939
940 CatPrint (
941 Str,
942 L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x,%s,%s,%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",
943 IP->RemoteIpAddress.Addr[0],
944 IP->RemoteIpAddress.Addr[1],
945 IP->RemoteIpAddress.Addr[2],
946 IP->RemoteIpAddress.Addr[3],
947 IP->RemoteIpAddress.Addr[4],
948 IP->RemoteIpAddress.Addr[5],
949 IP->RemoteIpAddress.Addr[6],
950 IP->RemoteIpAddress.Addr[7],
951 IP->RemoteIpAddress.Addr[8],
952 IP->RemoteIpAddress.Addr[9],
953 IP->RemoteIpAddress.Addr[10],
954 IP->RemoteIpAddress.Addr[11],
955 IP->RemoteIpAddress.Addr[12],
956 IP->RemoteIpAddress.Addr[13],
957 IP->RemoteIpAddress.Addr[14],
958 IP->RemoteIpAddress.Addr[15],
959 IP->Protocol ? L"TCP" : L"UDP",
960 (IP->StaticIpAddress == TRUE) ? L"Static" : L"DHCP",
961 IP->LocalIpAddress.Addr[0],
962 IP->LocalIpAddress.Addr[1],
963 IP->LocalIpAddress.Addr[2],
964 IP->LocalIpAddress.Addr[3],
965 IP->LocalIpAddress.Addr[4],
966 IP->LocalIpAddress.Addr[5],
967 IP->LocalIpAddress.Addr[6],
968 IP->LocalIpAddress.Addr[7],
969 IP->LocalIpAddress.Addr[8],
970 IP->LocalIpAddress.Addr[9],
971 IP->LocalIpAddress.Addr[10],
972 IP->LocalIpAddress.Addr[11],
973 IP->LocalIpAddress.Addr[12],
974 IP->LocalIpAddress.Addr[13],
975 IP->LocalIpAddress.Addr[14],
976 IP->LocalIpAddress.Addr[15]
977 );
978 }
979
980 STATIC
981 VOID
982 DevPathToTextInfiniBand (
983 IN OUT POOL_PRINT *Str,
984 IN VOID *DevPath,
985 IN BOOLEAN DisplayOnly,
986 IN BOOLEAN AllowShortcuts
987 )
988 {
989 INFINIBAND_DEVICE_PATH *InfiniBand;
990
991 InfiniBand = DevPath;
992 CatPrint (
993 Str,
994 L"Infiniband(%x,%g,%lx,%lx,%lx)",
995 InfiniBand->ResourceFlags,
996 InfiniBand->PortGid,
997 InfiniBand->ServiceId,
998 InfiniBand->TargetPortId,
999 InfiniBand->DeviceId
1000 );
1001 }
1002
1003 STATIC
1004 VOID
1005 DevPathToTextUart (
1006 IN OUT POOL_PRINT *Str,
1007 IN VOID *DevPath,
1008 IN BOOLEAN DisplayOnly,
1009 IN BOOLEAN AllowShortcuts
1010 )
1011 {
1012 UART_DEVICE_PATH *Uart;
1013 CHAR8 Parity;
1014
1015 Uart = DevPath;
1016 switch (Uart->Parity) {
1017 case 0:
1018 Parity = 'D';
1019 break;
1020
1021 case 1:
1022 Parity = 'N';
1023 break;
1024
1025 case 2:
1026 Parity = 'E';
1027 break;
1028
1029 case 3:
1030 Parity = 'O';
1031 break;
1032
1033 case 4:
1034 Parity = 'M';
1035 break;
1036
1037 case 5:
1038 Parity = 'S';
1039 break;
1040
1041 default:
1042 Parity = 'x';
1043 break;
1044 }
1045
1046 if (Uart->BaudRate == 0) {
1047 CatPrint (Str, L"Uart(DEFAULT,");
1048 } else {
1049 CatPrint (Str, L"Uart(%ld,", Uart->BaudRate);
1050 }
1051
1052 if (Uart->DataBits == 0) {
1053 CatPrint (Str, L"DEFAULT,");
1054 } else {
1055 CatPrint (Str, L"%d,", Uart->DataBits);
1056 }
1057
1058 CatPrint (Str, L"%c,", Parity);
1059
1060 switch (Uart->StopBits) {
1061 case 0:
1062 CatPrint (Str, L"D)");
1063 break;
1064
1065 case 1:
1066 CatPrint (Str, L"1)");
1067 break;
1068
1069 case 2:
1070 CatPrint (Str, L"1.5)");
1071 break;
1072
1073 case 3:
1074 CatPrint (Str, L"2)");
1075 break;
1076
1077 default:
1078 CatPrint (Str, L"x)");
1079 break;
1080 }
1081 }
1082
1083 STATIC
1084 VOID
1085 DevPathToTextiSCSI (
1086 IN OUT POOL_PRINT *Str,
1087 IN VOID *DevPath,
1088 IN BOOLEAN DisplayOnly,
1089 IN BOOLEAN AllowShortcuts
1090 )
1091 {
1092 ISCSI_DEVICE_PATH_WITH_NAME *iSCSI;
1093 UINT16 Options;
1094
1095 iSCSI = DevPath;
1096 CatPrint (
1097 Str,
1098 L"iSCSI(%s,%x,%lx,",
1099 iSCSI->iSCSITargetName,
1100 iSCSI->TargetPortalGroupTag,
1101 iSCSI->Lun
1102 );
1103
1104 Options = iSCSI->LoginOption;
1105 CatPrint (Str, L"%s,", ((Options >> 1) & 0x0001) ? L"CRC32C" : L"None");
1106 CatPrint (Str, L"%s,", ((Options >> 3) & 0x0001) ? L"CRC32C" : L"None");
1107 if ((Options >> 11) & 0x0001) {
1108 CatPrint (Str, L"%s,", L"None");
1109 } else if ((Options >> 12) & 0x0001) {
1110 CatPrint (Str, L"%s,", L"CHAP_UNI");
1111 } else {
1112 CatPrint (Str, L"%s,", L"CHAP_BI");
1113
1114 }
1115
1116 CatPrint (Str, L"%s)", (iSCSI->NetworkProtocol == 0) ? L"TCP" : L"reserved");
1117 }
1118
1119 STATIC
1120 VOID
1121 DevPathToTextHardDrive (
1122 IN OUT POOL_PRINT *Str,
1123 IN VOID *DevPath,
1124 IN BOOLEAN DisplayOnly,
1125 IN BOOLEAN AllowShortcuts
1126 )
1127 {
1128 HARDDRIVE_DEVICE_PATH *Hd;
1129
1130 Hd = DevPath;
1131 switch (Hd->SignatureType) {
1132 case 0:
1133 CatPrint (
1134 Str,
1135 L"HD(%d,%s,0,",
1136 Hd->PartitionNumber,
1137 L"None"
1138 );
1139 break;
1140
1141 case SIGNATURE_TYPE_MBR:
1142 CatPrint (
1143 Str,
1144 L"HD(%d,%s,%08x,",
1145 Hd->PartitionNumber,
1146 L"MBR",
1147 *((UINT32 *) (&(Hd->Signature[0])))
1148 );
1149 break;
1150
1151 case SIGNATURE_TYPE_GUID:
1152 CatPrint (
1153 Str,
1154 L"HD(%d,%s,%g,",
1155 Hd->PartitionNumber,
1156 L"GUID",
1157 (EFI_GUID *) &(Hd->Signature[0])
1158 );
1159 break;
1160
1161 default:
1162 break;
1163 }
1164
1165 CatPrint (Str, L"%lx,%lx)", Hd->PartitionStart, Hd->PartitionSize);
1166 }
1167
1168 STATIC
1169 VOID
1170 DevPathToTextCDROM (
1171 IN OUT POOL_PRINT *Str,
1172 IN VOID *DevPath,
1173 IN BOOLEAN DisplayOnly,
1174 IN BOOLEAN AllowShortcuts
1175 )
1176 {
1177 CDROM_DEVICE_PATH *Cd;
1178
1179 Cd = DevPath;
1180 if (DisplayOnly == TRUE) {
1181 CatPrint (Str, L"CDROM(%x)", Cd->BootEntry);
1182 return ;
1183 }
1184
1185 CatPrint (Str, L"CDROM(%x,%lx,%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize);
1186 }
1187
1188 STATIC
1189 VOID
1190 DevPathToTextFilePath (
1191 IN OUT POOL_PRINT *Str,
1192 IN VOID *DevPath,
1193 IN BOOLEAN DisplayOnly,
1194 IN BOOLEAN AllowShortcuts
1195 )
1196 {
1197 FILEPATH_DEVICE_PATH *Fp;
1198
1199 Fp = DevPath;
1200 CatPrint (Str, L"%s", Fp->PathName);
1201 }
1202
1203 STATIC
1204 VOID
1205 DevPathToTextMediaProtocol (
1206 IN OUT POOL_PRINT *Str,
1207 IN VOID *DevPath,
1208 IN BOOLEAN DisplayOnly,
1209 IN BOOLEAN AllowShortcuts
1210 )
1211 {
1212 MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
1213
1214 MediaProt = DevPath;
1215 CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);
1216 }
1217
1218 STATIC
1219 VOID
1220 DevPathToTextBBS (
1221 IN OUT POOL_PRINT *Str,
1222 IN VOID *DevPath,
1223 IN BOOLEAN DisplayOnly,
1224 IN BOOLEAN AllowShortcuts
1225 )
1226 {
1227 BBS_BBS_DEVICE_PATH *Bbs;
1228 CHAR16 *Type;
1229
1230 Bbs = DevPath;
1231 switch (Bbs->DeviceType) {
1232 case BBS_TYPE_FLOPPY:
1233 Type = L"Floppy";
1234 break;
1235
1236 case BBS_TYPE_HARDDRIVE:
1237 Type = L"HD";
1238 break;
1239
1240 case BBS_TYPE_CDROM:
1241 Type = L"CDROM";
1242 break;
1243
1244 case BBS_TYPE_PCMCIA:
1245 Type = L"PCMCIA";
1246 break;
1247
1248 case BBS_TYPE_USB:
1249 Type = L"USB";
1250 break;
1251
1252 case BBS_TYPE_EMBEDDED_NETWORK:
1253 Type = L"Network";
1254 break;
1255
1256 default:
1257 Type = L"?";
1258 break;
1259 }
1260
1261 CatPrint (Str, L"BBS(%s,%a", Type, Bbs->String);
1262
1263 if (DisplayOnly == TRUE) {
1264 CatPrint (Str, L")");
1265 return ;
1266 }
1267
1268 CatPrint (Str, L",%x)", Bbs->StatusFlag);
1269 }
1270
1271 STATIC
1272 VOID
1273 DevPathToTextEndInstance (
1274 IN OUT POOL_PRINT *Str,
1275 IN VOID *DevPath,
1276 IN BOOLEAN DisplayOnly,
1277 IN BOOLEAN AllowShortcuts
1278 )
1279 {
1280 CatPrint (Str, L",");
1281 }
1282
1283 STATIC
1284 VOID
1285 DevPathToTextNodeUnknown (
1286 IN OUT POOL_PRINT *Str,
1287 IN VOID *DevPath,
1288 IN BOOLEAN DisplayOnly,
1289 IN BOOLEAN AllowShortcuts
1290 )
1291 {
1292 CatPrint (Str, L"?");
1293 }
1294
1295 GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_TABLE DevPathToTextTable[] = {
1296 {HARDWARE_DEVICE_PATH, HW_PCI_DP, DevPathToTextPci},
1297 {HARDWARE_DEVICE_PATH, HW_PCCARD_DP, DevPathToTextPccard},
1298 {HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, DevPathToTextMemMap},
1299 {HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DevPathToTextVendor},
1300 {HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, DevPathToTextController},
1301 {ACPI_DEVICE_PATH, ACPI_DP, DevPathToTextAcpi},
1302 {ACPI_DEVICE_PATH, ACPI_EXTENDED_DP, DevPathToTextExtAcpi},
1303 {MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, DevPathToTextAtapi},
1304 {MESSAGING_DEVICE_PATH, MSG_SCSI_DP, DevPathToTextScsi},
1305 {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, DevPathToTextFibre},
1306 {MESSAGING_DEVICE_PATH, MSG_1394_DP, DevPathToText1394},
1307 {MESSAGING_DEVICE_PATH, MSG_USB_DP, DevPathToTextUsb},
1308 {MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP, DevPathToTextUsbWWID},
1309 {MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP, DevPathToTextLogicalUnit},
1310 {MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, DevPathToTextUsbClass},
1311 {MESSAGING_DEVICE_PATH, MSG_I2O_DP, DevPathToTextI2O},
1312 {MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, DevPathToTextMacAddr},
1313 {MESSAGING_DEVICE_PATH, MSG_IPv4_DP, DevPathToTextIPv4},
1314 {MESSAGING_DEVICE_PATH, MSG_IPv6_DP, DevPathToTextIPv6},
1315 {MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, DevPathToTextInfiniBand},
1316 {MESSAGING_DEVICE_PATH, MSG_UART_DP, DevPathToTextUart},
1317 {MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, DevPathToTextVendor},
1318 {MESSAGING_DEVICE_PATH, MSG_ISCSI_DP, DevPathToTextiSCSI},
1319 {MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, DevPathToTextHardDrive},
1320 {MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, DevPathToTextCDROM},
1321 {MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, DevPathToTextVendor},
1322 {MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, DevPathToTextFilePath},
1323 {MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, DevPathToTextMediaProtocol},
1324 {MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, DevPathToTextFilePath},
1325 {BBS_DEVICE_PATH, BBS_BBS_DP, DevPathToTextBBS},
1326 {END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance},
1327 {0, 0, NULL}
1328 };
1329
1330 CHAR16 *
1331 ConvertDeviceNodeToText (
1332 IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode,
1333 IN BOOLEAN DisplayOnly,
1334 IN BOOLEAN AllowShortcuts
1335 )
1336 /*++
1337
1338 Routine Description:
1339 Convert a device node to its text representation.
1340
1341 Arguments:
1342 DeviceNode - Points to the device node to be converted.
1343 DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation
1344 of the display node is used, where applicable. If DisplayOnly
1345 is FALSE, then the longer text representation of the display node
1346 is used.
1347 AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text
1348 representation for a device node can be used, where applicable.
1349
1350 Returns:
1351 A pointer - a pointer to the allocated text representation of the device node.
1352 NULL - if DeviceNode is NULL or there was insufficient memory.
1353
1354 --*/
1355 {
1356 POOL_PRINT Str;
1357 UINTN Index;
1358 UINTN NewSize;
1359 VOID (*DumpNode)(POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN);
1360
1361 if (DeviceNode == NULL) {
1362 return NULL;
1363 }
1364
1365 ZeroMem (&Str, sizeof (Str));
1366
1367 //
1368 // Process the device path node
1369 //
1370 DumpNode = NULL;
1371 for (Index = 0; DevPathToTextTable[Index].Function != NULL; Index++) {
1372 if (DevicePathType (DeviceNode) == DevPathToTextTable[Index].Type &&
1373 DevicePathSubType (DeviceNode) == DevPathToTextTable[Index].SubType
1374 ) {
1375 DumpNode = DevPathToTextTable[Index].Function;
1376 break;
1377 }
1378 }
1379 //
1380 // If not found, use a generic function
1381 //
1382 if (DumpNode == NULL) {
1383 DumpNode = DevPathToTextNodeUnknown;
1384 }
1385
1386 //
1387 // Print this node
1388 //
1389 DumpNode (&Str, (VOID *) DeviceNode, DisplayOnly, AllowShortcuts);
1390
1391 //
1392 // Shrink pool used for string allocation
1393 //
1394 NewSize = (Str.Len + 1) * sizeof (CHAR16);
1395 Str.Str = ReallocatePool (Str.Str, NewSize, NewSize);
1396 ASSERT (Str.Str != NULL);
1397 Str.Str[Str.Len] = 0;
1398 return Str.Str;
1399 }
1400
1401 CHAR16 *
1402 ConvertDevicePathToText (
1403 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1404 IN BOOLEAN DisplayOnly,
1405 IN BOOLEAN AllowShortcuts
1406 )
1407 /*++
1408
1409 Routine Description:
1410 Convert a device path to its text representation.
1411
1412 Arguments:
1413 DeviceNode - Points to the device path to be converted.
1414 DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation
1415 of the display node is used, where applicable. If DisplayOnly
1416 is FALSE, then the longer text representation of the display node
1417 is used.
1418 AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text
1419 representation for a device node can be used, where applicable.
1420
1421 Returns:
1422 A pointer - a pointer to the allocated text representation of the device path.
1423 NULL - if DeviceNode is NULL or there was insufficient memory.
1424
1425 --*/
1426 {
1427 POOL_PRINT Str;
1428 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1429 EFI_DEVICE_PATH_PROTOCOL *UnpackDevPath;
1430 UINTN Index;
1431 UINTN NewSize;
1432 VOID (*DumpNode) (POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN);
1433
1434 if (DevicePath == NULL) {
1435 return NULL;
1436 }
1437
1438 ZeroMem (&Str, sizeof (Str));
1439
1440 //
1441 // Unpacked the device path
1442 //
1443 UnpackDevPath = UnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath);
1444 ASSERT (UnpackDevPath != NULL);
1445
1446 //
1447 // Process each device path node
1448 //
1449 DevPathNode = UnpackDevPath;
1450 while (!IsDevicePathEnd (DevPathNode)) {
1451 //
1452 // Find the handler to dump this device path node
1453 //
1454 DumpNode = NULL;
1455 for (Index = 0; DevPathToTextTable[Index].Function; Index += 1) {
1456
1457 if (DevicePathType (DevPathNode) == DevPathToTextTable[Index].Type &&
1458 DevicePathSubType (DevPathNode) == DevPathToTextTable[Index].SubType
1459 ) {
1460 DumpNode = DevPathToTextTable[Index].Function;
1461 break;
1462 }
1463 }
1464 //
1465 // If not found, use a generic function
1466 //
1467 if (!DumpNode) {
1468 DumpNode = DevPathToTextNodeUnknown;
1469 }
1470 //
1471 // Put a path seperator in if needed
1472 //
1473 if (Str.Len && DumpNode != DevPathToTextEndInstance) {
1474 if (*(Str.Str + Str.Len / sizeof (CHAR16) - 1) != L',') {
1475 CatPrint (&Str, L"/");
1476 }
1477 }
1478 //
1479 // Print this node of the device path
1480 //
1481 DumpNode (&Str, DevPathNode, DisplayOnly, AllowShortcuts);
1482
1483 //
1484 // Next device path node
1485 //
1486 DevPathNode = NextDevicePathNode (DevPathNode);
1487 }
1488 //
1489 // Shrink pool used for string allocation
1490 //
1491 gBS->FreePool (UnpackDevPath);
1492
1493 NewSize = (Str.Len + 1) * sizeof (CHAR16);
1494 Str.Str = ReallocatePool (Str.Str, NewSize, NewSize);
1495 ASSERT (Str.Str != NULL);
1496 Str.Str[Str.Len] = 0;
1497 return Str.Str;
1498 }