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