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