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 * 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 * 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 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 * 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 * 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 * 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 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 * 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 * 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* 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 * 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