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