1 /** @file 2 EFI glue for BIOS INT 13h block devices. 3 4 This file is coded to EDD 3.0 as defined by T13 D1386 Revision 4 5 Availible on http://www.t13.org/#Project drafts 6 Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r4.pdf 7 8 Copyright (c) 1999 - 2011, Intel Corporation. All rights reserved.<BR> 9 10 This program and the accompanying materials 11 are licensed and made available under the terms and conditions 12 of the BSD License which accompanies this distribution. The 13 full text of the license may be found at 14 http://opensource.org/licenses/bsd-license.php 15 16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 18 19 **/ 20 21 #include "BiosBlkIo.h" 22 23 // 24 // Global data declaration 25 // 26 // 27 // EFI Driver Binding Protocol Instance 28 // 29 EFI_DRIVER_BINDING_PROTOCOL gBiosBlockIoDriverBinding = { 30 BiosBlockIoDriverBindingSupported, 31 BiosBlockIoDriverBindingStart, 32 BiosBlockIoDriverBindingStop, 33 0x3, 34 NULL, 35 NULL 36 }; 37 38 // 39 // Semaphore to control access to global variables mActiveInstances and mBufferUnder1Mb 40 // 41 EFI_LOCK mGlobalDataLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_APPLICATION); 42 43 // 44 // Number of active instances of this protocol. This is used to allocate/free 45 // the shared buffer. You must acquire the semaphore to modify. 46 // 47 UINTN mActiveInstances = 0; 48 49 // 50 // Pointer to the beginning of the buffer used for real mode thunk 51 // You must acquire the semaphore to modify. 52 // 53 EFI_PHYSICAL_ADDRESS mBufferUnder1Mb = 0; 54 55 // 56 // Address packet is a buffer under 1 MB for all version EDD calls 57 // 58 EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb; 59 60 // 61 // This is a buffer for INT 13h func 48 information 62 // 63 BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb; 64 65 // 66 // Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB 67 // 0xFE00 bytes is the max transfer size supported. 68 // 69 VOID *mEdd11Buffer; 70 71 /** 72 Driver entry point. 73 74 @param ImageHandle Handle of driver image. 75 @param SystemTable Pointer to system table. 76 77 @retval EFI_SUCCESS Entrypoint successfully executed. 78 @retval Others Fail to execute entrypoint. 79 80 **/ 81 EFI_STATUS 82 EFIAPI 83 BiosBlockIoDriverEntryPoint ( 84 IN EFI_HANDLE ImageHandle, 85 IN EFI_SYSTEM_TABLE *SystemTable 86 ) 87 { 88 EFI_STATUS Status; 89 90 // 91 // Install protocols 92 // 93 Status = EfiLibInstallDriverBindingComponentName2 ( 94 ImageHandle, 95 SystemTable, 96 &gBiosBlockIoDriverBinding, 97 ImageHandle, 98 &gBiosBlockIoComponentName, 99 &gBiosBlockIoComponentName2 100 ); 101 if (EFI_ERROR (Status)) { 102 return Status; 103 } 104 // 105 // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver 106 // 107 return gBS->InstallMultipleProtocolInterfaces ( 108 &ImageHandle, 109 &gEfiLegacyBiosGuid, 110 NULL, 111 NULL 112 ); 113 } 114 115 /** 116 Check whether the driver supports this device. 117 118 @param This The Udriver binding protocol. 119 @param Controller The controller handle to check. 120 @param RemainingDevicePath The remaining device path. 121 122 @retval EFI_SUCCESS The driver supports this controller. 123 @retval other This device isn't supported. 124 125 **/ 126 EFI_STATUS 127 EFIAPI 128 BiosBlockIoDriverBindingSupported ( 129 IN EFI_DRIVER_BINDING_PROTOCOL *This, 130 IN EFI_HANDLE Controller, 131 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 132 ) 133 { 134 EFI_STATUS Status; 135 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; 136 EFI_PCI_IO_PROTOCOL *PciIo; 137 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 138 PCI_TYPE00 Pci; 139 140 // 141 // See if the Legacy BIOS Protocol is available 142 // 143 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); 144 if (EFI_ERROR (Status)) { 145 return Status; 146 } 147 148 Status = gBS->OpenProtocol ( 149 Controller, 150 &gEfiDevicePathProtocolGuid, 151 (VOID **) &DevicePath, 152 This->DriverBindingHandle, 153 Controller, 154 EFI_OPEN_PROTOCOL_BY_DRIVER 155 ); 156 if (EFI_ERROR (Status)) { 157 return Status; 158 } 159 160 gBS->CloseProtocol ( 161 Controller, 162 &gEfiDevicePathProtocolGuid, 163 This->DriverBindingHandle, 164 Controller 165 ); 166 167 // 168 // Open the IO Abstraction(s) needed to perform the supported test 169 // 170 Status = gBS->OpenProtocol ( 171 Controller, 172 &gEfiPciIoProtocolGuid, 173 (VOID **) &PciIo, 174 This->DriverBindingHandle, 175 Controller, 176 EFI_OPEN_PROTOCOL_BY_DRIVER 177 ); 178 if (EFI_ERROR (Status)) { 179 return Status; 180 } 181 // 182 // See if this is a PCI VGA Controller by looking at the Command register and 183 // Class Code Register 184 // 185 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci); 186 if (EFI_ERROR (Status)) { 187 Status = EFI_UNSUPPORTED; 188 goto Done; 189 } 190 191 Status = EFI_UNSUPPORTED; 192 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE || 193 (Pci.Hdr.ClassCode[2] == PCI_BASE_CLASS_INTELLIGENT && Pci.Hdr.ClassCode[1] == PCI_SUB_CLASS_INTELLIGENT) 194 ) { 195 Status = EFI_SUCCESS; 196 } 197 198 Done: 199 gBS->CloseProtocol ( 200 Controller, 201 &gEfiPciIoProtocolGuid, 202 This->DriverBindingHandle, 203 Controller 204 ); 205 206 return Status; 207 } 208 209 /** 210 Starts the device with this driver. 211 212 @param This The driver binding instance. 213 @param Controller Handle of device to bind driver to. 214 @param RemainingDevicePath Optional parameter use to pick a specific child 215 device to start. 216 217 @retval EFI_SUCCESS The controller is controlled by the driver. 218 @retval Other This controller cannot be started. 219 220 **/ 221 EFI_STATUS 222 EFIAPI 223 BiosBlockIoDriverBindingStart ( 224 IN EFI_DRIVER_BINDING_PROTOCOL *This, 225 IN EFI_HANDLE Controller, 226 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 227 ) 228 { 229 EFI_STATUS Status; 230 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; 231 EFI_PCI_IO_PROTOCOL *PciIo; 232 UINT8 DiskStart; 233 UINT8 DiskEnd; 234 BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; 235 EFI_DEVICE_PATH_PROTOCOL *PciDevPath; 236 UINTN Index; 237 UINTN Flags; 238 UINTN TmpAddress; 239 BOOLEAN DeviceEnable; 240 241 // 242 // Initialize variables 243 // 244 PciIo = NULL; 245 PciDevPath = NULL; 246 247 DeviceEnable = FALSE; 248 249 // 250 // See if the Legacy BIOS Protocol is available 251 // 252 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); 253 if (EFI_ERROR (Status)) { 254 goto Error; 255 } 256 // 257 // Open the IO Abstraction(s) needed 258 // 259 Status = gBS->OpenProtocol ( 260 Controller, 261 &gEfiPciIoProtocolGuid, 262 (VOID **) &PciIo, 263 This->DriverBindingHandle, 264 Controller, 265 EFI_OPEN_PROTOCOL_BY_DRIVER 266 ); 267 if (EFI_ERROR (Status)) { 268 goto Error; 269 } 270 271 Status = gBS->OpenProtocol ( 272 Controller, 273 &gEfiDevicePathProtocolGuid, 274 (VOID **) &PciDevPath, 275 This->DriverBindingHandle, 276 Controller, 277 EFI_OPEN_PROTOCOL_BY_DRIVER 278 ); 279 280 if (EFI_ERROR (Status)) { 281 goto Error; 282 } 283 // 284 // Enable the device and make sure VGA cycles are being forwarded to this VGA device 285 // 286 Status = PciIo->Attributes ( 287 PciIo, 288 EfiPciIoAttributeOperationEnable, 289 EFI_PCI_DEVICE_ENABLE, 290 NULL 291 ); 292 if (EFI_ERROR (Status)) { 293 goto Error; 294 } 295 296 DeviceEnable = TRUE; 297 298 // 299 // Check to see if there is a legacy option ROM image associated with this PCI device 300 // 301 Status = LegacyBios->CheckPciRom ( 302 LegacyBios, 303 Controller, 304 NULL, 305 NULL, 306 &Flags 307 ); 308 if (EFI_ERROR (Status)) { 309 goto Error; 310 } 311 // 312 // Post the legacy option ROM if it is available. 313 // 314 Status = LegacyBios->InstallPciRom ( 315 LegacyBios, 316 Controller, 317 NULL, 318 &Flags, 319 &DiskStart, 320 &DiskEnd, 321 NULL, 322 NULL 323 ); 324 if (EFI_ERROR (Status)) { 325 goto Error; 326 } 327 // 328 // All instances share a buffer under 1MB to put real mode thunk code in 329 // If it has not been allocated, then we allocate it. 330 // 331 if (mBufferUnder1Mb == 0) { 332 // 333 // Should only be here if there are no active instances 334 // 335 ASSERT (mActiveInstances == 0); 336 337 // 338 // Acquire the lock 339 // 340 EfiAcquireLock (&mGlobalDataLock); 341 342 // 343 // Allocate below 1MB 344 // 345 mBufferUnder1Mb = 0x00000000000FFFFF; 346 Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb); 347 348 // 349 // Release the lock 350 // 351 EfiReleaseLock (&mGlobalDataLock); 352 353 // 354 // Check memory allocation success 355 // 356 if (EFI_ERROR (Status)) { 357 // 358 // In checked builds we want to assert if the allocate failed. 359 // 360 ASSERT_EFI_ERROR (Status); 361 Status = EFI_OUT_OF_RESOURCES; 362 mBufferUnder1Mb = 0; 363 goto Error; 364 } 365 366 TmpAddress = (UINTN) mBufferUnder1Mb; 367 // 368 // Adjusting the value to be on proper boundary 369 // 370 mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress); 371 372 TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER; 373 // 374 // Adjusting the value to be on proper boundary 375 // 376 mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress); 377 378 TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE); 379 // 380 // Adjusting the value to be on proper boundary 381 // 382 mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress); 383 } 384 // 385 // Allocate the private device structure for each disk 386 // 387 for (Index = DiskStart; Index < DiskEnd; Index++) { 388 389 Status = gBS->AllocatePool ( 390 EfiBootServicesData, 391 sizeof (BIOS_BLOCK_IO_DEV), 392 (VOID **) &BiosBlockIoPrivate 393 ); 394 if (EFI_ERROR (Status)) { 395 goto Error; 396 } 397 // 398 // Zero the private device structure 399 // 400 ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV)); 401 402 // 403 // Initialize the private device structure 404 // 405 BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE; 406 BiosBlockIoPrivate->ControllerHandle = Controller; 407 BiosBlockIoPrivate->LegacyBios = LegacyBios; 408 BiosBlockIoPrivate->PciIo = PciIo; 409 410 BiosBlockIoPrivate->Bios.Floppy = FALSE; 411 BiosBlockIoPrivate->Bios.Number = (UINT8) Index; 412 BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C'); 413 BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE; 414 415 if (BiosInitBlockIo (BiosBlockIoPrivate)) { 416 SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath); 417 418 // 419 // Install the Block Io Protocol onto a new child handle 420 // 421 Status = gBS->InstallMultipleProtocolInterfaces ( 422 &BiosBlockIoPrivate->Handle, 423 &gEfiBlockIoProtocolGuid, 424 &BiosBlockIoPrivate->BlockIo, 425 &gEfiDevicePathProtocolGuid, 426 BiosBlockIoPrivate->DevicePath, 427 NULL 428 ); 429 if (EFI_ERROR (Status)) { 430 gBS->FreePool (BiosBlockIoPrivate); 431 } 432 // 433 // Open For Child Device 434 // 435 Status = gBS->OpenProtocol ( 436 Controller, 437 &gEfiPciIoProtocolGuid, 438 (VOID **) &BiosBlockIoPrivate->PciIo, 439 This->DriverBindingHandle, 440 BiosBlockIoPrivate->Handle, 441 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 442 ); 443 444 } else { 445 gBS->FreePool (BiosBlockIoPrivate); 446 } 447 } 448 449 Error: 450 if (EFI_ERROR (Status)) { 451 if (PciIo != NULL) { 452 if (DeviceEnable) { 453 PciIo->Attributes ( 454 PciIo, 455 EfiPciIoAttributeOperationDisable, 456 EFI_PCI_DEVICE_ENABLE, 457 NULL 458 ); 459 } 460 gBS->CloseProtocol ( 461 Controller, 462 &gEfiPciIoProtocolGuid, 463 This->DriverBindingHandle, 464 Controller 465 ); 466 if (PciDevPath != NULL) { 467 gBS->CloseProtocol ( 468 Controller, 469 &gEfiDevicePathProtocolGuid, 470 This->DriverBindingHandle, 471 Controller 472 ); 473 } 474 if (mBufferUnder1Mb != 0 && mActiveInstances == 0) { 475 gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); 476 477 // 478 // Clear the buffer back to 0 479 // 480 EfiAcquireLock (&mGlobalDataLock); 481 mBufferUnder1Mb = 0; 482 EfiReleaseLock (&mGlobalDataLock); 483 } 484 } 485 } else { 486 // 487 // Successfully installed, so increment the number of active instances 488 // 489 EfiAcquireLock (&mGlobalDataLock); 490 mActiveInstances++; 491 EfiReleaseLock (&mGlobalDataLock); 492 } 493 494 return Status; 495 } 496 497 /** 498 Stop the device handled by this driver. 499 500 @param This The driver binding protocol. 501 @param Controller The controller to release. 502 @param NumberOfChildren The number of handles in ChildHandleBuffer. 503 @param ChildHandleBuffer The array of child handle. 504 505 @retval EFI_SUCCESS The device was stopped. 506 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 507 @retval Others Fail to uninstall protocols attached on the device. 508 509 **/ 510 EFI_STATUS 511 EFIAPI 512 BiosBlockIoDriverBindingStop ( 513 IN EFI_DRIVER_BINDING_PROTOCOL *This, 514 IN EFI_HANDLE Controller, 515 IN UINTN NumberOfChildren, 516 IN EFI_HANDLE *ChildHandleBuffer 517 ) 518 { 519 EFI_STATUS Status; 520 BOOLEAN AllChildrenStopped; 521 EFI_BLOCK_IO_PROTOCOL *BlockIo; 522 BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; 523 UINTN Index; 524 525 // 526 // Decrement the number of active instances 527 // 528 if (mActiveInstances != 0) { 529 // 530 // Add a check since the stop function will be called 2 times for each handle 531 // 532 EfiAcquireLock (&mGlobalDataLock); 533 mActiveInstances--; 534 EfiReleaseLock (&mGlobalDataLock); 535 } 536 537 if ((mActiveInstances == 0) && (mBufferUnder1Mb != 0)) { 538 // 539 // Free our global buffer 540 // 541 Status = gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); 542 ASSERT_EFI_ERROR (Status); 543 544 EfiAcquireLock (&mGlobalDataLock); 545 mBufferUnder1Mb = 0; 546 EfiReleaseLock (&mGlobalDataLock); 547 } 548 549 AllChildrenStopped = TRUE; 550 551 for (Index = 0; Index < NumberOfChildren; Index++) { 552 Status = gBS->OpenProtocol ( 553 ChildHandleBuffer[Index], 554 &gEfiBlockIoProtocolGuid, 555 (VOID **) &BlockIo, 556 This->DriverBindingHandle, 557 Controller, 558 EFI_OPEN_PROTOCOL_GET_PROTOCOL 559 ); 560 if (EFI_ERROR (Status)) { 561 return Status; 562 } 563 564 BiosBlockIoPrivate = BIOS_BLOCK_IO_FROM_THIS (BlockIo); 565 566 // 567 // Release PCI I/O and Block IO Protocols on the clild handle. 568 // 569 Status = gBS->UninstallMultipleProtocolInterfaces ( 570 ChildHandleBuffer[Index], 571 &gEfiBlockIoProtocolGuid, 572 &BiosBlockIoPrivate->BlockIo, 573 &gEfiDevicePathProtocolGuid, 574 BiosBlockIoPrivate->DevicePath, 575 NULL 576 ); 577 if (EFI_ERROR (Status)) { 578 AllChildrenStopped = FALSE; 579 } 580 // 581 // Shutdown the hardware 582 // 583 BiosBlockIoPrivate->PciIo->Attributes ( 584 BiosBlockIoPrivate->PciIo, 585 EfiPciIoAttributeOperationDisable, 586 EFI_PCI_DEVICE_ENABLE, 587 NULL 588 ); 589 590 gBS->CloseProtocol ( 591 Controller, 592 &gEfiPciIoProtocolGuid, 593 This->DriverBindingHandle, 594 ChildHandleBuffer[Index] 595 ); 596 597 gBS->FreePool (BiosBlockIoPrivate); 598 } 599 600 if (!AllChildrenStopped) { 601 return EFI_DEVICE_ERROR; 602 } 603 604 Status = gBS->CloseProtocol ( 605 Controller, 606 &gEfiDevicePathProtocolGuid, 607 This->DriverBindingHandle, 608 Controller 609 ); 610 611 Status = gBS->CloseProtocol ( 612 Controller, 613 &gEfiPciIoProtocolGuid, 614 This->DriverBindingHandle, 615 Controller 616 ); 617 618 return EFI_SUCCESS; 619 } 620 621 /** 622 Build device path for device. 623 624 @param BaseDevicePath Base device path. 625 @param Drive Legacy drive. 626 @param DevicePath Device path for output. 627 628 **/ 629 VOID 630 SetBiosInitBlockIoDevicePath ( 631 IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, 632 IN BIOS_LEGACY_DRIVE *Drive, 633 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath 634 ) 635 { 636 EFI_STATUS Status; 637 BLOCKIO_VENDOR_DEVICE_PATH VendorNode; 638 639 Status = EFI_UNSUPPORTED; 640 641 // 642 // BugBug: Check for memory leaks! 643 // 644 if (Drive->EddVersion == EDD_VERSION_30) { 645 // 646 // EDD 3.0 case. 647 // 648 Status = BuildEdd30DevicePath (BaseDevicePath, Drive, DevicePath); 649 } 650 651 if (EFI_ERROR (Status)) { 652 // 653 // EDD 1.1 device case or it is unrecognized EDD 3.0 device 654 // 655 ZeroMem (&VendorNode, sizeof (VendorNode)); 656 VendorNode.DevicePath.Header.Type = HARDWARE_DEVICE_PATH; 657 VendorNode.DevicePath.Header.SubType = HW_VENDOR_DP; 658 SetDevicePathNodeLength (&VendorNode.DevicePath.Header, sizeof (VendorNode)); 659 CopyMem (&VendorNode.DevicePath.Guid, &gBlockIoVendorGuid, sizeof (EFI_GUID)); 660 VendorNode.LegacyDriveLetter = Drive->Number; 661 *DevicePath = AppendDevicePathNode (BaseDevicePath, &VendorNode.DevicePath.Header); 662 } 663 } 664 665 /** 666 Build device path for EDD 3.0. 667 668 @param BaseDevicePath Base device path. 669 @param Drive Legacy drive. 670 @param DevicePath Device path for output. 671 672 @retval EFI_SUCCESS The device path is built successfully. 673 @retval EFI_UNSUPPORTED It is failed to built device path. 674 675 **/ 676 EFI_STATUS 677 BuildEdd30DevicePath ( 678 IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath, 679 IN BIOS_LEGACY_DRIVE *Drive, 680 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath 681 ) 682 { 683 // 684 // AVL UINT64 Address; 685 // AVL EFI_HANDLE Handle; 686 // 687 EFI_DEV_PATH Node; 688 UINT32 Controller; 689 690 Controller = (UINT32) Drive->Parameters.InterfacePath.Pci.Controller; 691 692 ZeroMem (&Node, sizeof (Node)); 693 if ((AsciiStrnCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) || 694 (AsciiStrnCmp ("ATA", Drive->Parameters.InterfaceType, 3) == 0) 695 ) { 696 // 697 // ATA or ATAPI drive found 698 // 699 Node.Atapi.Header.Type = MESSAGING_DEVICE_PATH; 700 Node.Atapi.Header.SubType = MSG_ATAPI_DP; 701 SetDevicePathNodeLength (&Node.Atapi.Header, sizeof (ATAPI_DEVICE_PATH)); 702 Node.Atapi.SlaveMaster = Drive->Parameters.DevicePath.Atapi.Master; 703 Node.Atapi.Lun = Drive->Parameters.DevicePath.Atapi.Lun; 704 Node.Atapi.PrimarySecondary = (UINT8) Controller; 705 } else { 706 // 707 // Not an ATA/ATAPI drive 708 // 709 if (Controller != 0) { 710 ZeroMem (&Node, sizeof (Node)); 711 Node.Controller.Header.Type = HARDWARE_DEVICE_PATH; 712 Node.Controller.Header.SubType = HW_CONTROLLER_DP; 713 SetDevicePathNodeLength (&Node.Controller.Header, sizeof (CONTROLLER_DEVICE_PATH)); 714 Node.Controller.ControllerNumber = Controller; 715 *DevicePath = AppendDevicePathNode (*DevicePath, &Node.DevPath); 716 } 717 718 ZeroMem (&Node, sizeof (Node)); 719 720 if (AsciiStrnCmp ("SCSI", Drive->Parameters.InterfaceType, 4) == 0) { 721 // 722 // SCSI drive 723 // 724 Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH; 725 Node.Scsi.Header.SubType = MSG_SCSI_DP; 726 SetDevicePathNodeLength (&Node.Scsi.Header, sizeof (SCSI_DEVICE_PATH)); 727 728 // 729 // Lun is miss aligned in both EDD and Device Path data structures. 730 // thus we do a byte copy, to prevent alignment traps on IA-64. 731 // 732 CopyMem (&Node.Scsi.Lun, &Drive->Parameters.DevicePath.Scsi.Lun, sizeof (UINT16)); 733 Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.Pun; 734 735 } else if (AsciiStrnCmp ("USB", Drive->Parameters.InterfaceType, 3) == 0) { 736 // 737 // USB drive 738 // 739 Node.Usb.Header.Type = MESSAGING_DEVICE_PATH; 740 Node.Usb.Header.SubType = MSG_USB_DP; 741 SetDevicePathNodeLength (&Node.Usb.Header, sizeof (USB_DEVICE_PATH)); 742 Node.Usb.ParentPortNumber = (UINT8) Drive->Parameters.DevicePath.Usb.Reserved; 743 744 } else if (AsciiStrnCmp ("1394", Drive->Parameters.InterfaceType, 4) == 0) { 745 // 746 // 1394 drive 747 // 748 Node.F1394.Header.Type = MESSAGING_DEVICE_PATH; 749 Node.F1394.Header.SubType = MSG_1394_DP; 750 SetDevicePathNodeLength (&Node.F1394.Header, sizeof (F1394_DEVICE_PATH)); 751 Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid; 752 753 } else if (AsciiStrnCmp ("FIBRE", Drive->Parameters.InterfaceType, 5) == 0) { 754 // 755 // Fibre drive 756 // 757 Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH; 758 Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP; 759 SetDevicePathNodeLength (&Node.FibreChannel.Header, sizeof (FIBRECHANNEL_DEVICE_PATH)); 760 Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn; 761 Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun; 762 763 } else { 764 DEBUG ( 765 ( 766 DEBUG_BLKIO, "It is unrecognized EDD 3.0 device, Drive Number = %x, InterfaceType = %s\n", 767 Drive->Number, 768 Drive->Parameters.InterfaceType 769 ) 770 ); 771 } 772 } 773 774 if (Node.DevPath.Type == 0) { 775 return EFI_UNSUPPORTED; 776 } 777 778 *DevicePath = AppendDevicePathNode (BaseDevicePath, &Node.DevPath); 779 return EFI_SUCCESS; 780 } 781