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