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
BiosBlockIoDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
BiosBlockIoDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
BiosBlockIoDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
BiosBlockIoDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
SetBiosInitBlockIoDevicePath(IN EFI_DEVICE_PATH_PROTOCOL * BaseDevicePath,IN BIOS_LEGACY_DRIVE * Drive,OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath)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
BuildEdd30DevicePath(IN EFI_DEVICE_PATH_PROTOCOL * BaseDevicePath,IN BIOS_LEGACY_DRIVE * Drive,IN EFI_DEVICE_PATH_PROTOCOL ** DevicePath)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