dpath.c revision 1.1 1 /* $NetBSD: dpath.c,v 1.1 2014/04/01 16:16:06 jakllsch Exp $ */
2
3 /*++
4
5 Copyright (c) 1998 Intel Corporation
6
7 Module Name:
8
9 dpath.c
10
11 Abstract:
12 MBR & Device Path functions
13
14
15
16 Revision History
17
18 --*/
19
20 #include "lib.h"
21
22 #define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
23
24
25
26 EFI_DEVICE_PATH *
27 DevicePathFromHandle (
28 IN EFI_HANDLE Handle
29 )
30 {
31 EFI_STATUS Status;
32 EFI_DEVICE_PATH *DevicePath;
33
34 Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DevicePathProtocol, (VOID*)&DevicePath);
35 if (EFI_ERROR(Status)) {
36 DevicePath = NULL;
37 }
38
39 return DevicePath;
40 }
41
42
43 EFI_DEVICE_PATH *
44 DevicePathInstance (
45 IN OUT EFI_DEVICE_PATH **DevicePath,
46 OUT UINTN *Size
47 )
48 {
49 EFI_DEVICE_PATH *Start, *Next, *DevPath;
50 UINTN Count;
51
52 DevPath = *DevicePath;
53 Start = DevPath;
54
55 if (!DevPath) {
56 return NULL;
57 }
58
59 //
60 // Check for end of device path type
61 //
62
63 for (Count = 0; ; Count++) {
64 Next = NextDevicePathNode(DevPath);
65
66 if (IsDevicePathEndType(DevPath)) {
67 break;
68 }
69
70 if (Count > 01000) {
71 //
72 // BugBug: Debug code to catch bogus device paths
73 //
74 DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) ));
75 DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
76 break;
77 }
78
79 DevPath = Next;
80 }
81
82 ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE ||
83 DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
84
85 //
86 // Set next position
87 //
88
89 if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
90 Next = NULL;
91 }
92
93 *DevicePath = Next;
94
95 //
96 // Return size and start of device path instance
97 //
98
99 *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start);
100 return Start;
101 }
102
103 UINTN
104 DevicePathInstanceCount (
105 IN EFI_DEVICE_PATH *DevicePath
106 )
107 {
108 UINTN Count, Size;
109
110 Count = 0;
111 while (DevicePathInstance(&DevicePath, &Size)) {
112 Count += 1;
113 }
114
115 return Count;
116 }
117
118
119 EFI_DEVICE_PATH *
120 AppendDevicePath (
121 IN EFI_DEVICE_PATH *Src1,
122 IN EFI_DEVICE_PATH *Src2
123 )
124 // Src1 may have multiple "instances" and each instance is appended
125 // Src2 is appended to each instance is Src1. (E.g., it's possible
126 // to append a new instance to the complete device path by passing
127 // it in Src2)
128 {
129 UINTN Src1Size, Src1Inst, Src2Size, Size;
130 EFI_DEVICE_PATH *Dst, *Inst;
131 UINT8 *DstPos;
132
133 //
134 // If there's only 1 path, just duplicate it
135 //
136
137 if (!Src1) {
138 ASSERT (!IsDevicePathUnpacked (Src2));
139 return DuplicateDevicePath (Src2);
140 }
141
142 if (!Src2) {
143 ASSERT (!IsDevicePathUnpacked (Src1));
144 return DuplicateDevicePath (Src1);
145 }
146
147 //
148 // Verify we're not working with unpacked paths
149 //
150
151 // ASSERT (!IsDevicePathUnpacked (Src1));
152 // ASSERT (!IsDevicePathUnpacked (Src2));
153
154 //
155 // Append Src2 to every instance in Src1
156 //
157
158 Src1Size = DevicePathSize(Src1);
159 Src1Inst = DevicePathInstanceCount(Src1);
160 Src2Size = DevicePathSize(Src2);
161 Size = Src1Size * Src1Inst + Src2Size;
162
163 Dst = AllocatePool (Size);
164 if (Dst) {
165 DstPos = (UINT8 *) Dst;
166
167 //
168 // Copy all device path instances
169 //
170
171 while ((Inst = DevicePathInstance (&Src1, &Size))) {
172
173 CopyMem(DstPos, Inst, Size);
174 DstPos += Size;
175
176 CopyMem(DstPos, Src2, Src2Size);
177 DstPos += Src2Size;
178
179 CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
180 DstPos += sizeof(EFI_DEVICE_PATH);
181 }
182
183 // Change last end marker
184 DstPos -= sizeof(EFI_DEVICE_PATH);
185 CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH));
186 }
187
188 return Dst;
189 }
190
191
192 EFI_DEVICE_PATH *
193 AppendDevicePathNode (
194 IN EFI_DEVICE_PATH *Src1,
195 IN EFI_DEVICE_PATH *Src2
196 )
197 // Src1 may have multiple "instances" and each instance is appended
198 // Src2 is a signal device path node (without a terminator) that is
199 // appended to each instance is Src1.
200 {
201 EFI_DEVICE_PATH *Temp, *Eop;
202 UINTN Length;
203
204 //
205 // Build a Src2 that has a terminator on it
206 //
207
208 Length = DevicePathNodeLength(Src2);
209 Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
210 if (!Temp) {
211 return NULL;
212 }
213
214 CopyMem (Temp, Src2, Length);
215 Eop = NextDevicePathNode(Temp);
216 SetDevicePathEndNode(Eop);
217
218 //
219 // Append device paths
220 //
221
222 Src1 = AppendDevicePath (Src1, Temp);
223 FreePool (Temp);
224 return Src1;
225 }
226
227
228 EFI_DEVICE_PATH *
229 FileDevicePath (
230 IN EFI_HANDLE Device OPTIONAL,
231 IN CHAR16 *FileName
232 )
233 /*++
234
235 N.B. Results are allocated from pool. The caller must FreePool
236 the resulting device path structure
237
238 --*/
239 {
240 UINTN Size;
241 FILEPATH_DEVICE_PATH *FilePath;
242 EFI_DEVICE_PATH *Eop, *DevicePath;
243
244 Size = StrSize(FileName);
245 FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
246 DevicePath = NULL;
247
248 if (FilePath) {
249
250 //
251 // Build a file path
252 //
253
254 FilePath->Header.Type = MEDIA_DEVICE_PATH;
255 FilePath->Header.SubType = MEDIA_FILEPATH_DP;
256 SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
257 CopyMem (FilePath->PathName, FileName, Size);
258 Eop = NextDevicePathNode(&FilePath->Header);
259 SetDevicePathEndNode(Eop);
260
261 //
262 // Append file path to device's device path
263 //
264
265 DevicePath = (EFI_DEVICE_PATH *) FilePath;
266 if (Device) {
267 DevicePath = AppendDevicePath (
268 DevicePathFromHandle(Device),
269 DevicePath
270 );
271
272 FreePool(FilePath);
273 }
274 }
275
276 return DevicePath;
277 }
278
279
280
281 UINTN
282 DevicePathSize (
283 IN EFI_DEVICE_PATH *DevPath
284 )
285 {
286 EFI_DEVICE_PATH *Start;
287
288 //
289 // Search for the end of the device path structure
290 //
291
292 Start = DevPath;
293 while (!IsDevicePathEnd(DevPath)) {
294 DevPath = NextDevicePathNode(DevPath);
295 }
296
297 //
298 // Compute the size
299 //
300
301 return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH);
302 }
303
304 EFI_DEVICE_PATH *
305 DuplicateDevicePath (
306 IN EFI_DEVICE_PATH *DevPath
307 )
308 {
309 EFI_DEVICE_PATH *NewDevPath;
310 UINTN Size;
311
312
313 //
314 // Compute the size
315 //
316
317 Size = DevicePathSize (DevPath);
318
319 //
320 // Make a copy
321 //
322
323 NewDevPath = AllocatePool (Size);
324 if (NewDevPath) {
325 CopyMem (NewDevPath, DevPath, Size);
326 }
327
328 return NewDevPath;
329 }
330
331 EFI_DEVICE_PATH *
332 UnpackDevicePath (
333 IN EFI_DEVICE_PATH *DevPath
334 )
335 {
336 EFI_DEVICE_PATH *Src, *Dest, *NewPath;
337 UINTN Size;
338
339 //
340 // Walk device path and round sizes to valid boundries
341 //
342
343 Src = DevPath;
344 Size = 0;
345 for (; ;) {
346 Size += DevicePathNodeLength(Src);
347 Size += ALIGN_SIZE(Size);
348
349 if (IsDevicePathEnd(Src)) {
350 break;
351 }
352
353 Src = NextDevicePathNode(Src);
354 }
355
356
357 //
358 // Allocate space for the unpacked path
359 //
360
361 NewPath = AllocateZeroPool (Size);
362 if (NewPath) {
363
364 ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
365
366 //
367 // Copy each node
368 //
369
370 Src = DevPath;
371 Dest = NewPath;
372 for (; ;) {
373 Size = DevicePathNodeLength(Src);
374 CopyMem (Dest, Src, Size);
375 Size += ALIGN_SIZE(Size);
376 SetDevicePathNodeLength (Dest, Size);
377 Dest->Type |= EFI_DP_TYPE_UNPACKED;
378 Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);
379
380 if (IsDevicePathEnd(Src)) {
381 break;
382 }
383
384 Src = NextDevicePathNode(Src);
385 }
386 }
387
388 return NewPath;
389 }
390
391
392 EFI_DEVICE_PATH*
393 AppendDevicePathInstance (
394 IN EFI_DEVICE_PATH *Src,
395 IN EFI_DEVICE_PATH *Instance
396 )
397 {
398 UINT8 *Ptr;
399 EFI_DEVICE_PATH *DevPath;
400 UINTN SrcSize;
401 UINTN InstanceSize;
402
403 if (Src == NULL) {
404 return DuplicateDevicePath (Instance);
405 }
406 SrcSize = DevicePathSize(Src);
407 InstanceSize = DevicePathSize(Instance);
408 Ptr = AllocatePool (SrcSize + InstanceSize);
409 DevPath = (EFI_DEVICE_PATH *)Ptr;
410 ASSERT(DevPath);
411
412 CopyMem (Ptr, Src, SrcSize);
413 // FreePool (Src);
414
415 while (!IsDevicePathEnd(DevPath)) {
416 DevPath = NextDevicePathNode(DevPath);
417 }
418 //
419 // Convert the End to an End Instance, since we are
420 // appending another instacne after this one its a good
421 // idea.
422 //
423 DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
424
425 DevPath = NextDevicePathNode(DevPath);
426 CopyMem (DevPath, Instance, InstanceSize);
427 return (EFI_DEVICE_PATH *)Ptr;
428 }
429
430 EFI_STATUS
431 LibDevicePathToInterface (
432 IN EFI_GUID *Protocol,
433 IN EFI_DEVICE_PATH *FilePath,
434 OUT VOID **Interface
435 )
436 {
437 EFI_STATUS Status;
438 EFI_HANDLE Device;
439
440 Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &FilePath, &Device);
441
442 if (!EFI_ERROR(Status)) {
443
444 // If we didn't get a direct match return not found
445 Status = EFI_NOT_FOUND;
446
447 if (IsDevicePathEnd(FilePath)) {
448
449 //
450 // It was a direct match, lookup the protocol interface
451 //
452
453 Status =uefi_call_wrapper(BS->HandleProtocol, 3, Device, Protocol, Interface);
454 }
455 }
456
457 //
458 // If there was an error, do not return an interface
459 //
460
461 if (EFI_ERROR(Status)) {
462 *Interface = NULL;
463 }
464
465 return Status;
466 }
467
468 VOID
469 _DevPathPci (
470 IN OUT POOL_PRINT *Str,
471 IN VOID *DevPath
472 )
473 {
474 PCI_DEVICE_PATH *Pci;
475
476 Pci = DevPath;
477 CatPrint(Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);
478 }
479
480 VOID
481 _DevPathPccard (
482 IN OUT POOL_PRINT *Str,
483 IN VOID *DevPath
484 )
485 {
486 PCCARD_DEVICE_PATH *Pccard;
487
488 Pccard = DevPath;
489 CatPrint(Str, L"Pccard(Socket%x)", Pccard->SocketNumber);
490 }
491
492 VOID
493 _DevPathMemMap (
494 IN OUT POOL_PRINT *Str,
495 IN VOID *DevPath
496 )
497 {
498 MEMMAP_DEVICE_PATH *MemMap;
499
500 MemMap = DevPath;
501 CatPrint(Str, L"MemMap(%d:%x-%x)",
502 MemMap->MemoryType,
503 MemMap->StartingAddress,
504 MemMap->EndingAddress
505 );
506 }
507
508 VOID
509 _DevPathController (
510 IN OUT POOL_PRINT *Str,
511 IN VOID *DevPath
512 )
513 {
514 CONTROLLER_DEVICE_PATH *Controller;
515
516 Controller = DevPath;
517 CatPrint(Str, L"Ctrl(%d)",
518 Controller->Controller
519 );
520 }
521
522 VOID
523 _DevPathVendor (
524 IN OUT POOL_PRINT *Str,
525 IN VOID *DevPath
526 )
527 {
528 VENDOR_DEVICE_PATH *Vendor;
529 CHAR16 *Type;
530 UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevPath;
531
532 Vendor = DevPath;
533 switch (DevicePathType(&Vendor->Header)) {
534 case HARDWARE_DEVICE_PATH: Type = L"Hw"; break;
535 case MESSAGING_DEVICE_PATH: Type = L"Msg"; break;
536 case MEDIA_DEVICE_PATH: Type = L"Media"; break;
537 default: Type = L"?"; break;
538 }
539
540 CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid);
541 if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) {
542 //
543 // GUID used by EFI to enumerate an EDD 1.1 device
544 //
545 UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor;
546 CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
547 } else {
548 CatPrint(Str, L")");
549 }
550 }
551
552
553 VOID
554 _DevPathAcpi (
555 IN OUT POOL_PRINT *Str,
556 IN VOID *DevPath
557 )
558 {
559 ACPI_HID_DEVICE_PATH *Acpi;
560
561 Acpi = DevPath;
562 if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
563 CatPrint(Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
564 } else {
565 CatPrint(Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);
566 }
567 }
568
569
570 VOID
571 _DevPathAtapi (
572 IN OUT POOL_PRINT *Str,
573 IN VOID *DevPath
574 )
575 {
576 ATAPI_DEVICE_PATH *Atapi;
577
578 Atapi = DevPath;
579 CatPrint(Str, L"Ata(%s,%s)",
580 Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
581 Atapi->SlaveMaster ? L"Slave" : L"Master"
582 );
583 }
584
585 VOID
586 _DevPathScsi (
587 IN OUT POOL_PRINT *Str,
588 IN VOID *DevPath
589 )
590 {
591 SCSI_DEVICE_PATH *Scsi;
592
593 Scsi = DevPath;
594 CatPrint(Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);
595 }
596
597
598 VOID
599 _DevPathFibre (
600 IN OUT POOL_PRINT *Str,
601 IN VOID *DevPath
602 )
603 {
604 FIBRECHANNEL_DEVICE_PATH *Fibre;
605
606 Fibre = DevPath;
607 CatPrint(Str, L"Fibre(%lx)", Fibre->WWN);
608 }
609
610 VOID
611 _DevPath1394 (
612 IN OUT POOL_PRINT *Str,
613 IN VOID *DevPath
614 )
615 {
616 F1394_DEVICE_PATH *F1394;
617
618 F1394 = DevPath;
619 CatPrint(Str, L"1394(%g)", &F1394->Guid);
620 }
621
622
623
624 VOID
625 _DevPathUsb (
626 IN OUT POOL_PRINT *Str,
627 IN VOID *DevPath
628 )
629 {
630 USB_DEVICE_PATH *Usb;
631
632 Usb = DevPath;
633 CatPrint(Str, L"Usb(%x)", Usb->Port);
634 }
635
636
637 VOID
638 _DevPathI2O (
639 IN OUT POOL_PRINT *Str,
640 IN VOID *DevPath
641 )
642 {
643 I2O_DEVICE_PATH *I2O;
644
645 I2O = DevPath;
646 CatPrint(Str, L"I2O(%x)", I2O->Tid);
647 }
648
649 VOID
650 _DevPathMacAddr (
651 IN OUT POOL_PRINT *Str,
652 IN VOID *DevPath
653 )
654 {
655 MAC_ADDR_DEVICE_PATH *MAC;
656 UINTN HwAddressSize;
657 UINTN Index;
658
659 MAC = DevPath;
660
661 HwAddressSize = sizeof(EFI_MAC_ADDRESS);
662 if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
663 HwAddressSize = 6;
664 }
665
666 CatPrint(Str, L"Mac(");
667
668 for(Index = 0; Index < HwAddressSize; Index++) {
669 CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
670 }
671 CatPrint(Str, L")");
672 }
673
674 VOID
675 _DevPathIPv4 (
676 IN OUT POOL_PRINT *Str,
677 IN VOID *DevPath
678 )
679 {
680 IPv4_DEVICE_PATH *IP;
681
682 IP = DevPath;
683 CatPrint(Str, L"IPv4(not-done)");
684 }
685
686 VOID
687 _DevPathIPv6 (
688 IN OUT POOL_PRINT *Str,
689 IN VOID *DevPath
690 )
691 {
692 IPv6_DEVICE_PATH *IP;
693
694 IP = DevPath;
695 CatPrint(Str, L"IP-v6(not-done)");
696 }
697
698 VOID
699 _DevPathInfiniBand (
700 IN OUT POOL_PRINT *Str,
701 IN VOID *DevPath
702 )
703 {
704 INFINIBAND_DEVICE_PATH *InfiniBand;
705
706 InfiniBand = DevPath;
707 CatPrint(Str, L"InfiniBand(not-done)");
708 }
709
710 VOID
711 _DevPathUart (
712 IN OUT POOL_PRINT *Str,
713 IN VOID *DevPath
714 )
715 {
716 UART_DEVICE_PATH *Uart;
717 CHAR8 Parity;
718
719 Uart = DevPath;
720 switch (Uart->Parity) {
721 case 0 : Parity = 'D'; break;
722 case 1 : Parity = 'N'; break;
723 case 2 : Parity = 'E'; break;
724 case 3 : Parity = 'O'; break;
725 case 4 : Parity = 'M'; break;
726 case 5 : Parity = 'S'; break;
727 default : Parity = 'x'; break;
728 }
729
730 if (Uart->BaudRate == 0) {
731 CatPrint(Str, L"Uart(DEFAULT %c",Uart->BaudRate,Parity);
732 } else {
733 CatPrint(Str, L"Uart(%d %c",Uart->BaudRate,Parity);
734 }
735
736 if (Uart->DataBits == 0) {
737 CatPrint(Str, L"D");
738 } else {
739 CatPrint(Str, L"%d",Uart->DataBits);
740 }
741
742 switch (Uart->StopBits) {
743 case 0 : CatPrint(Str, L"D)"); break;
744 case 1 : CatPrint(Str, L"1)"); break;
745 case 2 : CatPrint(Str, L"1.5)"); break;
746 case 3 : CatPrint(Str, L"2)"); break;
747 default : CatPrint(Str, L"x)"); break;
748 }
749 }
750
751
752 VOID
753 _DevPathHardDrive (
754 IN OUT POOL_PRINT *Str,
755 IN VOID *DevPath
756 )
757 {
758 HARDDRIVE_DEVICE_PATH *Hd;
759
760 Hd = DevPath;
761 switch (Hd->SignatureType) {
762 case SIGNATURE_TYPE_MBR:
763 CatPrint(Str, L"HD(Part%d,Sig%08X)",
764 Hd->PartitionNumber,
765 *((UINT32 *)(&(Hd->Signature[0])))
766 );
767 break;
768 case SIGNATURE_TYPE_GUID:
769 CatPrint(Str, L"HD(Part%d,Sig%g)",
770 Hd->PartitionNumber,
771 (EFI_GUID *) &(Hd->Signature[0])
772 );
773 break;
774 default:
775 CatPrint(Str, L"HD(Part%d,MBRType=%02x,SigType=%02x)",
776 Hd->PartitionNumber,
777 Hd->MBRType,
778 Hd->SignatureType
779 );
780 break;
781 }
782 }
783
784 VOID
785 _DevPathCDROM (
786 IN OUT POOL_PRINT *Str,
787 IN VOID *DevPath
788 )
789 {
790 CDROM_DEVICE_PATH *Cd;
791
792 Cd = DevPath;
793 CatPrint(Str, L"CDROM(Entry%x)", Cd->BootEntry);
794 }
795
796 VOID
797 _DevPathFilePath (
798 IN OUT POOL_PRINT *Str,
799 IN VOID *DevPath
800 )
801 {
802 FILEPATH_DEVICE_PATH *Fp;
803
804 Fp = DevPath;
805 CatPrint(Str, L"%s", Fp->PathName);
806 }
807
808 VOID
809 _DevPathMediaProtocol (
810 IN OUT POOL_PRINT *Str,
811 IN VOID *DevPath
812 )
813 {
814 MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
815
816 MediaProt = DevPath;
817 CatPrint(Str, L"%g", &MediaProt->Protocol);
818 }
819
820 VOID
821 _DevPathBssBss (
822 IN OUT POOL_PRINT *Str,
823 IN VOID *DevPath
824 )
825 {
826 BBS_BBS_DEVICE_PATH *Bss;
827 CHAR16 *Type;
828
829 Bss = DevPath;
830 switch (Bss->DeviceType) {
831 case BBS_TYPE_FLOPPY: Type = L"Floppy"; break;
832 case BBS_TYPE_HARDDRIVE: Type = L"Harddrive"; break;
833 case BBS_TYPE_CDROM: Type = L"CDROM"; break;
834 case BBS_TYPE_PCMCIA: Type = L"PCMCIA"; break;
835 case BBS_TYPE_USB: Type = L"Usb"; break;
836 case BBS_TYPE_EMBEDDED_NETWORK: Type = L"Net"; break;
837 default: Type = L"?"; break;
838 }
839
840 CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
841 }
842
843
844 VOID
845 _DevPathEndInstance (
846 IN OUT POOL_PRINT *Str,
847 IN VOID *DevPath
848 )
849 {
850 CatPrint(Str, L",");
851 }
852
853 VOID
854 _DevPathNodeUnknown (
855 IN OUT POOL_PRINT *Str,
856 IN VOID *DevPath
857 )
858 {
859 CatPrint(Str, L"?");
860 }
861
862
863 struct {
864 UINT8 Type;
865 UINT8 SubType;
866 VOID (*Function)(POOL_PRINT *, VOID *);
867 } DevPathTable[] = {
868 { HARDWARE_DEVICE_PATH, HW_PCI_DP, _DevPathPci},
869 { HARDWARE_DEVICE_PATH, HW_PCCARD_DP, _DevPathPccard},
870 { HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, _DevPathMemMap},
871 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, _DevPathVendor},
872 { HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, _DevPathController},
873 { ACPI_DEVICE_PATH, ACPI_DP, _DevPathAcpi},
874 { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, _DevPathAtapi},
875 { MESSAGING_DEVICE_PATH, MSG_SCSI_DP, _DevPathScsi},
876 { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, _DevPathFibre},
877 { MESSAGING_DEVICE_PATH, MSG_1394_DP, _DevPath1394},
878 { MESSAGING_DEVICE_PATH, MSG_USB_DP, _DevPathUsb},
879 { MESSAGING_DEVICE_PATH, MSG_I2O_DP, _DevPathI2O},
880 { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, _DevPathMacAddr},
881 { MESSAGING_DEVICE_PATH, MSG_IPv4_DP, _DevPathIPv4},
882 { MESSAGING_DEVICE_PATH, MSG_IPv6_DP, _DevPathIPv6},
883 { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, _DevPathInfiniBand},
884 { MESSAGING_DEVICE_PATH, MSG_UART_DP, _DevPathUart},
885 { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, _DevPathVendor},
886 { MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, _DevPathHardDrive},
887 { MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, _DevPathCDROM},
888 { MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, _DevPathVendor},
889 { MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, _DevPathFilePath},
890 { MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, _DevPathMediaProtocol},
891 { BBS_DEVICE_PATH, BBS_BBS_DP, _DevPathBssBss},
892 { END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
893 { 0, 0, NULL}
894 };
895
896
897 CHAR16 *
898 DevicePathToStr (
899 EFI_DEVICE_PATH *DevPath
900 )
901 /*++
902
903 Turns the Device Path into a printable string. Allcoates
904 the string from pool. The caller must FreePool the returned
905 string.
906
907 --*/
908 {
909 POOL_PRINT Str;
910 EFI_DEVICE_PATH *DevPathNode;
911 VOID (*DumpNode)(POOL_PRINT *, VOID *);
912 UINTN Index, NewSize;
913
914 ZeroMem(&Str, sizeof(Str));
915
916 //
917 // Unpacked the device path
918 //
919
920 DevPath = UnpackDevicePath(DevPath);
921 ASSERT (DevPath);
922
923
924 //
925 // Process each device path node
926 //
927
928 DevPathNode = DevPath;
929 while (!IsDevicePathEnd(DevPathNode)) {
930 //
931 // Find the handler to dump this device path node
932 //
933
934 DumpNode = NULL;
935 for (Index = 0; DevPathTable[Index].Function; Index += 1) {
936
937 if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
938 DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
939 DumpNode = DevPathTable[Index].Function;
940 break;
941 }
942 }
943
944 //
945 // If not found, use a generic function
946 //
947
948 if (!DumpNode) {
949 DumpNode = _DevPathNodeUnknown;
950 }
951
952 //
953 // Put a path seperator in if needed
954 //
955
956 if (Str.len && DumpNode != _DevPathEndInstance) {
957 CatPrint (&Str, L"/");
958 }
959
960 //
961 // Print this node of the device path
962 //
963
964 DumpNode (&Str, DevPathNode);
965
966 //
967 // Next device path node
968 //
969
970 DevPathNode = NextDevicePathNode(DevPathNode);
971 }
972
973 //
974 // Shrink pool used for string allocation
975 //
976
977 FreePool (DevPath);
978 NewSize = (Str.len + 1) * sizeof(CHAR16);
979 Str.str = ReallocatePool (Str.str, NewSize, NewSize);
980 Str.str[Str.len] = 0;
981 return Str.str;
982 }
983
984 BOOLEAN
985 LibMatchDevicePaths (
986 IN EFI_DEVICE_PATH *Multi,
987 IN EFI_DEVICE_PATH *Single
988 )
989 {
990 EFI_DEVICE_PATH *DevicePath, *DevicePathInst;
991 UINTN Size;
992
993 if (!Multi || !Single) {
994 return FALSE;
995 }
996
997 DevicePath = Multi;
998 while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
999 if (CompareMem (Single, DevicePathInst, Size) == 0) {
1000 return TRUE;
1001 }
1002 }
1003 return FALSE;
1004 }
1005
1006 EFI_DEVICE_PATH *
1007 LibDuplicateDevicePathInstance (
1008 IN EFI_DEVICE_PATH *DevPath
1009 )
1010 {
1011 EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp;
1012 UINTN Size;
1013
1014 //
1015 // get the size of an instance from the input
1016 //
1017
1018 Temp = DevPath;
1019 DevicePathInst = DevicePathInstance (&Temp, &Size);
1020
1021 //
1022 // Make a copy and set proper end type
1023 //
1024 NewDevPath = NULL;
1025 if (Size) {
1026 NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
1027 }
1028
1029 if (NewDevPath) {
1030 CopyMem (NewDevPath, DevicePathInst, Size);
1031 Temp = NextDevicePathNode(NewDevPath);
1032 SetDevicePathEndNode(Temp);
1033 }
1034
1035 return NewDevPath;
1036 }
1037
1038