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