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