]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
fix memory leak at AccessAtaDevice() of AtaBus.
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaBusDxe / AtaBus.c
CommitLineData
ad86a50a 1/** @file\r
2 This file implements protocol interfaces for ATA bus driver.\r
3 \r
4 This file implements protocol interfaces: Driver Binding protocol,\r
5 Block IO protocol and DiskInfo protocol.\r
6 \r
e519983a 7 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 8 This program and the accompanying materials\r
ad86a50a 9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16\r
17**/\r
18\r
19#include "AtaBus.h"\r
20\r
21//\r
22// ATA Bus Driver Binding Protocol Instance\r
23//\r
24EFI_DRIVER_BINDING_PROTOCOL gAtaBusDriverBinding = {\r
25 AtaBusDriverBindingSupported,\r
26 AtaBusDriverBindingStart,\r
27 AtaBusDriverBindingStop,\r
28 0x10,\r
29 NULL,\r
30 NULL\r
31};\r
32\r
33//\r
34// Template for ATA Child Device.\r
35//\r
36ATA_DEVICE gAtaDeviceTemplate = {\r
05a44e91 37 ATA_DEVICE_SIGNATURE, // Signature\r
38 NULL, // Handle\r
ad86a50a 39 { // BlockIo\r
40 EFI_BLOCK_IO_PROTOCOL_REVISION,\r
41 NULL,\r
42 AtaBlockIoReset,\r
43 AtaBlockIoReadBlocks,\r
44 AtaBlockIoWriteBlocks,\r
45 AtaBlockIoFlushBlocks\r
46 },\r
490b5ea1 47 { // BlockIo2\r
48 NULL,\r
49 AtaBlockIoResetEx,\r
50 AtaBlockIoReadBlocksEx,\r
51 AtaBlockIoWriteBlocksEx,\r
52 AtaBlockIoFlushBlocksEx\r
53 },\r
ad86a50a 54 { // BlockMedia\r
55 0, // MediaId\r
56 FALSE, // RemovableMedia\r
57 TRUE, // MediaPresent\r
58 FALSE, // LogicPartition\r
59 FALSE, // ReadOnly\r
60 FALSE, // WritingCache\r
61 0x200, // BlockSize \r
907c1a00 62 0, // IoAlign\r
3bfa77f0 63 0, // LastBlock\r
64 0, // LowestAlignedLba\r
65 1 // LogicalBlocksPerPhysicalBlock\r
ad86a50a 66 },\r
67 { // DiskInfo\r
68 EFI_DISK_INFO_IDE_INTERFACE_GUID,\r
69 AtaDiskInfoInquiry,\r
70 AtaDiskInfoIdentify,\r
71 AtaDiskInfoSenseData,\r
72 AtaDiskInfoWhichIde\r
73 },\r
05a44e91 74 NULL, // DevicePath\r
c24097a5 75 {\r
76 AtaStorageSecurityReceiveData,\r
77 AtaStorageSecuritySendData\r
78 },\r
05a44e91 79 NULL, // AtaBusDriverData\r
80 0, // Port\r
81 0, // PortMultiplierPort\r
ad86a50a 82 { 0, }, // Packet\r
83 {{ 0}, }, // Acb\r
84 NULL, // Asb\r
85 FALSE, // UdmaValid\r
86 FALSE, // Lba48Bit\r
87 NULL, // IdentifyData\r
88 NULL, // ControllerNameTable\r
490b5ea1 89 {L'\0', }, // ModelName\r
90 {NULL, NULL} // AtaTaskList\r
ad86a50a 91};\r
92\r
93/**\r
94 Allocates an aligned buffer for ATA device.\r
95\r
96 This function allocates an aligned buffer for the ATA device to perform\r
97 ATA pass through operations. The alignment requirement is from ATA pass\r
98 through interface.\r
99\r
100 @param AtaDevice The ATA child device involved for the operation.\r
101 @param BufferSize The request buffer size.\r
102\r
103 @return A pointer to the aligned buffer or NULL if the allocation fails.\r
104\r
105**/\r
106VOID *\r
107AllocateAlignedBuffer (\r
108 IN ATA_DEVICE *AtaDevice,\r
109 IN UINTN BufferSize\r
110 )\r
111{\r
112 return AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), AtaDevice->AtaBusDriverData->AtaPassThru->Mode->IoAlign);\r
113}\r
114\r
115/**\r
116 Frees an aligned buffer for ATA device.\r
117\r
118 This function frees an aligned buffer for the ATA device to perform\r
119 ATA pass through operations.\r
120\r
05a44e91 121 @param Buffer The aligned buffer to be freed.\r
ad86a50a 122 @param BufferSize The request buffer size.\r
123\r
124**/\r
125VOID\r
126FreeAlignedBuffer (\r
127 IN VOID *Buffer,\r
128 IN UINTN BufferSize\r
129 )\r
130{\r
131 if (Buffer != NULL) {\r
132 FreePages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));\r
133 }\r
134}\r
135\r
136\r
137/**\r
138 Release all the resources allocated for the ATA device.\r
139\r
140 This function releases all the resources allocated for the ATA device.\r
141\r
142 @param AtaDevice The ATA child device involved for the operation.\r
143\r
144**/\r
145VOID\r
146ReleaseAtaResources (\r
147 IN ATA_DEVICE *AtaDevice\r
148 )\r
149{\r
490b5ea1 150 ATA_BUS_ASYN_TASK *Task;\r
151 LIST_ENTRY *Entry;\r
152 LIST_ENTRY *DelEntry;\r
153 EFI_TPL OldTpl;\r
154\r
ad86a50a 155 FreeUnicodeStringTable (AtaDevice->ControllerNameTable);\r
3c063fed 156 FreeAlignedBuffer (AtaDevice->Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
157 FreeAlignedBuffer (AtaDevice->IdentifyData, sizeof (ATA_IDENTIFY_DATA));\r
ad86a50a 158 if (AtaDevice->DevicePath != NULL) {\r
159 FreePool (AtaDevice->DevicePath);\r
160 }\r
490b5ea1 161 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
162 if (!IsListEmpty (&AtaDevice->AtaTaskList)) {\r
163 //\r
164 // Free the Subtask list.\r
165 //\r
3c063fed 166 for(Entry = AtaDevice->AtaTaskList.ForwardLink; \r
490b5ea1 167 Entry != (&AtaDevice->AtaTaskList);\r
168 ) {\r
169 DelEntry = Entry;\r
170 Entry = Entry->ForwardLink;\r
171 Task = ATA_AYNS_TASK_FROM_ENTRY (DelEntry);\r
172 \r
173 RemoveEntryList (DelEntry);\r
174 FreeAtaSubTask (Task);\r
175 }\r
176 }\r
177 gBS->RestoreTPL (OldTpl);\r
ad86a50a 178 FreePool (AtaDevice);\r
179}\r
180\r
181\r
182/**\r
183 Registers an ATA device.\r
184\r
185 This function allocates an ATA device structure for the ATA device specified by\r
186 Port and PortMultiplierPort if the ATA device is identified as a valid one. \r
187 Then it will create child handle and install Block IO and Disk Info protocol on\r
188 it.\r
189\r
05a44e91 190 @param AtaBusDriverData The parent ATA bus driver data structure.\r
ad86a50a 191 @param Port The port number of the ATA device.\r
192 @param PortMultiplierPort The port multiplier port number of the ATA device.\r
193\r
194 @retval EFI_SUCCESS The ATA device is successfully registered.\r
195 @retval EFI_OUT_OF_RESOURCES There is not enough memory to allocate the ATA device\r
196 and related data structures.\r
197 @return Others Some error occurs when registering the ATA device.\r
198**/\r
199EFI_STATUS\r
200RegisterAtaDevice (\r
201 IN OUT ATA_BUS_DRIVER_DATA *AtaBusDriverData,\r
202 IN UINT16 Port,\r
203 IN UINT16 PortMultiplierPort\r
204 )\r
205{\r
206 EFI_STATUS Status;\r
207 ATA_DEVICE *AtaDevice;\r
208 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
209 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
e519983a 210 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
211 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
212 EFI_HANDLE DeviceHandle;\r
ad86a50a 213\r
e519983a 214 AtaDevice = NULL;\r
ad86a50a 215 NewDevicePathNode = NULL;\r
e519983a 216 DevicePath = NULL;\r
217 RemainingDevicePath = NULL;\r
218\r
219 //\r
220 // Build device path \r
221 //\r
222 AtaPassThru = AtaBusDriverData->AtaPassThru;\r
223 Status = AtaPassThru->BuildDevicePath (AtaPassThru, Port, PortMultiplierPort, &NewDevicePathNode);\r
224 if (EFI_ERROR (Status)) {\r
225 goto Done;\r
226 }\r
227\r
228 DevicePath = AppendDevicePathNode (AtaBusDriverData->ParentDevicePath, NewDevicePathNode);\r
229 if (DevicePath == NULL) {\r
e70ae46c 230 Status = EFI_OUT_OF_RESOURCES;\r
e519983a 231 goto Done;\r
232 }\r
233\r
234 DeviceHandle = NULL;\r
e70ae46c 235 RemainingDevicePath = DevicePath;\r
e519983a 236 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);\r
237 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {\r
238 Status = EFI_ALREADY_STARTED;\r
e70ae46c 239 FreePool (DevicePath);\r
e519983a 240 goto Done;\r
241 }\r
ad86a50a 242\r
243 //\r
244 // Allocate ATA device from the template.\r
245 //\r
3c063fed 246 AtaDevice = AllocateCopyPool (sizeof (ATA_DEVICE), &gAtaDeviceTemplate);\r
ad86a50a 247 if (AtaDevice == NULL) {\r
e519983a 248 Status = EFI_OUT_OF_RESOURCES;\r
249 goto Done;\r
ad86a50a 250 }\r
251\r
252 //\r
253 // Initializes ATA device structures and allocates the required buffer.\r
254 //\r
490b5ea1 255 AtaDevice->BlockIo.Media = &AtaDevice->BlockMedia;\r
256 AtaDevice->BlockIo2.Media = &AtaDevice->BlockMedia;\r
257 AtaDevice->AtaBusDriverData = AtaBusDriverData;\r
258 AtaDevice->DevicePath = DevicePath;\r
259 AtaDevice->Port = Port;\r
ad86a50a 260 AtaDevice->PortMultiplierPort = PortMultiplierPort;\r
3c063fed 261 AtaDevice->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (EFI_ATA_STATUS_BLOCK));\r
ad86a50a 262 if (AtaDevice->Asb == NULL) {\r
263 Status = EFI_OUT_OF_RESOURCES;\r
264 goto Done;\r
265 }\r
3c063fed 266 AtaDevice->IdentifyData = AllocateAlignedBuffer (AtaDevice, sizeof (ATA_IDENTIFY_DATA));\r
ad86a50a 267 if (AtaDevice->IdentifyData == NULL) {\r
268 Status = EFI_OUT_OF_RESOURCES;\r
269 goto Done;\r
270 }\r
271\r
490b5ea1 272 //\r
273 // Initial Ata Task List\r
274 //\r
275 InitializeListHead (&AtaDevice->AtaTaskList);\r
276\r
ad86a50a 277 //\r
278 // Try to identify the ATA device via the ATA pass through command. \r
279 //\r
280 Status = DiscoverAtaDevice (AtaDevice);\r
281 if (EFI_ERROR (Status)) {\r
282 goto Done;\r
283 }\r
490b5ea1 284\r
ad86a50a 285 //\r
286 // Build controller name for Component Name (2) protocol.\r
287 //\r
288 Status = AddUnicodeString2 (\r
289 "eng",\r
290 gAtaBusComponentName.SupportedLanguages,\r
291 &AtaDevice->ControllerNameTable,\r
292 AtaDevice->ModelName,\r
293 TRUE\r
294 );\r
295 if (EFI_ERROR (Status)) {\r
296 goto Done;\r
297 }\r
298\r
299 Status = AddUnicodeString2 (\r
300 "en",\r
301 gAtaBusComponentName2.SupportedLanguages,\r
302 &AtaDevice->ControllerNameTable,\r
303 AtaDevice->ModelName,\r
304 FALSE\r
305 );\r
306 if (EFI_ERROR (Status)) {\r
307 goto Done;\r
308 }\r
309\r
ad86a50a 310 //\r
311 // Update to AHCI interface GUID based on device path node. The default one\r
312 // is IDE interface GUID copied from template.\r
313 //\r
314 if (NewDevicePathNode->SubType == MSG_SATA_DP) {\r
315 CopyGuid (&AtaDevice->DiskInfo.Interface, &gEfiDiskInfoAhciInterfaceGuid);\r
316 }\r
317\r
ad86a50a 318 Status = gBS->InstallMultipleProtocolInterfaces (\r
319 &AtaDevice->Handle,\r
320 &gEfiDevicePathProtocolGuid,\r
321 AtaDevice->DevicePath,\r
322 &gEfiBlockIoProtocolGuid,\r
323 &AtaDevice->BlockIo,\r
490b5ea1 324 &gEfiBlockIo2ProtocolGuid,\r
325 &AtaDevice->BlockIo2,\r
ad86a50a 326 &gEfiDiskInfoProtocolGuid,\r
327 &AtaDevice->DiskInfo,\r
328 NULL\r
329 );\r
330 if (EFI_ERROR (Status)) {\r
331 goto Done;\r
332 }\r
333\r
c24097a5 334 //\r
335 // See if the ata device support trust computing feature or not.\r
336 // If yes, then install Storage Security Protocol at the ata device handle.\r
337 //\r
338 if ((AtaDevice->IdentifyData->trusted_computing_support & BIT0) != 0) {\r
339 DEBUG ((EFI_D_INFO, "Found TCG support in Port %x PortMultiplierPort %x\n", Port, PortMultiplierPort));\r
340 Status = gBS->InstallProtocolInterface (\r
341 &AtaDevice->Handle,\r
342 &gEfiStorageSecurityCommandProtocolGuid,\r
343 EFI_NATIVE_INTERFACE,\r
344 &AtaDevice->StorageSecurity\r
345 );\r
346 if (EFI_ERROR (Status)) {\r
347 goto Done;\r
348 }\r
349 }\r
350\r
ad86a50a 351 gBS->OpenProtocol (\r
352 AtaBusDriverData->Controller,\r
353 &gEfiAtaPassThruProtocolGuid,\r
354 (VOID **) &AtaPassThru,\r
355 AtaBusDriverData->DriverBindingHandle,\r
356 AtaDevice->Handle,\r
357 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
358 );\r
e519983a 359\r
ad86a50a 360Done:\r
361 if (NewDevicePathNode != NULL) {\r
362 FreePool (NewDevicePathNode);\r
363 }\r
364\r
e519983a 365 if (EFI_ERROR (Status) && (AtaDevice != NULL)) {\r
ad86a50a 366 ReleaseAtaResources (AtaDevice); \r
367 DEBUG ((DEBUG_ERROR | DEBUG_INIT, "Failed to initialize Port %x PortMultiplierPort %x, status = %r\n", Port, PortMultiplierPort, Status));\r
368 }\r
369 return Status;\r
370}\r
371\r
372\r
373/**\r
374 Unregisters an ATA device.\r
375\r
376 This function removes the protocols installed on the controller handle and \r
377 frees the resources allocated for the ATA device. \r
378\r
05a44e91 379 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.\r
ad86a50a 380 @param Controller The controller handle of the ATA device.\r
381 @param Handle The child handle.\r
382\r
383 @retval EFI_SUCCESS The ATA device is successfully unregistered.\r
384 @return Others Some error occurs when unregistering the ATA device.\r
385\r
386**/\r
387EFI_STATUS\r
388UnregisterAtaDevice (\r
389 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
390 IN EFI_HANDLE Controller,\r
391 IN EFI_HANDLE Handle\r
392 )\r
393{\r
c24097a5 394 EFI_STATUS Status;\r
395 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
396 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;\r
397 ATA_DEVICE *AtaDevice;\r
398 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
399 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;\r
400\r
401 BlockIo2 = NULL;\r
402 BlockIo = NULL;\r
ad86a50a 403\r
404 Status = gBS->OpenProtocol (\r
405 Handle,\r
406 &gEfiBlockIoProtocolGuid,\r
407 (VOID **) &BlockIo,\r
408 This->DriverBindingHandle,\r
409 Controller,\r
410 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
411 );\r
412 if (EFI_ERROR (Status)) {\r
490b5ea1 413 //\r
414 // Locate BlockIo2 protocol\r
415 //\r
416 Status = gBS->OpenProtocol (\r
417 Handle,\r
418 &gEfiBlockIo2ProtocolGuid,\r
419 (VOID **) &BlockIo2,\r
420 This->DriverBindingHandle,\r
421 Controller,\r
422 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
423 );\r
424 if (EFI_ERROR (Status)) {\r
425 return Status;\r
426 }\r
ad86a50a 427 }\r
428\r
490b5ea1 429 //\r
430 // Get AtaDevice data.\r
431 //\r
432 if (BlockIo != NULL) {\r
433 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (BlockIo);\r
434 } else {\r
435 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (BlockIo2);\r
436 } \r
ad86a50a 437\r
438 //\r
439 // Close the child handle\r
440 //\r
441 gBS->CloseProtocol (\r
442 Controller,\r
443 &gEfiAtaPassThruProtocolGuid,\r
444 This->DriverBindingHandle,\r
445 Handle\r
446 );\r
447\r
490b5ea1 448 //\r
449 // The Ata Bus driver installs the BlockIo and BlockIo2 in the DriverBindingStart().\r
450 // Here should uninstall both of them.\r
451 //\r
ad86a50a 452 Status = gBS->UninstallMultipleProtocolInterfaces (\r
453 Handle,\r
454 &gEfiDevicePathProtocolGuid,\r
455 AtaDevice->DevicePath,\r
456 &gEfiBlockIoProtocolGuid,\r
457 &AtaDevice->BlockIo,\r
490b5ea1 458 &gEfiBlockIo2ProtocolGuid,\r
459 &AtaDevice->BlockIo2,\r
ad86a50a 460 &gEfiDiskInfoProtocolGuid,\r
461 &AtaDevice->DiskInfo,\r
462 NULL\r
463 );\r
464\r
465 if (EFI_ERROR (Status)) {\r
466 gBS->OpenProtocol (\r
467 Controller,\r
468 &gEfiAtaPassThruProtocolGuid,\r
469 (VOID **) &AtaPassThru,\r
470 This->DriverBindingHandle,\r
471 Handle,\r
472 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
473 );\r
474 return Status;\r
475 }\r
476\r
c24097a5 477 //\r
478 // If Storage Security Command Protocol is installed, then uninstall this protocol.\r
479 //\r
480 Status = gBS->OpenProtocol (\r
481 Handle,\r
482 &gEfiStorageSecurityCommandProtocolGuid,\r
483 (VOID **) &StorageSecurity,\r
484 This->DriverBindingHandle,\r
485 Controller,\r
486 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
487 );\r
488\r
489 if (!EFI_ERROR (Status)) {\r
490 Status = gBS->UninstallProtocolInterface (\r
491 Handle,\r
492 &gEfiStorageSecurityCommandProtocolGuid,\r
493 &AtaDevice->StorageSecurity\r
494 );\r
495 if (EFI_ERROR (Status)) {\r
496 gBS->OpenProtocol (\r
497 Controller,\r
498 &gEfiAtaPassThruProtocolGuid,\r
499 (VOID **) &AtaPassThru,\r
500 This->DriverBindingHandle,\r
501 Handle,\r
502 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
503 );\r
3c063fed 504 return Status;\r
c24097a5 505 }\r
506 }\r
507\r
ad86a50a 508 ReleaseAtaResources (AtaDevice);\r
ad86a50a 509 return Status;\r
510}\r
511\r
512\r
513\r
514/**\r
515 Tests to see if this driver supports a given controller. If a child device is provided, \r
516 it further tests to see if this driver supports creating a handle for the specified child device.\r
517\r
518 This function checks to see if the driver specified by This supports the device specified by \r
519 ControllerHandle. Drivers will typically use the device path attached to \r
520 ControllerHandle and/or the services from the bus I/O abstraction attached to \r
521 ControllerHandle to determine if the driver supports ControllerHandle. This function \r
522 may be called many times during platform initialization. In order to reduce boot times, the tests \r
523 performed by this function must be very small, and take as little time as possible to execute. This \r
524 function must not change the state of any hardware devices, and this function must be aware that the \r
525 device specified by ControllerHandle may already be managed by the same driver or a \r
526 different driver. This function must match its calls to AllocatePages() with FreePages(), \r
527 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
528 Since ControllerHandle may have been previously started by the same driver, if a protocol is \r
529 already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
530 to guarantee the state of ControllerHandle is not modified by this function.\r
531\r
532 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
533 @param[in] ControllerHandle The handle of the controller to test. This handle \r
534 must support a protocol interface that supplies \r
535 an I/O abstraction to the driver.\r
536 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
537 parameter is ignored by device drivers, and is optional for bus \r
538 drivers. For bus drivers, if this parameter is not NULL, then \r
539 the bus driver must determine if the bus controller specified \r
540 by ControllerHandle and the child controller specified \r
541 by RemainingDevicePath are both supported by this \r
542 bus driver.\r
543\r
544 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
545 RemainingDevicePath is supported by the driver specified by This.\r
546 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
547 RemainingDevicePath is already being managed by the driver\r
548 specified by This.\r
549 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
550 RemainingDevicePath is already being managed by a different\r
551 driver or an application that requires exclusive access.\r
552 Currently not implemented.\r
553 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
554 RemainingDevicePath is not supported by the driver specified by This.\r
555**/\r
556EFI_STATUS\r
557EFIAPI\r
558AtaBusDriverBindingSupported (\r
559 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
560 IN EFI_HANDLE Controller,\r
561 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
562 )\r
563{\r
564 EFI_STATUS Status;\r
565 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
566 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
567 UINT16 Port;\r
568 UINT16 PortMultiplierPort;\r
490b5ea1 569\r
ad86a50a 570 //\r
571 // Test EFI_ATA_PASS_THRU_PROTOCOL on controller handle.\r
572 //\r
573 Status = gBS->OpenProtocol (\r
574 Controller,\r
575 &gEfiAtaPassThruProtocolGuid,\r
576 (VOID **) &AtaPassThru,\r
577 This->DriverBindingHandle,\r
578 Controller,\r
579 EFI_OPEN_PROTOCOL_BY_DRIVER\r
580 );\r
581\r
582 if (Status == EFI_ALREADY_STARTED) {\r
583 return EFI_SUCCESS;\r
584 }\r
585\r
586 if (EFI_ERROR (Status)) {\r
587 return Status;\r
588 }\r
589\r
590 //\r
591 // Test RemainingDevicePath is valid or not.\r
592 //\r
593 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {\r
594 Status = AtaPassThru->GetDevice (AtaPassThru, RemainingDevicePath, &Port, &PortMultiplierPort);\r
595 if (EFI_ERROR (Status)) {\r
596 return Status;\r
597 }\r
598 }\r
599\r
600 //\r
601 // Close the I/O Abstraction(s) used to perform the supported test\r
602 //\r
603 gBS->CloseProtocol (\r
604 Controller,\r
605 &gEfiAtaPassThruProtocolGuid,\r
606 This->DriverBindingHandle,\r
607 Controller\r
608 );\r
609\r
610 //\r
611 // Open the EFI Device Path protocol needed to perform the supported test\r
612 //\r
613 Status = gBS->OpenProtocol (\r
614 Controller,\r
615 &gEfiDevicePathProtocolGuid,\r
616 (VOID **) &ParentDevicePath,\r
617 This->DriverBindingHandle,\r
618 Controller,\r
619 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
620 );\r
621 return Status;\r
622}\r
623\r
624\r
625/**\r
626 Starts a device controller or a bus controller.\r
627\r
628 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
629 As a result, much of the error checking on the parameters to Start() has been moved into this \r
630 common boot service. It is legal to call Start() from other locations, \r
631 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
632 1. ControllerHandle must be a valid EFI_HANDLE.\r
633 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
634 EFI_DEVICE_PATH_PROTOCOL.\r
635 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
636 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
637\r
638 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
639 @param[in] ControllerHandle The handle of the controller to start. This handle \r
640 must support a protocol interface that supplies \r
641 an I/O abstraction to the driver.\r
642 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
643 parameter is ignored by device drivers, and is optional for bus \r
644 drivers. For a bus driver, if this parameter is NULL, then handles \r
490b5ea1 645 for all the children of Controller are created by this driver.\r
ad86a50a 646 If this parameter is not NULL and the first Device Path Node is \r
647 not the End of Device Path Node, then only the handle for the \r
648 child device specified by the first Device Path Node of \r
649 RemainingDevicePath is created by this driver.\r
650 If the first Device Path Node of RemainingDevicePath is \r
651 the End of Device Path Node, no child handle is created by this\r
652 driver.\r
653\r
654 @retval EFI_SUCCESS The device was started.\r
655 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
656 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
657 @retval Others The driver failded to start the device.\r
658\r
659**/\r
660EFI_STATUS\r
661EFIAPI\r
662AtaBusDriverBindingStart (\r
663 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
664 IN EFI_HANDLE Controller,\r
665 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
666 )\r
667{\r
668 EFI_STATUS Status;\r
669 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
670 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
671 ATA_BUS_DRIVER_DATA *AtaBusDriverData;\r
672 UINT16 Port;\r
673 UINT16 PortMultiplierPort;\r
674\r
675 AtaBusDriverData = NULL;\r
676\r
677 Status = gBS->OpenProtocol (\r
678 Controller,\r
679 &gEfiDevicePathProtocolGuid,\r
680 (VOID **) &ParentDevicePath,\r
681 This->DriverBindingHandle,\r
682 Controller,\r
683 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
684 );\r
685 if (EFI_ERROR (Status)) {\r
686 return Status;\r
687 }\r
688\r
689 Status = gBS->OpenProtocol (\r
690 Controller,\r
691 &gEfiAtaPassThruProtocolGuid,\r
692 (VOID **) &AtaPassThru,\r
693 This->DriverBindingHandle,\r
694 Controller,\r
695 EFI_OPEN_PROTOCOL_BY_DRIVER\r
696 );\r
697 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
698 goto ErrorExit;\r
699 }\r
700\r
701 //\r
702 // Check EFI_ALREADY_STARTED to reuse the original ATA_BUS_DRIVER_DATA.\r
703 //\r
704 if (Status != EFI_ALREADY_STARTED) {\r
705 AtaBusDriverData = AllocateZeroPool (sizeof (ATA_BUS_DRIVER_DATA));\r
706 if (AtaBusDriverData == NULL) {\r
707 Status = EFI_OUT_OF_RESOURCES;\r
708 goto ErrorExit;\r
709 }\r
710\r
711 AtaBusDriverData->AtaPassThru = AtaPassThru;\r
490b5ea1 712 AtaBusDriverData->Controller = Controller;\r
ad86a50a 713 AtaBusDriverData->ParentDevicePath = ParentDevicePath;\r
714 AtaBusDriverData->DriverBindingHandle = This->DriverBindingHandle;\r
715\r
716 Status = gBS->InstallMultipleProtocolInterfaces (\r
717 &Controller,\r
718 &gEfiCallerIdGuid,\r
719 AtaBusDriverData,\r
720 NULL\r
721 );\r
722 if (EFI_ERROR (Status)) {\r
723 goto ErrorExit;\r
724 }\r
725\r
726 } else {\r
727 Status = gBS->OpenProtocol (\r
728 Controller,\r
729 &gEfiCallerIdGuid,\r
730 (VOID **) &AtaBusDriverData,\r
731 This->DriverBindingHandle,\r
732 Controller,\r
733 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
734 );\r
735 if (EFI_ERROR (Status)) {\r
736 AtaBusDriverData = NULL;\r
737 goto ErrorExit;\r
738 }\r
739 }\r
740\r
741 if (RemainingDevicePath == NULL) {\r
742 Port = 0xFFFF;\r
743 while (TRUE) {\r
744 Status = AtaPassThru->GetNextPort (AtaPassThru, &Port);\r
745 if (EFI_ERROR (Status)) {\r
746 //\r
747 // We cannot find more legal port then we are done.\r
748 //\r
749 break;\r
750 }\r
490b5ea1 751\r
ad86a50a 752 PortMultiplierPort = 0xFFFF;\r
753 while (TRUE) {\r
754 Status = AtaPassThru->GetNextDevice (AtaPassThru, Port, &PortMultiplierPort);\r
755 if (EFI_ERROR (Status)) {\r
756 //\r
757 // We cannot find more legal port multiplier port number for ATA device\r
758 // on the port, then we are done.\r
759 //\r
760 break;\r
761 }\r
762 RegisterAtaDevice (AtaBusDriverData, Port, PortMultiplierPort);\r
763 }\r
764 }\r
765 Status = EFI_SUCCESS;\r
766 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
767 Status = AtaPassThru->GetDevice (AtaPassThru, RemainingDevicePath, &Port, &PortMultiplierPort);\r
768 if (!EFI_ERROR (Status)) {\r
769 Status = RegisterAtaDevice (AtaBusDriverData,Port, PortMultiplierPort);\r
770 }\r
771 }\r
490b5ea1 772\r
ad86a50a 773 return Status;\r
774\r
775ErrorExit:\r
776\r
777 if (AtaBusDriverData != NULL) {\r
778 gBS->UninstallMultipleProtocolInterfaces (\r
779 Controller,\r
780 &gEfiCallerIdGuid,\r
781 AtaBusDriverData,\r
782 NULL\r
783 );\r
784 FreePool (AtaBusDriverData);\r
785 }\r
786\r
787 gBS->CloseProtocol (\r
788 Controller,\r
789 &gEfiAtaPassThruProtocolGuid,\r
790 This->DriverBindingHandle,\r
791 Controller\r
792 );\r
793\r
794 return Status;\r
795\r
796}\r
797\r
798\r
799/**\r
800 Stops a device controller or a bus controller.\r
801 \r
802 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
803 As a result, much of the error checking on the parameters to Stop() has been moved \r
804 into this common boot service. It is legal to call Stop() from other locations, \r
805 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
806 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
807 same driver's Start() function.\r
808 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
809 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
810 Start() function, and the Start() function must have called OpenProtocol() on\r
811 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
812 \r
813 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
814 @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
815 support a bus specific I/O protocol for the driver \r
816 to use to stop the device.\r
817 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
818 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
819 if NumberOfChildren is 0.\r
820\r
821 @retval EFI_SUCCESS The device was stopped.\r
822 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
823\r
824**/\r
825EFI_STATUS\r
826EFIAPI\r
827AtaBusDriverBindingStop (\r
828 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
829 IN EFI_HANDLE Controller,\r
830 IN UINTN NumberOfChildren,\r
831 IN EFI_HANDLE *ChildHandleBuffer\r
832 )\r
833{\r
834 EFI_STATUS Status;\r
835 BOOLEAN AllChildrenStopped;\r
836 UINTN Index;\r
837 ATA_BUS_DRIVER_DATA *AtaBusDriverData;\r
838\r
839 if (NumberOfChildren == 0) {\r
840 Status = gBS->OpenProtocol (\r
841 Controller,\r
842 &gEfiCallerIdGuid,\r
843 (VOID **) &AtaBusDriverData,\r
844 This->DriverBindingHandle,\r
845 Controller,\r
846 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
847 );\r
848 if (!EFI_ERROR (Status)) {\r
849 gBS->UninstallMultipleProtocolInterfaces (\r
850 Controller,\r
851 &gEfiCallerIdGuid,\r
852 AtaBusDriverData,\r
853 NULL\r
854 );\r
855 FreePool (AtaBusDriverData);\r
856 }\r
857\r
858 gBS->CloseProtocol (\r
859 Controller,\r
860 &gEfiAtaPassThruProtocolGuid,\r
861 This->DriverBindingHandle,\r
862 Controller\r
863 );\r
864\r
865 return EFI_SUCCESS;\r
866 }\r
867\r
868 AllChildrenStopped = TRUE;\r
869\r
870 for (Index = 0; Index < NumberOfChildren; Index++) {\r
871\r
872 Status = UnregisterAtaDevice (This, Controller, ChildHandleBuffer[Index]);\r
873 if (EFI_ERROR (Status)) {\r
874 AllChildrenStopped = FALSE;\r
875 }\r
876 }\r
877\r
878 if (!AllChildrenStopped) {\r
879 return EFI_DEVICE_ERROR;\r
880 }\r
881\r
882 return EFI_SUCCESS;\r
883}\r
884\r
885\r
886/**\r
887 Reset the Block Device.\r
888\r
889 @param This Indicates a pointer to the calling context.\r
890 @param ExtendedVerification Driver may perform diagnostics on reset.\r
891\r
892 @retval EFI_SUCCESS The device was reset.\r
893 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
894 not be reset.\r
895\r
896**/\r
897EFI_STATUS\r
898EFIAPI\r
899AtaBlockIoReset (\r
900 IN EFI_BLOCK_IO_PROTOCOL *This,\r
901 IN BOOLEAN ExtendedVerification\r
902 )\r
903{\r
904 EFI_STATUS Status;\r
905 ATA_DEVICE *AtaDevice;\r
906 EFI_TPL OldTpl;\r
907\r
908 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
909\r
910 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
911\r
490b5ea1 912 Status = ResetAtaDevice (AtaDevice);\r
ad86a50a 913\r
c6e797ae 914 if (EFI_ERROR (Status)) {\r
915 Status = EFI_DEVICE_ERROR;\r
916 }\r
917\r
ad86a50a 918 gBS->RestoreTPL (OldTpl);\r
919 return Status;\r
920}\r
921\r
922\r
923/**\r
924 Read/Write BufferSize bytes from Lba from/into Buffer.\r
925\r
490b5ea1 926 @param[in] This Indicates a pointer to the calling context. Either be\r
927 block I/O or block I/O2. \r
928 @param[in] MediaId The media ID that the read/write request is for.\r
929 @param[in] Lba The starting logical block address to be read/written.\r
930 The caller is responsible for reading/writing to only\r
931 legitimate locations.\r
932 @param[in, out] Token A pointer to the token associated with the transaction.\r
933 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
934 @param[out] Buffer A pointer to the destination/source buffer for the data.\r
935 @param[in] IsBlockIo2 Indicate the calling is from BlockIO or BlockIO2. TURE is\r
936 from BlockIO2, FALSE is for BlockIO.\r
937 @param[in] IsWrite Indicates whether it is a write operation.\r
ad86a50a 938\r
939 @retval EFI_SUCCESS The data was read/written correctly to the device.\r
940 @retval EFI_WRITE_PROTECTED The device can not be read/written to.\r
941 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.\r
942 @retval EFI_NO_MEDIA There is no media in the device.\r
943 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
944 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
945 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid, \r
946 or the buffer is not on proper alignment.\r
947\r
948**/\r
949EFI_STATUS\r
950BlockIoReadWrite (\r
490b5ea1 951 IN VOID *This,\r
952 IN UINT32 MediaId,\r
953 IN EFI_LBA Lba,\r
954 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
955 IN UINTN BufferSize,\r
956 OUT VOID *Buffer,\r
957 IN BOOLEAN IsBlockIo2,\r
958 IN BOOLEAN IsWrite\r
ad86a50a 959 )\r
960{\r
961 ATA_DEVICE *AtaDevice;\r
962 EFI_STATUS Status;\r
963 EFI_TPL OldTpl;\r
964 EFI_BLOCK_IO_MEDIA *Media;\r
965 UINTN BlockSize;\r
966 UINTN NumberOfBlocks;\r
967 UINTN IoAlign;\r
968\r
490b5ea1 969 if (IsBlockIo2) {\r
970 Media = ((EFI_BLOCK_IO2_PROTOCOL *) This)->Media;\r
971 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);\r
972 } else {\r
973 Media = ((EFI_BLOCK_IO_PROTOCOL *) This)->Media;\r
974 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
975 }\r
976\r
fcf5e49d
RN
977 if (MediaId != Media->MediaId) {\r
978 return EFI_MEDIA_CHANGED;\r
979 }\r
980\r
490b5ea1 981 //\r
982 // Check parameters.\r
983 //\r
ad86a50a 984 if (Buffer == NULL) {\r
985 return EFI_INVALID_PARAMETER;\r
986 }\r
987\r
988 if (BufferSize == 0) {\r
989 return EFI_SUCCESS;\r
490b5ea1 990 } \r
ad86a50a 991\r
ad86a50a 992 BlockSize = Media->BlockSize;\r
993 if ((BufferSize % BlockSize) != 0) {\r
994 return EFI_BAD_BUFFER_SIZE;\r
995 }\r
996 \r
997 NumberOfBlocks = BufferSize / BlockSize;\r
998 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
999 return EFI_INVALID_PARAMETER;\r
1000 }\r
1001\r
1002 IoAlign = Media->IoAlign;\r
1003 if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {\r
1004 return EFI_INVALID_PARAMETER;\r
1005 }\r
1006\r
1007 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ad86a50a 1008 \r
1009 //\r
1010 // Invoke low level AtaDevice Access Routine.\r
1011 //\r
490b5ea1 1012 Status = AccessAtaDevice (AtaDevice, Buffer, Lba, NumberOfBlocks, IsWrite, Token);\r
ad86a50a 1013 \r
1014 gBS->RestoreTPL (OldTpl);\r
1015\r
1016 return Status;\r
1017}\r
1018\r
1019\r
1020/**\r
1021 Read BufferSize bytes from Lba into Buffer.\r
1022\r
1023 @param This Indicates a pointer to the calling context.\r
1024 @param MediaId Id of the media, changes every time the media is replaced.\r
1025 @param Lba The starting Logical Block Address to read from\r
1026 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
1027 @param Buffer A pointer to the destination buffer for the data. The caller is\r
1028 responsible for either having implicit or explicit ownership of the buffer.\r
1029\r
1030 @retval EFI_SUCCESS The data was read correctly from the device.\r
1031 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
1032 @retval EFI_NO_MEDIA There is no media in the device.\r
1033 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
1034 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
1035 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
1036 or the buffer is not on proper alignment.\r
1037\r
1038**/\r
1039EFI_STATUS\r
1040EFIAPI\r
1041AtaBlockIoReadBlocks (\r
1042 IN EFI_BLOCK_IO_PROTOCOL *This,\r
1043 IN UINT32 MediaId,\r
1044 IN EFI_LBA Lba,\r
1045 IN UINTN BufferSize,\r
1046 OUT VOID *Buffer\r
1047 )\r
1048{\r
490b5ea1 1049 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, FALSE);\r
ad86a50a 1050}\r
1051\r
1052\r
1053/**\r
1054 Write BufferSize bytes from Lba into Buffer.\r
1055\r
1056 @param This Indicates a pointer to the calling context.\r
1057 @param MediaId The media ID that the write request is for.\r
1058 @param Lba The starting logical block address to be written. The caller is\r
1059 responsible for writing to only legitimate locations.\r
1060 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
1061 @param Buffer A pointer to the source buffer for the data.\r
1062\r
1063 @retval EFI_SUCCESS The data was written correctly to the device.\r
1064 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
1065 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
1066 @retval EFI_NO_MEDIA There is no media in the device.\r
1067 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
1068 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
1069 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
1070 or the buffer is not on proper alignment.\r
1071\r
1072**/\r
1073EFI_STATUS\r
1074EFIAPI\r
1075AtaBlockIoWriteBlocks (\r
1076 IN EFI_BLOCK_IO_PROTOCOL *This,\r
1077 IN UINT32 MediaId,\r
1078 IN EFI_LBA Lba,\r
1079 IN UINTN BufferSize,\r
1080 IN VOID *Buffer\r
1081 )\r
1082{\r
490b5ea1 1083 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, TRUE);\r
ad86a50a 1084}\r
1085\r
1086\r
1087/**\r
1088 Flush the Block Device.\r
1089\r
1090 @param This Indicates a pointer to the calling context.\r
1091\r
1092 @retval EFI_SUCCESS All outstanding data was written to the device\r
1093 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
1094 @retval EFI_NO_MEDIA There is no media in the device.\r
1095\r
1096**/\r
1097EFI_STATUS\r
1098EFIAPI\r
1099AtaBlockIoFlushBlocks (\r
1100 IN EFI_BLOCK_IO_PROTOCOL *This\r
1101 )\r
1102{\r
1103 //\r
1104 // return directly\r
1105 //\r
1106 return EFI_SUCCESS;\r
1107}\r
1108\r
490b5ea1 1109/**\r
1110 Reset the Block Device.\r
1111\r
1112 @param[in] This Indicates a pointer to the calling context.\r
1113 @param[in] ExtendedVerification Driver may perform diagnostics on reset.\r
1114\r
1115 @retval EFI_SUCCESS The device was reset.\r
1116 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
1117 not be reset.\r
1118\r
1119**/\r
1120EFI_STATUS\r
1121EFIAPI\r
1122AtaBlockIoResetEx (\r
1123 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1124 IN BOOLEAN ExtendedVerification\r
1125 )\r
1126{\r
1127 EFI_STATUS Status;\r
1128 ATA_DEVICE *AtaDevice;\r
1129 EFI_TPL OldTpl;\r
1130\r
1131 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1132\r
1133 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);\r
1134\r
1135 Status = ResetAtaDevice (AtaDevice);\r
1136\r
1137 if (EFI_ERROR (Status)) {\r
1138 Status = EFI_DEVICE_ERROR;\r
1139 }\r
1140\r
1141 gBS->RestoreTPL (OldTpl);\r
1142 return Status;\r
1143}\r
1144\r
1145/**\r
1146 Read BufferSize bytes from Lba into Buffer.\r
1147\r
1148 @param[in] This Indicates a pointer to the calling context.\r
1149 @param[in] MediaId Id of the media, changes every time the media is replaced.\r
1150 @param[in] Lba The starting Logical Block Address to read from.\r
1151 @param[in, out] Token A pointer to the token associated with the transaction.\r
1152 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
1153 @param[out] Buffer A pointer to the destination buffer for the data. The caller is\r
1154 responsible for either having implicit or explicit ownership of the buffer.\r
1155\r
1156 @retval EFI_SUCCESS The read request was queued if Event is not NULL.\r
1157 The data was read correctly from the device if\r
1158 the Event is NULL.\r
1159 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
1160 the read.\r
1161 @retval EFI_NO_MEDIA There is no media in the device.\r
1162 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1163 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
1164 intrinsic block size of the device.\r
1165 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
1166 or the buffer is not on proper alignment.\r
1167 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
1168 of resources.\r
1169\r
1170**/\r
1171EFI_STATUS\r
1172EFIAPI\r
1173AtaBlockIoReadBlocksEx (\r
1174 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1175 IN UINT32 MediaId,\r
1176 IN EFI_LBA Lba,\r
1177 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
1178 IN UINTN BufferSize,\r
1179 OUT VOID *Buffer\r
1180 )\r
1181{\r
1182 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, FALSE);\r
1183}\r
1184\r
1185\r
1186/**\r
1187 Write BufferSize bytes from Lba into Buffer.\r
1188\r
1189 @param[in] This Indicates a pointer to the calling context.\r
1190 @param[in] MediaId The media ID that the write request is for.\r
1191 @param[in] Lba The starting logical block address to be written. The\r
1192 caller is responsible for writing to only legitimate\r
1193 locations.\r
1194 @param[in, out] Token A pointer to the token associated with the transaction.\r
1195 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
1196 @param[in] Buffer A pointer to the source buffer for the data.\r
ad86a50a 1197\r
490b5ea1 1198 @retval EFI_SUCCESS The data was written correctly to the device.\r
1199 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
1200 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
1201 @retval EFI_NO_MEDIA There is no media in the device.\r
1202 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
1203 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
1204 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
1205 or the buffer is not on proper alignment.\r
1206\r
1207**/\r
1208EFI_STATUS\r
1209EFIAPI\r
1210AtaBlockIoWriteBlocksEx (\r
1211 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1212 IN UINT32 MediaId,\r
1213 IN EFI_LBA Lba,\r
1214 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
1215 IN UINTN BufferSize,\r
1216 IN VOID *Buffer\r
1217 )\r
1218{\r
1219 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, TRUE);\r
1220}\r
1221\r
1222\r
1223/**\r
1224 Flush the Block Device.\r
1225\r
1226 @param[in] This Indicates a pointer to the calling context.\r
1227 @param[in, out] Token A pointer to the token associated with the transaction.\r
1228\r
1229 @retval EFI_SUCCESS All outstanding data was written to the device\r
1230 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
1231 @retval EFI_NO_MEDIA There is no media in the device.\r
1232\r
1233**/\r
1234EFI_STATUS\r
1235EFIAPI\r
1236AtaBlockIoFlushBlocksEx (\r
1237 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1238 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
1239 )\r
1240{\r
1241 //\r
3c063fed 1242 // Signal event and return directly.\r
490b5ea1 1243 //\r
1244 if (Token != NULL && Token->Event != NULL) {\r
1245 Token->TransactionStatus = EFI_SUCCESS;\r
1246 gBS->SignalEvent (Token->Event);\r
1247 }\r
1248 return EFI_SUCCESS;\r
1249}\r
ad86a50a 1250/**\r
1251 Provides inquiry information for the controller type.\r
1252 \r
1253 This function is used by the IDE bus driver to get inquiry data. Data format\r
1254 of Identify data is defined by the Interface GUID.\r
1255\r
05a44e91 1256 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1257 @param[in, out] InquiryData Pointer to a buffer for the inquiry data.\r
1258 @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.\r
ad86a50a 1259\r
1260 @retval EFI_SUCCESS The command was accepted without any errors.\r
1261 @retval EFI_NOT_FOUND Device does not support this data class \r
1262 @retval EFI_DEVICE_ERROR Error reading InquiryData from device \r
1263 @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough \r
1264\r
1265**/\r
1266EFI_STATUS\r
1267EFIAPI\r
1268AtaDiskInfoInquiry (\r
1269 IN EFI_DISK_INFO_PROTOCOL *This,\r
1270 IN OUT VOID *InquiryData,\r
1271 IN OUT UINT32 *InquiryDataSize\r
1272 )\r
1273{\r
1274 return EFI_NOT_FOUND;\r
1275}\r
1276\r
1277\r
1278/**\r
1279 Provides identify information for the controller type.\r
1280\r
1281 This function is used by the IDE bus driver to get identify data. Data format\r
1282 of Identify data is defined by the Interface GUID.\r
1283\r
05a44e91 1284 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL \r
ad86a50a 1285 instance.\r
05a44e91 1286 @param[in, out] IdentifyData Pointer to a buffer for the identify data.\r
1287 @param[in, out] IdentifyDataSize Pointer to the value for the identify data\r
ad86a50a 1288 size.\r
1289\r
1290 @retval EFI_SUCCESS The command was accepted without any errors.\r
1291 @retval EFI_NOT_FOUND Device does not support this data class \r
1292 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device \r
1293 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough \r
1294\r
1295**/\r
1296EFI_STATUS\r
1297EFIAPI\r
1298AtaDiskInfoIdentify (\r
1299 IN EFI_DISK_INFO_PROTOCOL *This,\r
1300 IN OUT VOID *IdentifyData,\r
1301 IN OUT UINT32 *IdentifyDataSize\r
1302 )\r
1303{\r
1304 EFI_STATUS Status;\r
1305 ATA_DEVICE *AtaDevice;\r
1306\r
1307 AtaDevice = ATA_DEVICE_FROM_DISK_INFO (This);\r
1308\r
1309 Status = EFI_BUFFER_TOO_SMALL;\r
3c063fed 1310 if (*IdentifyDataSize >= sizeof (ATA_IDENTIFY_DATA)) {\r
ad86a50a 1311 Status = EFI_SUCCESS;\r
3c063fed 1312 CopyMem (IdentifyData, AtaDevice->IdentifyData, sizeof (ATA_IDENTIFY_DATA));\r
ad86a50a 1313 }\r
3c063fed 1314 *IdentifyDataSize = sizeof (ATA_IDENTIFY_DATA);\r
ad86a50a 1315\r
1316 return Status;\r
1317}\r
1318\r
1319\r
1320/**\r
1321 Provides sense data information for the controller type.\r
1322 \r
1323 This function is used by the IDE bus driver to get sense data. \r
1324 Data format of Sense data is defined by the Interface GUID.\r
1325\r
05a44e91 1326 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1327 @param[in, out] SenseData Pointer to the SenseData.\r
1328 @param[in, out] SenseDataSize Size of SenseData in bytes.\r
1329 @param[out] SenseDataNumber Pointer to the value for the sense data size.\r
ad86a50a 1330\r
1331 @retval EFI_SUCCESS The command was accepted without any errors.\r
1332 @retval EFI_NOT_FOUND Device does not support this data class.\r
1333 @retval EFI_DEVICE_ERROR Error reading SenseData from device.\r
1334 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.\r
1335\r
1336**/\r
1337EFI_STATUS\r
1338EFIAPI\r
1339AtaDiskInfoSenseData (\r
1340 IN EFI_DISK_INFO_PROTOCOL *This,\r
1341 IN OUT VOID *SenseData,\r
1342 IN OUT UINT32 *SenseDataSize,\r
1343 OUT UINT8 *SenseDataNumber\r
1344 )\r
1345{\r
1346 return EFI_NOT_FOUND;\r
1347}\r
1348\r
1349\r
1350/**\r
1351 This function is used by the IDE bus driver to get controller information.\r
1352\r
1353 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. \r
1354 @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.\r
1355 @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.\r
1356\r
1357 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.\r
1358 @retval EFI_UNSUPPORTED This is not an IDE device.\r
1359\r
1360**/\r
1361EFI_STATUS\r
1362EFIAPI\r
1363AtaDiskInfoWhichIde (\r
1364 IN EFI_DISK_INFO_PROTOCOL *This,\r
1365 OUT UINT32 *IdeChannel,\r
1366 OUT UINT32 *IdeDevice\r
1367 )\r
1368{\r
1369 ATA_DEVICE *AtaDevice;\r
1370\r
1371 AtaDevice = ATA_DEVICE_FROM_DISK_INFO (This);\r
1372 *IdeChannel = AtaDevice->Port;\r
1373 *IdeDevice = AtaDevice->PortMultiplierPort;\r
1374\r
1375 return EFI_SUCCESS;\r
1376}\r
1377\r
c24097a5 1378/**\r
1379 Send a security protocol command to a device that receives data and/or the result\r
1380 of one or more commands sent by SendData.\r
1381\r
1382 The ReceiveData function sends a security protocol command to the given MediaId.\r
1383 The security protocol command sent is defined by SecurityProtocolId and contains\r
1384 the security protocol specific data SecurityProtocolSpecificData. The function\r
1385 returns the data from the security protocol command in PayloadBuffer.\r
1386\r
1387 For devices supporting the SCSI command set, the security protocol command is sent\r
1388 using the SECURITY PROTOCOL IN command defined in SPC-4.\r
1389\r
1390 For devices supporting the ATA command set, the security protocol command is sent\r
1391 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize\r
1392 is non-zero.\r
1393\r
1394 If the PayloadBufferSize is zero, the security protocol command is sent using the\r
1395 Trusted Non-Data command defined in ATA8-ACS.\r
1396\r
1397 If PayloadBufferSize is too small to store the available data from the security\r
1398 protocol command, the function shall copy PayloadBufferSize bytes into the\r
1399 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.\r
1400\r
1401 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,\r
1402 the function shall return EFI_INVALID_PARAMETER.\r
1403\r
1404 If the given MediaId does not support security protocol commands, the function shall\r
1405 return EFI_UNSUPPORTED. If there is no media in the device, the function returns\r
1406 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,\r
1407 the function returns EFI_MEDIA_CHANGED.\r
1408\r
1409 If the security protocol fails to complete within the Timeout period, the function\r
1410 shall return EFI_TIMEOUT.\r
1411\r
1412 If the security protocol command completes without an error, the function shall\r
1413 return EFI_SUCCESS. If the security protocol command completes with an error, the\r
1414 function shall return EFI_DEVICE_ERROR.\r
1415\r
1416 @param This Indicates a pointer to the calling context.\r
1417 @param MediaId ID of the medium to receive data from.\r
1418 @param Timeout The timeout, in 100ns units, to use for the execution\r
1419 of the security protocol command. A Timeout value of 0\r
1420 means that this function will wait indefinitely for the\r
1421 security protocol command to execute. If Timeout is greater\r
1422 than zero, then this function will return EFI_TIMEOUT\r
1423 if the time required to execute the receive data command\r
1424 is greater than Timeout.\r
1425 @param SecurityProtocolId The value of the "Security Protocol" parameter of\r
1426 the security protocol command to be sent.\r
1427 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
1428 of the security protocol command to be sent.\r
1429 @param PayloadBufferSize Size in bytes of the payload data buffer.\r
1430 @param PayloadBuffer A pointer to a destination buffer to store the security\r
1431 protocol command specific payload data for the security\r
1432 protocol command. The caller is responsible for having\r
1433 either implicit or explicit ownership of the buffer.\r
1434 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the\r
1435 data written to the payload data buffer.\r
1436\r
1437 @retval EFI_SUCCESS The security protocol command completed successfully.\r
1438 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available\r
1439 data from the device. The PayloadBuffer contains the truncated data.\r
1440 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.\r
1441 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.\r
1442 @retval EFI_NO_MEDIA There is no media in the device.\r
1443 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1444 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and\r
1445 PayloadBufferSize is non-zero.\r
1446 @retval EFI_TIMEOUT A timeout occurred while waiting for the security\r
1447 protocol command to execute.\r
1448\r
1449**/\r
1450EFI_STATUS\r
1451EFIAPI\r
1452AtaStorageSecurityReceiveData (\r
1453 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,\r
1454 IN UINT32 MediaId,\r
1455 IN UINT64 Timeout,\r
1456 IN UINT8 SecurityProtocolId,\r
1457 IN UINT16 SecurityProtocolSpecificData,\r
1458 IN UINTN PayloadBufferSize,\r
1459 OUT VOID *PayloadBuffer,\r
1460 OUT UINTN *PayloadTransferSize\r
1461 )\r
1462{\r
1463 EFI_STATUS Status;\r
1464 ATA_DEVICE *Private;\r
3c063fed 1465 EFI_TPL OldTpl;\r
c24097a5 1466\r
1467 DEBUG ((EFI_D_INFO, "EFI Storage Security Protocol - Read"));\r
1468 if ((PayloadBuffer == NULL || PayloadTransferSize == NULL) && PayloadBufferSize != 0) {\r
1469 return EFI_INVALID_PARAMETER;\r
1470 }\r
1471\r
1472 Status = EFI_SUCCESS;\r
1473 Private = ATA_DEVICE_FROM_STORAGE_SECURITY (This);\r
1474\r
1475 if (MediaId != Private->BlockIo.Media->MediaId) {\r
1476 return EFI_MEDIA_CHANGED;\r
1477 }\r
1478\r
1479 if (!Private->BlockIo.Media->MediaPresent) {\r
1480 return EFI_NO_MEDIA;\r
1481 }\r
1482\r
3c063fed 1483 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1484\r
c24097a5 1485 Status = TrustTransferAtaDevice (\r
1486 Private,\r
1487 PayloadBuffer,\r
1488 SecurityProtocolId,\r
1489 SecurityProtocolSpecificData,\r
1490 PayloadBufferSize,\r
1491 FALSE,\r
1492 Timeout,\r
1493 PayloadTransferSize\r
1494 );\r
1495\r
3c063fed 1496 gBS->RestoreTPL (OldTpl);\r
c24097a5 1497 return Status;\r
1498}\r
1499\r
1500/**\r
1501 Send a security protocol command to a device.\r
1502\r
1503 The SendData function sends a security protocol command containing the payload\r
1504 PayloadBuffer to the given MediaId. The security protocol command sent is\r
1505 defined by SecurityProtocolId and contains the security protocol specific data\r
1506 SecurityProtocolSpecificData. If the underlying protocol command requires a\r
1507 specific padding for the command payload, the SendData function shall add padding\r
1508 bytes to the command payload to satisfy the padding requirements.\r
1509\r
1510 For devices supporting the SCSI command set, the security protocol command is sent\r
1511 using the SECURITY PROTOCOL OUT command defined in SPC-4.\r
1512\r
1513 For devices supporting the ATA command set, the security protocol command is sent\r
1514 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize\r
1515 is non-zero. If the PayloadBufferSize is zero, the security protocol command is\r
1516 sent using the Trusted Non-Data command defined in ATA8-ACS.\r
1517\r
1518 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall\r
1519 return EFI_INVALID_PARAMETER.\r
1520\r
1521 If the given MediaId does not support security protocol commands, the function\r
1522 shall return EFI_UNSUPPORTED. If there is no media in the device, the function\r
1523 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the\r
1524 device, the function returns EFI_MEDIA_CHANGED.\r
1525\r
1526 If the security protocol fails to complete within the Timeout period, the function\r
1527 shall return EFI_TIMEOUT.\r
1528\r
1529 If the security protocol command completes without an error, the function shall return\r
1530 EFI_SUCCESS. If the security protocol command completes with an error, the function\r
1531 shall return EFI_DEVICE_ERROR.\r
1532\r
1533 @param This Indicates a pointer to the calling context.\r
1534 @param MediaId ID of the medium to receive data from.\r
1535 @param Timeout The timeout, in 100ns units, to use for the execution\r
1536 of the security protocol command. A Timeout value of 0\r
1537 means that this function will wait indefinitely for the\r
1538 security protocol command to execute. If Timeout is greater\r
1539 than zero, then this function will return EFI_TIMEOUT\r
1540 if the time required to execute the receive data command\r
1541 is greater than Timeout.\r
1542 @param SecurityProtocolId The value of the "Security Protocol" parameter of\r
1543 the security protocol command to be sent.\r
1544 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
1545 of the security protocol command to be sent.\r
1546 @param PayloadBufferSize Size in bytes of the payload data buffer.\r
1547 @param PayloadBuffer A pointer to a destination buffer to store the security\r
1548 protocol command specific payload data for the security\r
1549 protocol command.\r
1550\r
1551 @retval EFI_SUCCESS The security protocol command completed successfully.\r
1552 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.\r
1553 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.\r
1554 @retval EFI_NO_MEDIA There is no media in the device.\r
1555 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1556 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.\r
1557 @retval EFI_TIMEOUT A timeout occurred while waiting for the security\r
1558 protocol command to execute.\r
1559\r
1560**/\r
1561EFI_STATUS\r
1562EFIAPI\r
1563AtaStorageSecuritySendData (\r
1564 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,\r
1565 IN UINT32 MediaId,\r
1566 IN UINT64 Timeout,\r
1567 IN UINT8 SecurityProtocolId,\r
1568 IN UINT16 SecurityProtocolSpecificData,\r
1569 IN UINTN PayloadBufferSize,\r
1570 IN VOID *PayloadBuffer\r
1571 )\r
1572{\r
1573 EFI_STATUS Status;\r
1574 ATA_DEVICE *Private;\r
3c063fed 1575 EFI_TPL OldTpl;\r
c24097a5 1576\r
1577 DEBUG ((EFI_D_INFO, "EFI Storage Security Protocol - Send"));\r
1578 if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {\r
1579 return EFI_INVALID_PARAMETER;\r
1580 }\r
1581\r
1582 Status = EFI_SUCCESS;\r
1583 Private = ATA_DEVICE_FROM_STORAGE_SECURITY (This);\r
1584\r
1585 if (MediaId != Private->BlockIo.Media->MediaId) {\r
1586 return EFI_MEDIA_CHANGED;\r
1587 }\r
1588\r
3c063fed 1589 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
c24097a5 1590 Status = TrustTransferAtaDevice (\r
1591 Private,\r
1592 PayloadBuffer,\r
1593 SecurityProtocolId,\r
1594 SecurityProtocolSpecificData,\r
1595 PayloadBufferSize,\r
1596 TRUE,\r
1597 Timeout,\r
1598 NULL\r
1599 );\r
1600\r
3c063fed 1601 gBS->RestoreTPL (OldTpl);\r
c24097a5 1602 return Status;\r
1603}\r
ad86a50a 1604\r
1605/**\r
1606 The user Entry Point for module AtaBus. The user code starts with this function.\r
1607\r
1608 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1609 @param[in] SystemTable A pointer to the EFI System Table.\r
1610\r
1611 @retval EFI_SUCCESS The entry point is executed successfully.\r
1612 @retval other Some error occurs when executing this entry point.\r
1613\r
1614**/\r
1615EFI_STATUS\r
1616EFIAPI\r
1617InitializeAtaBus(\r
1618 IN EFI_HANDLE ImageHandle,\r
1619 IN EFI_SYSTEM_TABLE *SystemTable\r
1620 )\r
1621{\r
1622 EFI_STATUS Status;\r
1623\r
1624 //\r
1625 // Install driver model protocol(s).\r
1626 //\r
1627 Status = EfiLibInstallDriverBindingComponentName2 (\r
1628 ImageHandle,\r
1629 SystemTable,\r
1630 &gAtaBusDriverBinding,\r
1631 ImageHandle,\r
1632 &gAtaBusComponentName,\r
1633 &gAtaBusComponentName2\r
1634 );\r
1635 ASSERT_EFI_ERROR (Status);\r
1636\r
1637 return Status;\r
1638}\r