]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Library/EdkGenericBdsLib/DevicePath.c
f0debd566226dbd4b36ac1379cb380a48dace8a1
[mirror_edk2.git] / EdkModulePkg / Library / EdkGenericBdsLib / DevicePath.c
1 /*++
2
3 Copyright (c) 2006 - 2007, 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 DevicePath.c
15
16 Abstract:
17
18 BDS internal function define the default device path string, it can be
19 replaced by platform device path.
20
21 --*/
22
23 EFI_GUID mEfiUnixThunkProtocolGuid = EFI_UNIX_THUNK_PROTOCOL_GUID;
24 EFI_GUID mEfiUnixUgaGuid = EFI_UNIX_UGA_GUID;
25 EFI_GUID mEfiMsgPcAnsiGuid = DEVICE_PATH_MESSAGING_PC_ANSI;
26 EFI_GUID mEfiMsgVt100Guid = DEVICE_PATH_MESSAGING_VT_100;
27 EFI_GUID mEfiMsgVt100PlusGuid = DEVICE_PATH_MESSAGING_VT_100_PLUS;
28 EFI_GUID mEfiMsgVt100Utf8Guid = DEVICE_PATH_MESSAGING_VT_UTF8;
29
30 VOID *
31 ReallocatePool (
32 IN VOID *OldPool,
33 IN UINTN OldSize,
34 IN UINTN NewSize
35 )
36 /*++
37
38 Routine Description:
39
40 Adjusts the size of a previously allocated buffer.
41
42 Arguments:
43
44 OldPool - A pointer to the buffer whose size is being adjusted.
45
46 OldSize - The size of the current buffer.
47
48 NewSize - The size of the new buffer.
49
50 Returns:
51
52 EFI_SUCEESS - The requested number of bytes were allocated.
53
54 EFI_OUT_OF_RESOURCES - The pool requested could not be allocated.
55
56 EFI_INVALID_PARAMETER - The buffer was invalid.
57
58 --*/
59 {
60 VOID *NewPool;
61
62 NewPool = NULL;
63 if (NewSize) {
64 NewPool = AllocateZeroPool (NewSize);
65 }
66
67 if (OldPool) {
68 if (NewPool) {
69 CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
70 }
71
72 gBS->FreePool (OldPool);
73 }
74
75 return NewPool;
76 }
77
78 CHAR16 *
79 CatPrint (
80 IN OUT POOL_PRINT *Str,
81 IN CHAR16 *fmt,
82 ...
83 )
84 /*++
85
86 Routine Description:
87
88 Concatenates a formatted unicode string to allocated pool.
89 The caller must free the resulting buffer.
90
91 Arguments:
92
93 Str - Tracks the allocated pool, size in use, and
94 amount of pool allocated.
95
96 fmt - The format string
97
98 Returns:
99
100 Allocated buffer with the formatted string printed in it.
101 The caller must free the allocated buffer. The buffer
102 allocation is not packed.
103
104 --*/
105 {
106 UINT16 *AppendStr;
107 VA_LIST args;
108 UINTN strsize;
109
110 AppendStr = AllocateZeroPool (0x1000);
111 if (AppendStr == NULL) {
112 return Str->str;
113 }
114
115 VA_START (args, fmt);
116 UnicodeVSPrint (AppendStr, 0x1000, fmt, args);
117 VA_END (args);
118 if (NULL == Str->str) {
119 strsize = StrSize (AppendStr);
120 Str->str = AllocateZeroPool (strsize);
121 ASSERT (Str->str != NULL);
122 } else {
123 strsize = StrSize (AppendStr) + StrSize (Str->str) - sizeof (UINT16);
124 Str->str = ReallocatePool (
125 Str->str,
126 StrSize (Str->str),
127 strsize
128 );
129 ASSERT (Str->str != NULL);
130 }
131
132 Str->maxlen = MAX_CHAR * sizeof (UINT16);
133 if (strsize < Str->maxlen) {
134 StrCat (Str->str, AppendStr);
135 Str->len = strsize - sizeof (UINT16);
136 }
137
138 gBS->FreePool (AppendStr);
139 return Str->str;
140 }
141
142 EFI_DEVICE_PATH_PROTOCOL *
143 BdsLibUnpackDevicePath (
144 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
145 )
146 /*++
147
148 Routine Description:
149
150 Function unpacks a device path data structure so that all the nodes
151 of a device path are naturally aligned.
152
153 Arguments:
154
155 DevPath - A pointer to a device path data structure
156
157 Returns:
158
159 If the memory for the device path is successfully allocated, then a
160 pointer to the new device path is returned. Otherwise, NULL is returned.
161
162 --*/
163 {
164 EFI_DEVICE_PATH_PROTOCOL *Src;
165 EFI_DEVICE_PATH_PROTOCOL *Dest;
166 EFI_DEVICE_PATH_PROTOCOL *NewPath;
167 UINTN Size;
168
169 //
170 // Walk device path and round sizes to valid boundries
171 //
172 Src = DevPath;
173 Size = 0;
174 for (;;) {
175 Size += DevicePathNodeLength (Src);
176 Size += ALIGN_SIZE (Size);
177
178 if (IsDevicePathEnd (Src)) {
179 break;
180 }
181
182 Src = NextDevicePathNode (Src);
183 }
184 //
185 // Allocate space for the unpacked path
186 //
187 NewPath = AllocateZeroPool (Size);
188 if (NewPath) {
189
190 ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);
191
192 //
193 // Copy each node
194 //
195 Src = DevPath;
196 Dest = NewPath;
197 for (;;) {
198 Size = DevicePathNodeLength (Src);
199 CopyMem (Dest, Src, Size);
200 Size += ALIGN_SIZE (Size);
201 SetDevicePathNodeLength (Dest, Size);
202 Dest->Type |= EFI_DP_TYPE_UNPACKED;
203 Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);
204
205 if (IsDevicePathEnd (Src)) {
206 break;
207 }
208
209 Src = NextDevicePathNode (Src);
210 }
211 }
212
213 return NewPath;
214 }
215
216 VOID
217 DevPathPci (
218 IN OUT POOL_PRINT *Str,
219 IN VOID *DevPath
220 )
221 {
222 PCI_DEVICE_PATH *Pci;
223
224 Pci = DevPath;
225 CatPrint (Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);
226 }
227
228 VOID
229 DevPathPccard (
230 IN OUT POOL_PRINT *Str,
231 IN VOID *DevPath
232 )
233 {
234 PCCARD_DEVICE_PATH *Pccard;
235
236 Pccard = DevPath;
237 CatPrint (Str, L"Pcmcia(Function%x)", Pccard->FunctionNumber);
238 }
239
240 VOID
241 DevPathMemMap (
242 IN OUT POOL_PRINT *Str,
243 IN VOID *DevPath
244 )
245 {
246 MEMMAP_DEVICE_PATH *MemMap;
247
248 MemMap = DevPath;
249 CatPrint (
250 Str,
251 L"MemMap(%d:%.lx-%.lx)",
252 MemMap->MemoryType,
253 MemMap->StartingAddress,
254 MemMap->EndingAddress
255 );
256 }
257
258 VOID
259 DevPathController (
260 IN OUT POOL_PRINT *Str,
261 IN VOID *DevPath
262 )
263 {
264 CONTROLLER_DEVICE_PATH *Controller;
265
266 Controller = DevPath;
267 CatPrint (Str, L"Ctrl(%d)", Controller->ControllerNumber);
268 }
269
270 VOID
271 DevPathVendor (
272 IN OUT POOL_PRINT *Str,
273 IN VOID *DevPath
274 )
275 /*++
276
277 Routine Description:
278
279 Convert Vendor device path to device name
280
281 Arguments:
282
283 Str - The buffer store device name
284 DevPath - Pointer to vendor device path
285
286 Returns:
287
288 When it return, the device name have been stored in *Str.
289
290 --*/
291 {
292 VENDOR_DEVICE_PATH *Vendor;
293 CHAR16 *Type;
294 INT32 *Temp;
295
296 Vendor = DevPath;
297 Temp = (INT32 *) (&Vendor->Guid);
298
299 switch (DevicePathType (&Vendor->Header)) {
300 case HARDWARE_DEVICE_PATH:
301 //
302 // If the device is an Unix device, we will give it a readable device name.
303 //
304 if (CompareGuid (&Vendor->Guid, &mEfiUnixThunkProtocolGuid)) {
305 CatPrint (Str, L"%s", L"UnixBus");
306 return ;
307 } else if (CompareGuid (&Vendor->Guid, &mEfiUnixUgaGuid)) {
308 CatPrint (Str, L"%s", L"UGA");
309 return ;
310 } else {
311 Type = L"Hw";
312 break;
313 }
314
315 case MESSAGING_DEVICE_PATH:
316 //
317 // If the device is an Unix device, we will give it a readable device name.
318 //
319 if (CompareGuid (&Vendor->Guid, &mEfiMsgPcAnsiGuid)) {
320 CatPrint (Str, L"%s", L"PC-ANSI");
321 return ;
322 } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100Guid)) {
323 CatPrint (Str, L"%s", L"VT100");
324 return ;
325 } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100PlusGuid)) {
326 CatPrint (Str, L"%s", L"VT100+");
327 return ;
328 } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100Utf8Guid)) {
329 CatPrint (Str, L"%s", L"VT100-UTF8");
330 return ;
331 } else {
332 Type = L"Msg";
333 break;
334 }
335
336 case MEDIA_DEVICE_PATH:
337 Type = L"Media";
338 break;
339
340 default:
341 Type = L"?";
342 break;
343 }
344
345 CatPrint (Str, L"Ven%s(%g)", Type, &Vendor->Guid);
346 }
347
348 VOID
349 DevPathAcpi (
350 IN OUT POOL_PRINT *Str,
351 IN VOID *DevPath
352 )
353 {
354 ACPI_HID_DEVICE_PATH *Acpi;
355
356 Acpi = DevPath;
357 if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
358 CatPrint (Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
359 } else {
360 CatPrint (Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);
361 }
362 }
363
364 VOID
365 DevPathAtapi (
366 IN OUT POOL_PRINT *Str,
367 IN VOID *DevPath
368 )
369 {
370 ATAPI_DEVICE_PATH *Atapi;
371
372 Atapi = DevPath;
373 CatPrint (
374 Str,
375 L"Ata(%s,%s)",
376 Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
377 Atapi->SlaveMaster ? L"Slave" : L"Master"
378 );
379 }
380
381 VOID
382 DevPathScsi (
383 IN OUT POOL_PRINT *Str,
384 IN VOID *DevPath
385 )
386 {
387 SCSI_DEVICE_PATH *Scsi;
388
389 Scsi = DevPath;
390 CatPrint (Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);
391 }
392
393 VOID
394 DevPathFibre (
395 IN OUT POOL_PRINT *Str,
396 IN VOID *DevPath
397 )
398 {
399 FIBRECHANNEL_DEVICE_PATH *Fibre;
400
401 Fibre = DevPath;
402 CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);
403 }
404
405 VOID
406 DevPath1394 (
407 IN OUT POOL_PRINT *Str,
408 IN VOID *DevPath
409 )
410 {
411 F1394_DEVICE_PATH *F1394;
412
413 F1394 = DevPath;
414 CatPrint (Str, L"1394(%g)", &F1394->Guid);
415 }
416
417 VOID
418 DevPathUsb (
419 IN OUT POOL_PRINT *Str,
420 IN VOID *DevPath
421 )
422 {
423 USB_DEVICE_PATH *Usb;
424
425 Usb = DevPath;
426 CatPrint (Str, L"Usb(%x, %x)", Usb->ParentPortNumber, Usb->InterfaceNumber);
427 }
428
429 VOID
430 DevPathUsbClass (
431 IN OUT POOL_PRINT *Str,
432 IN VOID *DevPath
433 )
434 {
435 USB_CLASS_DEVICE_PATH *UsbClass;
436
437 UsbClass = DevPath;
438 CatPrint (
439 Str,
440 L"Usb Class(%x, %x, %x, %x, %x)",
441 UsbClass->VendorId,
442 UsbClass->ProductId,
443 UsbClass->DeviceClass,
444 UsbClass->DeviceSubClass,
445 UsbClass->DeviceProtocol
446 );
447 }
448
449 VOID
450 DevPathI2O (
451 IN OUT POOL_PRINT *Str,
452 IN VOID *DevPath
453 )
454 {
455 I2O_DEVICE_PATH *I2O;
456
457 I2O = DevPath;
458 CatPrint (Str, L"I2O(%x)", I2O->Tid);
459 }
460
461 VOID
462 DevPathMacAddr (
463 IN OUT POOL_PRINT *Str,
464 IN VOID *DevPath
465 )
466 {
467 MAC_ADDR_DEVICE_PATH *MAC;
468 UINTN HwAddressSize;
469 UINTN Index;
470
471 MAC = DevPath;
472
473 HwAddressSize = sizeof (EFI_MAC_ADDRESS);
474 if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
475 HwAddressSize = 6;
476 }
477
478 CatPrint (Str, L"Mac(");
479
480 for (Index = 0; Index < HwAddressSize; Index++) {
481 CatPrint (Str, L"%02x", MAC->MacAddress.Addr[Index]);
482 }
483
484 CatPrint (Str, L")");
485 }
486
487 VOID
488 DevPathIPv4 (
489 IN OUT POOL_PRINT *Str,
490 IN VOID *DevPath
491 )
492 {
493 IPv4_DEVICE_PATH *IP;
494
495 IP = DevPath;
496 CatPrint (
497 Str,
498 L"IPv4(%d.%d.%d.%d:%d)",
499 IP->RemoteIpAddress.Addr[0],
500 IP->RemoteIpAddress.Addr[1],
501 IP->RemoteIpAddress.Addr[2],
502 IP->RemoteIpAddress.Addr[3],
503 IP->RemotePort
504 );
505 }
506
507 VOID
508 DevPathIPv6 (
509 IN OUT POOL_PRINT *Str,
510 IN VOID *DevPath
511 )
512 {
513 IPv6_DEVICE_PATH *IP;
514
515 IP = DevPath;
516 CatPrint (Str, L"IP-v6(not-done)");
517 }
518
519 VOID
520 DevPathInfiniBand (
521 IN OUT POOL_PRINT *Str,
522 IN VOID *DevPath
523 )
524 {
525 INFINIBAND_DEVICE_PATH *InfiniBand;
526
527 InfiniBand = DevPath;
528 CatPrint (Str, L"InfiniBand(not-done)");
529 }
530
531 VOID
532 DevPathUart (
533 IN OUT POOL_PRINT *Str,
534 IN VOID *DevPath
535 )
536 {
537 UART_DEVICE_PATH *Uart;
538 CHAR8 Parity;
539
540 Uart = DevPath;
541 switch (Uart->Parity) {
542 case 0:
543 Parity = 'D';
544 break;
545
546 case 1:
547 Parity = 'N';
548 break;
549
550 case 2:
551 Parity = 'E';
552 break;
553
554 case 3:
555 Parity = 'O';
556 break;
557
558 case 4:
559 Parity = 'M';
560 break;
561
562 case 5:
563 Parity = 'S';
564 break;
565
566 default:
567 Parity = 'x';
568 break;
569 }
570
571 if (Uart->BaudRate == 0) {
572 CatPrint (Str, L"Uart(DEFAULT %c", Parity);
573 } else {
574 CatPrint (Str, L"Uart(%d %c", Uart->BaudRate, Parity);
575 }
576
577 if (Uart->DataBits == 0) {
578 CatPrint (Str, L"D");
579 } else {
580 CatPrint (Str, L"%d", Uart->DataBits);
581 }
582
583 switch (Uart->StopBits) {
584 case 0:
585 CatPrint (Str, L"D)");
586 break;
587
588 case 1:
589 CatPrint (Str, L"1)");
590 break;
591
592 case 2:
593 CatPrint (Str, L"1.5)");
594 break;
595
596 case 3:
597 CatPrint (Str, L"2)");
598 break;
599
600 default:
601 CatPrint (Str, L"x)");
602 break;
603 }
604 }
605
606 VOID
607 DevPathHardDrive (
608 IN OUT POOL_PRINT *Str,
609 IN VOID *DevPath
610 )
611 {
612 HARDDRIVE_DEVICE_PATH *Hd;
613
614 Hd = DevPath;
615 switch (Hd->SignatureType) {
616 case SIGNATURE_TYPE_MBR:
617 CatPrint (
618 Str,
619 L"HD(Part%d,Sig%08x)",
620 Hd->PartitionNumber,
621 *((UINT32 *) (&(Hd->Signature[0])))
622 );
623 break;
624
625 case SIGNATURE_TYPE_GUID:
626 CatPrint (
627 Str,
628 L"HD(Part%d,Sig%g)",
629 Hd->PartitionNumber,
630 (EFI_GUID *) &(Hd->Signature[0])
631 );
632 break;
633
634 default:
635 CatPrint (
636 Str,
637 L"HD(Part%d,MBRType=%02x,SigType=%02x)",
638 Hd->PartitionNumber,
639 Hd->MBRType,
640 Hd->SignatureType
641 );
642 break;
643 }
644 }
645
646 VOID
647 DevPathCDROM (
648 IN OUT POOL_PRINT *Str,
649 IN VOID *DevPath
650 )
651 {
652 CDROM_DEVICE_PATH *Cd;
653
654 Cd = DevPath;
655 CatPrint (Str, L"CDROM(Entry%x)", Cd->BootEntry);
656 }
657
658 VOID
659 DevPathFilePath (
660 IN OUT POOL_PRINT *Str,
661 IN VOID *DevPath
662 )
663 {
664 FILEPATH_DEVICE_PATH *Fp;
665
666 Fp = DevPath;
667 CatPrint (Str, L"%s", Fp->PathName);
668 }
669
670 VOID
671 DevPathMediaProtocol (
672 IN OUT POOL_PRINT *Str,
673 IN VOID *DevPath
674 )
675 {
676 MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
677
678 MediaProt = DevPath;
679 CatPrint (Str, L"%g", &MediaProt->Protocol);
680 }
681
682 VOID
683 DevPathFvFilePath (
684 IN OUT POOL_PRINT *Str,
685 IN VOID *DevPath
686 )
687 {
688 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
689
690 FvFilePath = DevPath;
691 CatPrint (Str, L"%g", &FvFilePath->NameGuid);
692 }
693
694 VOID
695 DevPathBssBss (
696 IN OUT POOL_PRINT *Str,
697 IN VOID *DevPath
698 )
699 {
700 BBS_BBS_DEVICE_PATH *Bbs;
701 CHAR16 *Type;
702
703 Bbs = DevPath;
704 switch (Bbs->DeviceType) {
705 case BBS_TYPE_FLOPPY:
706 Type = L"Floppy";
707 break;
708
709 case BBS_TYPE_HARDDRIVE:
710 Type = L"Harddrive";
711 break;
712
713 case BBS_TYPE_CDROM:
714 Type = L"CDROM";
715 break;
716
717 case BBS_TYPE_PCMCIA:
718 Type = L"PCMCIA";
719 break;
720
721 case BBS_TYPE_USB:
722 Type = L"Usb";
723 break;
724
725 case BBS_TYPE_EMBEDDED_NETWORK:
726 Type = L"Net";
727 break;
728
729 default:
730 Type = L"?";
731 break;
732 }
733 //
734 // Since current Print function hasn't implemented %a (for ansi string)
735 // we will only print Unicode strings.
736 //
737 CatPrint (Str, L"Legacy-%s", Type);
738 }
739
740 VOID
741 DevPathEndInstance (
742 IN OUT POOL_PRINT *Str,
743 IN VOID *DevPath
744 )
745 {
746 CatPrint (Str, L",");
747 }
748
749 VOID
750 DevPathNodeUnknown (
751 IN OUT POOL_PRINT *Str,
752 IN VOID *DevPath
753 )
754 {
755 CatPrint (Str, L"?");
756 }
757
758 DEVICE_PATH_STRING_TABLE DevPathTable[] = {
759 {
760 HARDWARE_DEVICE_PATH,
761 HW_PCI_DP,
762 DevPathPci
763 },
764 {
765 HARDWARE_DEVICE_PATH,
766 HW_PCCARD_DP,
767 DevPathPccard
768 },
769 {
770 HARDWARE_DEVICE_PATH,
771 HW_MEMMAP_DP,
772 DevPathMemMap
773 },
774 {
775 HARDWARE_DEVICE_PATH,
776 HW_VENDOR_DP,
777 DevPathVendor
778 },
779 {
780 HARDWARE_DEVICE_PATH,
781 HW_CONTROLLER_DP,
782 DevPathController
783 },
784 {
785 ACPI_DEVICE_PATH,
786 ACPI_DP,
787 DevPathAcpi
788 },
789 {
790 MESSAGING_DEVICE_PATH,
791 MSG_ATAPI_DP,
792 DevPathAtapi
793 },
794 {
795 MESSAGING_DEVICE_PATH,
796 MSG_SCSI_DP,
797 DevPathScsi
798 },
799 {
800 MESSAGING_DEVICE_PATH,
801 MSG_FIBRECHANNEL_DP,
802 DevPathFibre
803 },
804 {
805 MESSAGING_DEVICE_PATH,
806 MSG_1394_DP,
807 DevPath1394
808 },
809 {
810 MESSAGING_DEVICE_PATH,
811 MSG_USB_DP,
812 DevPathUsb
813 },
814 {
815 MESSAGING_DEVICE_PATH,
816 MSG_USB_CLASS_DP,
817 DevPathUsbClass
818 },
819 {
820 MESSAGING_DEVICE_PATH,
821 MSG_I2O_DP,
822 DevPathI2O
823 },
824 {
825 MESSAGING_DEVICE_PATH,
826 MSG_MAC_ADDR_DP,
827 DevPathMacAddr
828 },
829 {
830 MESSAGING_DEVICE_PATH,
831 MSG_IPv4_DP,
832 DevPathIPv4
833 },
834 {
835 MESSAGING_DEVICE_PATH,
836 MSG_IPv6_DP,
837 DevPathIPv6
838 },
839 {
840 MESSAGING_DEVICE_PATH,
841 MSG_INFINIBAND_DP,
842 DevPathInfiniBand
843 },
844 {
845 MESSAGING_DEVICE_PATH,
846 MSG_UART_DP,
847 DevPathUart
848 },
849 {
850 MESSAGING_DEVICE_PATH,
851 MSG_VENDOR_DP,
852 DevPathVendor
853 },
854 {
855 MEDIA_DEVICE_PATH,
856 MEDIA_HARDDRIVE_DP,
857 DevPathHardDrive
858 },
859 {
860 MEDIA_DEVICE_PATH,
861 MEDIA_CDROM_DP,
862 DevPathCDROM
863 },
864 {
865 MEDIA_DEVICE_PATH,
866 MEDIA_VENDOR_DP,
867 DevPathVendor
868 },
869 {
870 MEDIA_DEVICE_PATH,
871 MEDIA_FILEPATH_DP,
872 DevPathFilePath
873 },
874 {
875 MEDIA_DEVICE_PATH,
876 MEDIA_PROTOCOL_DP,
877 DevPathMediaProtocol
878 },
879
880 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
881 {
882 MEDIA_DEVICE_PATH,
883 MEDIA_FV_FILEPATH_DP,
884 DevPathFvFilePath
885 },
886 #endif
887
888 {
889 BBS_DEVICE_PATH,
890 BBS_BBS_DP,
891 DevPathBssBss
892 },
893 {
894 END_DEVICE_PATH_TYPE,
895 END_INSTANCE_DEVICE_PATH_SUBTYPE,
896 DevPathEndInstance
897 },
898 {
899 0,
900 0,
901 NULL
902 }
903 };
904
905 CHAR16 *
906 DevicePathToStr (
907 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
908 )
909 /*++
910
911 Turns the Device Path into a printable string. Allcoates
912 the string from pool. The caller must SafeFreePool the returned
913 string.
914
915 --*/
916 {
917 POOL_PRINT Str;
918 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
919 VOID (*DumpNode) (POOL_PRINT *, VOID *);
920
921 UINTN Index;
922 UINTN NewSize;
923
924 ZeroMem (&Str, sizeof (Str));
925
926 if (DevPath == NULL) {
927 goto Done;
928 }
929 //
930 // Unpacked the device path
931 //
932 DevPath = BdsLibUnpackDevicePath (DevPath);
933 ASSERT (DevPath);
934
935 //
936 // Process each device path node
937 //
938 DevPathNode = DevPath;
939 while (!IsDevicePathEnd (DevPathNode)) {
940 //
941 // Find the handler to dump this device path node
942 //
943 DumpNode = NULL;
944 for (Index = 0; DevPathTable[Index].Function; Index += 1) {
945
946 if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&
947 DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType
948 ) {
949 DumpNode = DevPathTable[Index].Function;
950 break;
951 }
952 }
953 //
954 // If not found, use a generic function
955 //
956 if (!DumpNode) {
957 DumpNode = DevPathNodeUnknown;
958 }
959 //
960 // Put a path seperator in if needed
961 //
962 if (Str.len && DumpNode != DevPathEndInstance) {
963 CatPrint (&Str, L"/");
964 }
965 //
966 // Print this node of the device path
967 //
968 DumpNode (&Str, DevPathNode);
969
970 //
971 // Next device path node
972 //
973 DevPathNode = NextDevicePathNode (DevPathNode);
974 }
975 //
976 // Shrink pool used for string allocation
977 //
978 gBS->FreePool (DevPath);
979
980 Done:
981 NewSize = (Str.len + 1) * sizeof (CHAR16);
982 Str.str = ReallocatePool (Str.str, NewSize, NewSize);
983 ASSERT (Str.str != NULL);
984 Str.str[Str.len] = 0;
985 return Str.str;
986 }
987
988 EFI_DEVICE_PATH_PROTOCOL *
989 LibDuplicateDevicePathInstance (
990 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
991 )
992 /*++
993
994 Routine Description:
995
996 Function creates a device path data structure that identically matches the
997 device path passed in.
998
999 Arguments:
1000
1001 DevPath - A pointer to a device path data structure.
1002
1003 Returns:
1004
1005 The new copy of DevPath is created to identically match the input.
1006 Otherwise, NULL is returned.
1007
1008 --*/
1009 {
1010 EFI_DEVICE_PATH_PROTOCOL *NewDevPath;
1011 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
1012 EFI_DEVICE_PATH_PROTOCOL *Temp;
1013 UINTN Size;
1014
1015 //
1016 // get the size of an instance from the input
1017 //
1018 Temp = DevPath;
1019 DevicePathInst = GetNextDevicePathInstance (&Temp, &Size);
1020
1021 //
1022 // Make a copy
1023 //
1024 NewDevPath = NULL;
1025 if (Size) {
1026 NewDevPath = AllocateZeroPool (Size);
1027 ASSERT (NewDevPath != NULL);
1028 }
1029
1030 if (NewDevPath) {
1031 CopyMem (NewDevPath, DevicePathInst, Size);
1032 }
1033
1034 return NewDevPath;
1035 }