1 /* $NetBSD: dpath.c,v 1.4 2021/09/30 19:02:48 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 // Guid has format of IEEE-EUI64 665 CatPrint(Str, L"I1394(%016lx)", F1394->Guid); 666 } 667 668 669 670 static VOID 671 _DevPathUsb ( 672 IN OUT POOL_PRINT *Str, 673 IN VOID *DevPath 674 ) 675 { 676 USB_DEVICE_PATH *Usb; 677 678 Usb = DevPath; 679 CatPrint( Str , L"Usb(0x%x,0x%x)" , Usb-> Port , Usb-> Endpoint ) ; 680 } 681 682 683 static VOID 684 _DevPathI2O ( 685 IN OUT POOL_PRINT *Str, 686 IN VOID *DevPath 687 ) 688 { 689 I2O_DEVICE_PATH *I2O; 690 691 I2O = DevPath; 692 CatPrint(Str, L"I2O(0x%X)", I2O->Tid); 693 } 694 695 static VOID 696 _DevPathMacAddr ( 697 IN OUT POOL_PRINT *Str, 698 IN VOID *DevPath 699 ) 700 { 701 MAC_ADDR_DEVICE_PATH *MAC; 702 UINTN HwAddressSize; 703 UINTN Index; 704 705 MAC = DevPath; 706 707 /* HwAddressSize = sizeof(EFI_MAC_ADDRESS); */ 708 HwAddressSize = DevicePathNodeLength( & MAC-> Header ) ; 709 HwAddressSize -= sizeof( MAC-> Header ) ; 710 HwAddressSize -= sizeof( MAC-> IfType ) ; 711 if (MAC->IfType == 0x01 || MAC->IfType == 0x00) { 712 HwAddressSize = 6; 713 } 714 715 CatPrint(Str, L"Mac("); 716 717 for(Index = 0; Index < HwAddressSize; Index++) { 718 CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]); 719 } 720 if ( MAC-> IfType != 0 ) { 721 CatPrint(Str, L",%d" , MAC-> IfType ) ; 722 } 723 CatPrint(Str, L")"); 724 } 725 726 static VOID 727 CatPrintIPv4( 728 IN OUT POOL_PRINT * Str , 729 IN EFI_IPv4_ADDRESS * Address 730 ) 731 { 732 CatPrint( Str , L"%d.%d.%d.%d" , Address-> Addr[ 0 ] , Address-> Addr[ 1 ] , 733 Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ; 734 } 735 736 static BOOLEAN 737 IsNotNullIPv4( 738 IN EFI_IPv4_ADDRESS * Address 739 ) 740 { 741 UINT8 val ; 742 val = Address-> Addr[ 0 ] | Address-> Addr[ 1 ] ; 743 val |= Address-> Addr[ 2 ] | Address-> Addr[ 3 ] ; 744 return val != 0 ; 745 } 746 747 static VOID 748 CatPrintNetworkProtocol( 749 IN OUT POOL_PRINT * Str , 750 IN UINT16 Proto 751 ) 752 { 753 if ( Proto == 6 ) { 754 CatPrint( Str , L"TCP" ) ; 755 } else if ( Proto == 17 ) { 756 CatPrint( Str , L"UDP" ) ; 757 } else { 758 CatPrint( Str , L"%d" , Proto ) ; 759 } 760 } 761 762 static VOID 763 _DevPathIPv4 ( 764 IN OUT POOL_PRINT *Str, 765 IN VOID *DevPath 766 ) 767 { 768 IPv4_DEVICE_PATH *IP __unused; 769 BOOLEAN show ; 770 771 IP = DevPath; 772 CatPrint( Str , L"IPv4(") ; 773 CatPrintIPv4( Str , & IP-> RemoteIpAddress ) ; 774 CatPrint( Str , L",") ; 775 CatPrintNetworkProtocol( Str , IP-> Protocol ) ; 776 CatPrint( Str , L",%s" , IP-> StaticIpAddress ? L"Static" : L"DHCP" ) ; 777 show = IsNotNullIPv4( & IP-> LocalIpAddress ) ; 778 if ( ! show && DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) { 779 /* only version 2 includes gateway and netmask */ 780 show |= IsNotNullIPv4( & IP-> GatewayIpAddress ) ; 781 show |= IsNotNullIPv4( & IP-> SubnetMask ) ; 782 } 783 if ( show ) { 784 CatPrint( Str , L"," ) ; 785 CatPrintIPv4( Str , & IP-> LocalIpAddress ) ; 786 if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) { 787 /* only version 2 includes gateway and netmask */ 788 show = IsNotNullIPv4( & IP-> GatewayIpAddress ) ; 789 show |= IsNotNullIPv4( & IP-> SubnetMask ) ; 790 if ( show ) { 791 CatPrint( Str , L",") ; 792 CatPrintIPv4( Str , & IP-> GatewayIpAddress ) ; 793 if ( IsNotNullIPv4( & IP-> SubnetMask ) ) { 794 CatPrint( Str , L",") ; 795 CatPrintIPv4( Str , & IP-> SubnetMask ) ; 796 } 797 } 798 } 799 } 800 CatPrint( Str , L")") ; 801 } 802 803 #define CatPrintIPv6_ADD( x , y ) ( ( (UINT16) ( x ) ) << 8 | ( y ) ) 804 static VOID 805 CatPrintIPv6( 806 IN OUT POOL_PRINT * Str , 807 IN EFI_IPv6_ADDRESS * Address 808 ) 809 { 810 CatPrint( Str , L"%x:%x:%x:%x:%x:%x:%x:%x" , 811 CatPrintIPv6_ADD( Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ) , 812 CatPrintIPv6_ADD( Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) , 813 CatPrintIPv6_ADD( Address-> Addr[ 4 ] , Address-> Addr[ 5 ] ) , 814 CatPrintIPv6_ADD( Address-> Addr[ 6 ] , Address-> Addr[ 7 ] ) , 815 CatPrintIPv6_ADD( Address-> Addr[ 8 ] , Address-> Addr[ 9 ] ) , 816 CatPrintIPv6_ADD( Address-> Addr[ 10 ] , Address-> Addr[ 11 ] ) , 817 CatPrintIPv6_ADD( Address-> Addr[ 12 ] , Address-> Addr[ 13 ] ) , 818 CatPrintIPv6_ADD( Address-> Addr[ 14 ] , Address-> Addr[ 15 ] ) ) ; 819 } 820 821 static VOID 822 _DevPathIPv6 ( 823 IN OUT POOL_PRINT *Str, 824 IN VOID *DevPath 825 ) 826 { 827 IPv6_DEVICE_PATH *IP __unused; 828 829 IP = DevPath; 830 CatPrint( Str , L"IPv6(") ; 831 CatPrintIPv6( Str , & IP-> RemoteIpAddress ) ; 832 CatPrint( Str , L",") ; 833 CatPrintNetworkProtocol( Str, IP-> Protocol ) ; 834 CatPrint( Str , L",%s," , IP-> IPAddressOrigin ? 835 ( IP-> IPAddressOrigin == 1 ? L"StatelessAutoConfigure" : 836 L"StatefulAutoConfigure" ) : L"Static" ) ; 837 CatPrintIPv6( Str , & IP-> LocalIpAddress ) ; 838 if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv6_DEVICE_PATH ) ) { 839 CatPrint( Str , L",") ; 840 CatPrintIPv6( Str , & IP-> GatewayIpAddress ) ; 841 CatPrint( Str , L",") ; 842 CatPrint( Str , L"%d" , & IP-> PrefixLength ) ; 843 } 844 CatPrint( Str , L")") ; 845 } 846 847 static VOID 848 _DevPathUri ( 849 IN OUT POOL_PRINT *Str, 850 IN VOID *DevPath 851 ) 852 { 853 URI_DEVICE_PATH *Uri; 854 855 Uri = DevPath; 856 857 CatPrint( Str, L"Uri(%a)", Uri->Uri ); 858 } 859 860 static VOID 861 _DevPathInfiniBand ( 862 IN OUT POOL_PRINT *Str, 863 IN VOID *DevPath 864 ) 865 { 866 INFINIBAND_DEVICE_PATH *InfiniBand __unused; 867 868 InfiniBand = DevPath; 869 CatPrint(Str, L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)", 870 InfiniBand->ResourceFlags, InfiniBand->PortGid, InfiniBand->ServiceId, 871 InfiniBand->TargetPortId, InfiniBand->DeviceId); 872 } 873 874 static VOID 875 _DevPathUart ( 876 IN OUT POOL_PRINT *Str, 877 IN VOID *DevPath 878 ) 879 { 880 UART_DEVICE_PATH *Uart; 881 CHAR8 Parity; 882 883 Uart = DevPath; 884 switch (Uart->Parity) { 885 case 0 : Parity = 'D'; break; 886 case 1 : Parity = 'N'; break; 887 case 2 : Parity = 'E'; break; 888 case 3 : Parity = 'O'; break; 889 case 4 : Parity = 'M'; break; 890 case 5 : Parity = 'S'; break; 891 default : Parity = 'x'; break; 892 } 893 894 if (Uart->BaudRate == 0) { 895 CatPrint(Str, L"Uart(DEFAULT,"); 896 } else { 897 CatPrint(Str, L"Uart(%ld,", Uart->BaudRate); 898 } 899 900 if (Uart->DataBits == 0) { 901 CatPrint(Str, L"DEFAULT,"); 902 } else { 903 CatPrint(Str, L"%d,", Uart->DataBits); 904 } 905 906 CatPrint(Str, L"%c,", Parity); 907 908 switch (Uart->StopBits) { 909 case 0 : CatPrint(Str, L"D)"); break; 910 case 1 : CatPrint(Str, L"1)"); break; 911 case 2 : CatPrint(Str, L"1.5)"); break; 912 case 3 : CatPrint(Str, L"2)"); break; 913 default : CatPrint(Str, L"x)"); break; 914 } 915 } 916 917 static VOID 918 _DevPathSata ( 919 IN OUT POOL_PRINT *Str, 920 IN VOID *DevPath 921 ) 922 { 923 SATA_DEVICE_PATH * Sata ; 924 925 Sata = DevPath; 926 CatPrint( Str , L"Sata(0x%x,0x%x,0x%x)" , Sata-> HBAPortNumber , 927 Sata-> PortMultiplierPortNumber , Sata-> Lun ) ; 928 } 929 930 static VOID 931 _DevPathHardDrive ( 932 IN OUT POOL_PRINT *Str, 933 IN VOID *DevPath 934 ) 935 { 936 HARDDRIVE_DEVICE_PATH *Hd; 937 938 Hd = DevPath; 939 switch (Hd->SignatureType) { 940 case SIGNATURE_TYPE_MBR: 941 CatPrint(Str, L"HD(%d,MBR,0x%08x)", 942 Hd->PartitionNumber, 943 *((UINT32 *)(&(Hd->Signature[0]))) 944 ); 945 break; 946 case SIGNATURE_TYPE_GUID: 947 CatPrint(Str, L"HD(%d,GPT,%g)", 948 Hd->PartitionNumber, 949 (EFI_GUID *) &(Hd->Signature[0]) 950 ); 951 break; 952 default: 953 CatPrint(Str, L"HD(%d,%d,0)", 954 Hd->PartitionNumber, 955 Hd->SignatureType 956 ); 957 break; 958 } 959 } 960 961 static VOID 962 _DevPathCDROM ( 963 IN OUT POOL_PRINT *Str, 964 IN VOID *DevPath 965 ) 966 { 967 CDROM_DEVICE_PATH *Cd; 968 969 Cd = DevPath; 970 CatPrint( Str , L"CDROM(0x%x)" , Cd-> BootEntry ) ; 971 } 972 973 static VOID 974 _DevPathFilePath ( 975 IN OUT POOL_PRINT *Str, 976 IN VOID *DevPath 977 ) 978 { 979 FILEPATH_DEVICE_PATH *Fp; 980 981 Fp = DevPath; 982 CatPrint(Str, L"%s", Fp->PathName); 983 } 984 985 static VOID 986 _DevPathMediaProtocol ( 987 IN OUT POOL_PRINT *Str, 988 IN VOID *DevPath 989 ) 990 { 991 MEDIA_PROTOCOL_DEVICE_PATH *MediaProt; 992 993 MediaProt = DevPath; 994 CatPrint(Str, L"%g", &MediaProt->Protocol); 995 } 996 997 static VOID 998 _DevPathBssBss ( 999 IN OUT POOL_PRINT *Str, 1000 IN VOID *DevPath 1001 ) 1002 { 1003 BBS_BBS_DEVICE_PATH *Bss; 1004 CHAR16 *Type; 1005 1006 Bss = DevPath; 1007 switch (Bss->DeviceType) { 1008 case BBS_TYPE_FLOPPY: Type = L"Floppy"; break; 1009 case BBS_TYPE_HARDDRIVE: Type = L"Harddrive"; break; 1010 case BBS_TYPE_CDROM: Type = L"CDROM"; break; 1011 case BBS_TYPE_PCMCIA: Type = L"PCMCIA"; break; 1012 case BBS_TYPE_USB: Type = L"Usb"; break; 1013 case BBS_TYPE_EMBEDDED_NETWORK: Type = L"Net"; break; 1014 default: Type = L"?"; break; 1015 } 1016 1017 CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String); 1018 } 1019 1020 1021 static VOID 1022 _DevPathEndInstance ( 1023 IN OUT POOL_PRINT *Str, 1024 IN VOID *DevPath EFI_UNUSED 1025 ) 1026 { 1027 CatPrint(Str, L","); 1028 } 1029 1030 /** 1031 * Print unknown device node. 1032 * UEFI 2.4 § 9.6.1.6 table 89. 1033 */ 1034 1035 static VOID 1036 _DevPathNodeUnknown ( 1037 IN OUT POOL_PRINT *Str, 1038 IN VOID *DevPath 1039 ) 1040 { 1041 EFI_DEVICE_PATH * Path ; 1042 UINT8 * value ; 1043 int length , index ; 1044 Path = DevPath ; 1045 value = DevPath ; 1046 value += 4 ; 1047 switch ( Path-> Type ) { 1048 case HARDWARE_DEVICE_PATH : { /* Unknown Hardware Device Path */ 1049 CatPrint( Str , L"HardwarePath(%d" , Path-> SubType ) ; 1050 break ; 1051 } 1052 case ACPI_DEVICE_PATH : { /* Unknown ACPI Device Path */ 1053 CatPrint( Str , L"AcpiPath(%d" , Path-> SubType ) ; 1054 break ; 1055 } 1056 case MESSAGING_DEVICE_PATH : { /* Unknown Messaging Device Path */ 1057 CatPrint( Str , L"Msg(%d" , Path-> SubType ) ; 1058 break ; 1059 } 1060 case MEDIA_DEVICE_PATH : { /* Unknown Media Device Path */ 1061 CatPrint( Str , L"MediaPath(%d" , Path-> SubType ) ; 1062 break ; 1063 } 1064 case BBS_DEVICE_PATH : { /* Unknown BIOS Boot Specification Device Path */ 1065 CatPrint( Str , L"BbsPath(%d" , Path-> SubType ) ; 1066 break ; 1067 } 1068 default : { /* Unknown Device Path */ 1069 CatPrint( Str , L"Path(%d,%d" , Path-> Type , Path-> SubType ) ; 1070 break ; 1071 } 1072 } 1073 length = DevicePathNodeLength( Path ) ; 1074 for ( index = 0 ; index < length ; index ++ ) { 1075 if ( index == 0 ) CatPrint( Str , L",0x" ) ; 1076 CatPrint( Str , L"%02x" , * value ) ; 1077 value ++ ; 1078 } 1079 CatPrint( Str , L")" ) ; 1080 } 1081 1082 1083 /* 1084 * Table to convert "Type" and "SubType" to a "convert to text" function/ 1085 * Entries hold "Type" and "SubType" for know values. 1086 * Special "SubType" 0 is used as default for known type with unknown subtype. 1087 */ 1088 struct { 1089 UINT8 Type; 1090 UINT8 SubType; 1091 VOID (*Function)(POOL_PRINT *, VOID *); 1092 } DevPathTable[] = { 1093 { HARDWARE_DEVICE_PATH, HW_PCI_DP, _DevPathPci}, 1094 { HARDWARE_DEVICE_PATH, HW_PCCARD_DP, _DevPathPccard}, 1095 { HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, _DevPathMemMap}, 1096 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, _DevPathVendor}, 1097 { HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, _DevPathController}, 1098 { ACPI_DEVICE_PATH, ACPI_DP, _DevPathAcpi}, 1099 { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, _DevPathAtapi}, 1100 { MESSAGING_DEVICE_PATH, MSG_SCSI_DP, _DevPathScsi}, 1101 { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, _DevPathFibre}, 1102 { MESSAGING_DEVICE_PATH, MSG_1394_DP, _DevPath1394}, 1103 { MESSAGING_DEVICE_PATH, MSG_USB_DP, _DevPathUsb}, 1104 { MESSAGING_DEVICE_PATH, MSG_I2O_DP, _DevPathI2O}, 1105 { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, _DevPathMacAddr}, 1106 { MESSAGING_DEVICE_PATH, MSG_IPv4_DP, _DevPathIPv4}, 1107 { MESSAGING_DEVICE_PATH, MSG_IPv6_DP, _DevPathIPv6}, 1108 { MESSAGING_DEVICE_PATH, MSG_URI_DP, _DevPathUri}, 1109 { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, _DevPathInfiniBand}, 1110 { MESSAGING_DEVICE_PATH, MSG_UART_DP, _DevPathUart}, 1111 { MESSAGING_DEVICE_PATH , MSG_SATA_DP , _DevPathSata } , 1112 { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, _DevPathVendor}, 1113 { MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, _DevPathHardDrive}, 1114 { MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, _DevPathCDROM}, 1115 { MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, _DevPathVendor}, 1116 { MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, _DevPathFilePath}, 1117 { MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, _DevPathMediaProtocol}, 1118 { BBS_DEVICE_PATH, BBS_BBS_DP, _DevPathBssBss}, 1119 { END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance}, 1120 { 0, 0, NULL} 1121 }; 1122 1123 1124 CHAR16 * 1125 DevicePathToStr ( 1126 EFI_DEVICE_PATH *DevPath 1127 ) 1128 /*++ 1129 1130 Turns the Device Path into a printable string. Allcoates 1131 the string from pool. The caller must FreePool the returned 1132 string. 1133 1134 --*/ 1135 { 1136 POOL_PRINT Str; 1137 EFI_DEVICE_PATH *DevPathNode; 1138 VOID (*DumpNode)(POOL_PRINT *, VOID *); 1139 UINTN Index, NewSize; 1140 1141 ZeroMem(&Str, sizeof(Str)); 1142 1143 // 1144 // Unpacked the device path 1145 // 1146 1147 DevPath = UnpackDevicePath(DevPath); 1148 ASSERT (DevPath); 1149 1150 1151 // 1152 // Process each device path node 1153 // 1154 1155 DevPathNode = DevPath; 1156 while (!IsDevicePathEnd(DevPathNode)) { 1157 // 1158 // Find the handler to dump this device path node 1159 // 1160 1161 DumpNode = NULL; 1162 for (Index = 0; DevPathTable[Index].Function; Index += 1) { 1163 1164 if (DevicePathType(DevPathNode) == DevPathTable[Index].Type && 1165 DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) { 1166 DumpNode = DevPathTable[Index].Function; 1167 break; 1168 } 1169 } 1170 1171 // 1172 // If not found, use a generic function 1173 // 1174 1175 if (!DumpNode) { 1176 DumpNode = _DevPathNodeUnknown; 1177 } 1178 1179 // 1180 // Put a path seperator in if needed 1181 // 1182 1183 if (Str.len && DumpNode != _DevPathEndInstance) { 1184 CatPrint (&Str, L"/"); 1185 } 1186 1187 // 1188 // Print this node of the device path 1189 // 1190 1191 DumpNode (&Str, DevPathNode); 1192 1193 // 1194 // Next device path node 1195 // 1196 1197 DevPathNode = NextDevicePathNode(DevPathNode); 1198 } 1199 1200 // 1201 // Shrink pool used for string allocation 1202 // 1203 1204 FreePool (DevPath); 1205 NewSize = (Str.len + 1) * sizeof(CHAR16); 1206 Str.str = ReallocatePool (Str.str, NewSize, NewSize); 1207 Str.str[Str.len] = 0; 1208 return Str.str; 1209 } 1210 1211 BOOLEAN 1212 LibMatchDevicePaths ( 1213 IN EFI_DEVICE_PATH *Multi, 1214 IN EFI_DEVICE_PATH *Single 1215 ) 1216 { 1217 EFI_DEVICE_PATH *DevicePath, *DevicePathInst; 1218 UINTN Size; 1219 1220 if (!Multi || !Single) { 1221 return FALSE; 1222 } 1223 1224 DevicePath = Multi; 1225 while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) { 1226 if (CompareMem (Single, DevicePathInst, Size) == 0) { 1227 return TRUE; 1228 } 1229 } 1230 return FALSE; 1231 } 1232 1233 EFI_DEVICE_PATH * 1234 LibDuplicateDevicePathInstance ( 1235 IN EFI_DEVICE_PATH *DevPath 1236 ) 1237 { 1238 EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp; 1239 UINTN Size = 0; 1240 1241 // 1242 // get the size of an instance from the input 1243 // 1244 1245 Temp = DevPath; 1246 DevicePathInst = DevicePathInstance (&Temp, &Size); 1247 1248 // 1249 // Make a copy and set proper end type 1250 // 1251 NewDevPath = NULL; 1252 if (Size) { 1253 NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH)); 1254 } 1255 1256 if (NewDevPath) { 1257 CopyMem (NewDevPath, DevicePathInst, Size); 1258 Temp = NextDevicePathNode(NewDevPath); 1259 SetDevicePathEndNode(Temp); 1260 } 1261 1262 return NewDevPath; 1263 } 1264 1265