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