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