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