1 /* $NetBSD: dpath.c,v 1.3 2018/08/16 18:22:05 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 __unused; 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 __unused; 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 __unused; 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