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