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