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