]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
Add TperReset Logic By using MOR bit - Remove the unnecessary parameter.
[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
467 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (BlockIo2);\r
58727f29 468 }\r
ad86a50a 469\r
470 //\r
471 // Close the child handle\r
472 //\r
473 gBS->CloseProtocol (\r
474 Controller,\r
475 &gEfiAtaPassThruProtocolGuid,\r
476 This->DriverBindingHandle,\r
477 Handle\r
478 );\r
479\r
490b5ea1 480 //\r
481 // The Ata Bus driver installs the BlockIo and BlockIo2 in the DriverBindingStart().\r
482 // Here should uninstall both of them.\r
483 //\r
ad86a50a 484 Status = gBS->UninstallMultipleProtocolInterfaces (\r
485 Handle,\r
486 &gEfiDevicePathProtocolGuid,\r
487 AtaDevice->DevicePath,\r
488 &gEfiBlockIoProtocolGuid,\r
489 &AtaDevice->BlockIo,\r
490b5ea1 490 &gEfiBlockIo2ProtocolGuid,\r
491 &AtaDevice->BlockIo2,\r
ad86a50a 492 &gEfiDiskInfoProtocolGuid,\r
493 &AtaDevice->DiskInfo,\r
494 NULL\r
495 );\r
496\r
497 if (EFI_ERROR (Status)) {\r
498 gBS->OpenProtocol (\r
499 Controller,\r
500 &gEfiAtaPassThruProtocolGuid,\r
501 (VOID **) &AtaPassThru,\r
502 This->DriverBindingHandle,\r
503 Handle,\r
504 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
505 );\r
506 return Status;\r
507 }\r
508\r
c24097a5 509 //\r
510 // If Storage Security Command Protocol is installed, then uninstall this protocol.\r
511 //\r
512 Status = gBS->OpenProtocol (\r
513 Handle,\r
514 &gEfiStorageSecurityCommandProtocolGuid,\r
515 (VOID **) &StorageSecurity,\r
516 This->DriverBindingHandle,\r
517 Controller,\r
518 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
519 );\r
520\r
521 if (!EFI_ERROR (Status)) {\r
522 Status = gBS->UninstallProtocolInterface (\r
523 Handle,\r
524 &gEfiStorageSecurityCommandProtocolGuid,\r
525 &AtaDevice->StorageSecurity\r
526 );\r
527 if (EFI_ERROR (Status)) {\r
528 gBS->OpenProtocol (\r
529 Controller,\r
530 &gEfiAtaPassThruProtocolGuid,\r
531 (VOID **) &AtaPassThru,\r
532 This->DriverBindingHandle,\r
533 Handle,\r
534 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
535 );\r
3c063fed 536 return Status;\r
c24097a5 537 }\r
538 }\r
539\r
ad86a50a 540 ReleaseAtaResources (AtaDevice);\r
7f070be5 541 return EFI_SUCCESS;\r
ad86a50a 542}\r
543\r
544\r
545\r
546/**\r
58727f29 547 Tests to see if this driver supports a given controller. If a child device is provided,\r
ad86a50a 548 it further tests to see if this driver supports creating a handle for the specified child device.\r
549\r
58727f29 550 This function checks to see if the driver specified by This supports the device specified by\r
551 ControllerHandle. Drivers will typically use the device path attached to\r
552 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
553 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
554 may be called many times during platform initialization. In order to reduce boot times, the tests\r
555 performed by this function must be very small, and take as little time as possible to execute. This\r
556 function must not change the state of any hardware devices, and this function must be aware that the\r
557 device specified by ControllerHandle may already be managed by the same driver or a\r
558 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
559 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
560 Since ControllerHandle may have been previously started by the same driver, if a protocol is\r
561 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
ad86a50a 562 to guarantee the state of ControllerHandle is not modified by this function.\r
563\r
564 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
58727f29 565 @param[in] ControllerHandle The handle of the controller to test. This handle\r
566 must support a protocol interface that supplies\r
ad86a50a 567 an I/O abstraction to the driver.\r
58727f29 568 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
569 parameter is ignored by device drivers, and is optional for bus\r
570 drivers. For bus drivers, if this parameter is not NULL, then\r
571 the bus driver must determine if the bus controller specified\r
572 by ControllerHandle and the child controller specified\r
573 by RemainingDevicePath are both supported by this\r
ad86a50a 574 bus driver.\r
575\r
576 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
577 RemainingDevicePath is supported by the driver specified by This.\r
578 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
579 RemainingDevicePath is already being managed by the driver\r
580 specified by This.\r
581 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
582 RemainingDevicePath is already being managed by a different\r
583 driver or an application that requires exclusive access.\r
584 Currently not implemented.\r
585 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
586 RemainingDevicePath is not supported by the driver specified by This.\r
587**/\r
588EFI_STATUS\r
589EFIAPI\r
590AtaBusDriverBindingSupported (\r
591 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
592 IN EFI_HANDLE Controller,\r
593 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
594 )\r
595{\r
596 EFI_STATUS Status;\r
597 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
598 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
599 UINT16 Port;\r
600 UINT16 PortMultiplierPort;\r
490b5ea1 601\r
ad86a50a 602 //\r
603 // Test EFI_ATA_PASS_THRU_PROTOCOL on controller handle.\r
604 //\r
605 Status = gBS->OpenProtocol (\r
606 Controller,\r
607 &gEfiAtaPassThruProtocolGuid,\r
608 (VOID **) &AtaPassThru,\r
609 This->DriverBindingHandle,\r
610 Controller,\r
611 EFI_OPEN_PROTOCOL_BY_DRIVER\r
612 );\r
613\r
614 if (Status == EFI_ALREADY_STARTED) {\r
615 return EFI_SUCCESS;\r
616 }\r
617\r
618 if (EFI_ERROR (Status)) {\r
619 return Status;\r
620 }\r
621\r
622 //\r
623 // Test RemainingDevicePath is valid or not.\r
624 //\r
625 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {\r
626 Status = AtaPassThru->GetDevice (AtaPassThru, RemainingDevicePath, &Port, &PortMultiplierPort);\r
627 if (EFI_ERROR (Status)) {\r
628 return Status;\r
629 }\r
630 }\r
631\r
632 //\r
633 // Close the I/O Abstraction(s) used to perform the supported test\r
634 //\r
635 gBS->CloseProtocol (\r
636 Controller,\r
637 &gEfiAtaPassThruProtocolGuid,\r
638 This->DriverBindingHandle,\r
639 Controller\r
640 );\r
641\r
642 //\r
643 // Open the EFI Device Path protocol needed to perform the supported test\r
644 //\r
645 Status = gBS->OpenProtocol (\r
646 Controller,\r
647 &gEfiDevicePathProtocolGuid,\r
648 (VOID **) &ParentDevicePath,\r
649 This->DriverBindingHandle,\r
650 Controller,\r
651 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
652 );\r
653 return Status;\r
654}\r
655\r
656\r
657/**\r
658 Starts a device controller or a bus controller.\r
659\r
660 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
58727f29 661 As a result, much of the error checking on the parameters to Start() has been moved into this\r
662 common boot service. It is legal to call Start() from other locations,\r
ad86a50a 663 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
664 1. ControllerHandle must be a valid EFI_HANDLE.\r
665 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
666 EFI_DEVICE_PATH_PROTOCOL.\r
667 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
58727f29 668 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
ad86a50a 669\r
670 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
58727f29 671 @param[in] ControllerHandle The handle of the controller to start. This handle\r
672 must support a protocol interface that supplies\r
ad86a50a 673 an I/O abstraction to the driver.\r
58727f29 674 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
675 parameter is ignored by device drivers, and is optional for bus\r
676 drivers. For a bus driver, if this parameter is NULL, then handles\r
490b5ea1 677 for all the children of Controller are created by this driver.\r
58727f29 678 If this parameter is not NULL and the first Device Path Node is\r
679 not the End of Device Path Node, then only the handle for the\r
680 child device specified by the first Device Path Node of\r
ad86a50a 681 RemainingDevicePath is created by this driver.\r
58727f29 682 If the first Device Path Node of RemainingDevicePath is\r
ad86a50a 683 the End of Device Path Node, no child handle is created by this\r
684 driver.\r
685\r
686 @retval EFI_SUCCESS The device was started.\r
687 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
688 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
689 @retval Others The driver failded to start the device.\r
690\r
691**/\r
692EFI_STATUS\r
693EFIAPI\r
694AtaBusDriverBindingStart (\r
695 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
696 IN EFI_HANDLE Controller,\r
697 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
698 )\r
699{\r
700 EFI_STATUS Status;\r
701 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
702 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
703 ATA_BUS_DRIVER_DATA *AtaBusDriverData;\r
704 UINT16 Port;\r
705 UINT16 PortMultiplierPort;\r
706\r
707 AtaBusDriverData = NULL;\r
708\r
709 Status = gBS->OpenProtocol (\r
710 Controller,\r
711 &gEfiDevicePathProtocolGuid,\r
712 (VOID **) &ParentDevicePath,\r
713 This->DriverBindingHandle,\r
714 Controller,\r
715 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
716 );\r
717 if (EFI_ERROR (Status)) {\r
718 return Status;\r
719 }\r
720\r
721 Status = gBS->OpenProtocol (\r
722 Controller,\r
723 &gEfiAtaPassThruProtocolGuid,\r
724 (VOID **) &AtaPassThru,\r
725 This->DriverBindingHandle,\r
726 Controller,\r
727 EFI_OPEN_PROTOCOL_BY_DRIVER\r
728 );\r
729 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
730 goto ErrorExit;\r
731 }\r
732\r
733 //\r
734 // Check EFI_ALREADY_STARTED to reuse the original ATA_BUS_DRIVER_DATA.\r
735 //\r
736 if (Status != EFI_ALREADY_STARTED) {\r
737 AtaBusDriverData = AllocateZeroPool (sizeof (ATA_BUS_DRIVER_DATA));\r
738 if (AtaBusDriverData == NULL) {\r
739 Status = EFI_OUT_OF_RESOURCES;\r
740 goto ErrorExit;\r
741 }\r
742\r
743 AtaBusDriverData->AtaPassThru = AtaPassThru;\r
490b5ea1 744 AtaBusDriverData->Controller = Controller;\r
ad86a50a 745 AtaBusDriverData->ParentDevicePath = ParentDevicePath;\r
746 AtaBusDriverData->DriverBindingHandle = This->DriverBindingHandle;\r
747\r
748 Status = gBS->InstallMultipleProtocolInterfaces (\r
749 &Controller,\r
750 &gEfiCallerIdGuid,\r
751 AtaBusDriverData,\r
752 NULL\r
753 );\r
754 if (EFI_ERROR (Status)) {\r
755 goto ErrorExit;\r
756 }\r
757\r
758 } else {\r
759 Status = gBS->OpenProtocol (\r
760 Controller,\r
761 &gEfiCallerIdGuid,\r
762 (VOID **) &AtaBusDriverData,\r
763 This->DriverBindingHandle,\r
764 Controller,\r
765 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
766 );\r
767 if (EFI_ERROR (Status)) {\r
768 AtaBusDriverData = NULL;\r
769 goto ErrorExit;\r
770 }\r
771 }\r
772\r
773 if (RemainingDevicePath == NULL) {\r
774 Port = 0xFFFF;\r
775 while (TRUE) {\r
776 Status = AtaPassThru->GetNextPort (AtaPassThru, &Port);\r
777 if (EFI_ERROR (Status)) {\r
778 //\r
779 // We cannot find more legal port then we are done.\r
780 //\r
781 break;\r
782 }\r
490b5ea1 783\r
ad86a50a 784 PortMultiplierPort = 0xFFFF;\r
785 while (TRUE) {\r
786 Status = AtaPassThru->GetNextDevice (AtaPassThru, Port, &PortMultiplierPort);\r
787 if (EFI_ERROR (Status)) {\r
788 //\r
789 // We cannot find more legal port multiplier port number for ATA device\r
790 // on the port, then we are done.\r
791 //\r
792 break;\r
793 }\r
794 RegisterAtaDevice (AtaBusDriverData, Port, PortMultiplierPort);\r
795 }\r
796 }\r
797 Status = EFI_SUCCESS;\r
798 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
799 Status = AtaPassThru->GetDevice (AtaPassThru, RemainingDevicePath, &Port, &PortMultiplierPort);\r
800 if (!EFI_ERROR (Status)) {\r
801 Status = RegisterAtaDevice (AtaBusDriverData,Port, PortMultiplierPort);\r
802 }\r
803 }\r
490b5ea1 804\r
ad86a50a 805 return Status;\r
806\r
807ErrorExit:\r
808\r
809 if (AtaBusDriverData != NULL) {\r
810 gBS->UninstallMultipleProtocolInterfaces (\r
811 Controller,\r
812 &gEfiCallerIdGuid,\r
813 AtaBusDriverData,\r
814 NULL\r
815 );\r
816 FreePool (AtaBusDriverData);\r
817 }\r
818\r
819 gBS->CloseProtocol (\r
820 Controller,\r
821 &gEfiAtaPassThruProtocolGuid,\r
822 This->DriverBindingHandle,\r
823 Controller\r
824 );\r
825\r
826 return Status;\r
827\r
828}\r
829\r
830\r
831/**\r
832 Stops a device controller or a bus controller.\r
58727f29 833\r
834 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
835 As a result, much of the error checking on the parameters to Stop() has been moved\r
836 into this common boot service. It is legal to call Stop() from other locations,\r
ad86a50a 837 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
838 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
839 same driver's Start() function.\r
840 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
841 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
842 Start() function, and the Start() function must have called OpenProtocol() on\r
843 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
58727f29 844\r
ad86a50a 845 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
58727f29 846 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
847 support a bus specific I/O protocol for the driver\r
ad86a50a 848 to use to stop the device.\r
849 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
58727f29 850 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
ad86a50a 851 if NumberOfChildren is 0.\r
852\r
853 @retval EFI_SUCCESS The device was stopped.\r
854 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
855\r
856**/\r
857EFI_STATUS\r
858EFIAPI\r
859AtaBusDriverBindingStop (\r
860 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
861 IN EFI_HANDLE Controller,\r
862 IN UINTN NumberOfChildren,\r
863 IN EFI_HANDLE *ChildHandleBuffer\r
864 )\r
865{\r
866 EFI_STATUS Status;\r
867 BOOLEAN AllChildrenStopped;\r
868 UINTN Index;\r
869 ATA_BUS_DRIVER_DATA *AtaBusDriverData;\r
870\r
871 if (NumberOfChildren == 0) {\r
872 Status = gBS->OpenProtocol (\r
873 Controller,\r
874 &gEfiCallerIdGuid,\r
875 (VOID **) &AtaBusDriverData,\r
876 This->DriverBindingHandle,\r
877 Controller,\r
878 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
879 );\r
880 if (!EFI_ERROR (Status)) {\r
881 gBS->UninstallMultipleProtocolInterfaces (\r
882 Controller,\r
883 &gEfiCallerIdGuid,\r
884 AtaBusDriverData,\r
885 NULL\r
886 );\r
887 FreePool (AtaBusDriverData);\r
888 }\r
889\r
890 gBS->CloseProtocol (\r
891 Controller,\r
892 &gEfiAtaPassThruProtocolGuid,\r
893 This->DriverBindingHandle,\r
894 Controller\r
895 );\r
896\r
897 return EFI_SUCCESS;\r
898 }\r
899\r
900 AllChildrenStopped = TRUE;\r
901\r
902 for (Index = 0; Index < NumberOfChildren; Index++) {\r
903\r
904 Status = UnregisterAtaDevice (This, Controller, ChildHandleBuffer[Index]);\r
905 if (EFI_ERROR (Status)) {\r
906 AllChildrenStopped = FALSE;\r
907 }\r
908 }\r
909\r
910 if (!AllChildrenStopped) {\r
911 return EFI_DEVICE_ERROR;\r
912 }\r
913\r
914 return EFI_SUCCESS;\r
915}\r
916\r
917\r
918/**\r
919 Reset the Block Device.\r
920\r
921 @param This Indicates a pointer to the calling context.\r
922 @param ExtendedVerification Driver may perform diagnostics on reset.\r
923\r
924 @retval EFI_SUCCESS The device was reset.\r
925 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
926 not be reset.\r
927\r
928**/\r
929EFI_STATUS\r
930EFIAPI\r
931AtaBlockIoReset (\r
932 IN EFI_BLOCK_IO_PROTOCOL *This,\r
933 IN BOOLEAN ExtendedVerification\r
934 )\r
935{\r
936 EFI_STATUS Status;\r
937 ATA_DEVICE *AtaDevice;\r
938 EFI_TPL OldTpl;\r
939\r
940 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
941\r
942 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
943\r
490b5ea1 944 Status = ResetAtaDevice (AtaDevice);\r
ad86a50a 945\r
c6e797ae 946 if (EFI_ERROR (Status)) {\r
947 Status = EFI_DEVICE_ERROR;\r
948 }\r
949\r
ad86a50a 950 gBS->RestoreTPL (OldTpl);\r
951 return Status;\r
952}\r
953\r
954\r
955/**\r
956 Read/Write BufferSize bytes from Lba from/into Buffer.\r
957\r
490b5ea1 958 @param[in] This Indicates a pointer to the calling context. Either be\r
58727f29 959 block I/O or block I/O2.\r
490b5ea1 960 @param[in] MediaId The media ID that the read/write request is for.\r
961 @param[in] Lba The starting logical block address to be read/written.\r
962 The caller is responsible for reading/writing to only\r
963 legitimate locations.\r
964 @param[in, out] Token A pointer to the token associated with the transaction.\r
965 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
966 @param[out] Buffer A pointer to the destination/source buffer for the data.\r
967 @param[in] IsBlockIo2 Indicate the calling is from BlockIO or BlockIO2. TURE is\r
968 from BlockIO2, FALSE is for BlockIO.\r
969 @param[in] IsWrite Indicates whether it is a write operation.\r
ad86a50a 970\r
971 @retval EFI_SUCCESS The data was read/written correctly to the device.\r
972 @retval EFI_WRITE_PROTECTED The device can not be read/written to.\r
973 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.\r
974 @retval EFI_NO_MEDIA There is no media in the device.\r
975 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
976 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
58727f29 977 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid,\r
ad86a50a 978 or the buffer is not on proper alignment.\r
979\r
980**/\r
981EFI_STATUS\r
982BlockIoReadWrite (\r
490b5ea1 983 IN VOID *This,\r
984 IN UINT32 MediaId,\r
985 IN EFI_LBA Lba,\r
986 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
987 IN UINTN BufferSize,\r
988 OUT VOID *Buffer,\r
989 IN BOOLEAN IsBlockIo2,\r
990 IN BOOLEAN IsWrite\r
ad86a50a 991 )\r
992{\r
993 ATA_DEVICE *AtaDevice;\r
994 EFI_STATUS Status;\r
995 EFI_TPL OldTpl;\r
996 EFI_BLOCK_IO_MEDIA *Media;\r
997 UINTN BlockSize;\r
998 UINTN NumberOfBlocks;\r
999 UINTN IoAlign;\r
1000\r
490b5ea1 1001 if (IsBlockIo2) {\r
1002 Media = ((EFI_BLOCK_IO2_PROTOCOL *) This)->Media;\r
1003 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);\r
1004 } else {\r
1005 Media = ((EFI_BLOCK_IO_PROTOCOL *) This)->Media;\r
1006 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
1007 }\r
1008\r
fcf5e49d
RN
1009 if (MediaId != Media->MediaId) {\r
1010 return EFI_MEDIA_CHANGED;\r
1011 }\r
1012\r
490b5ea1 1013 //\r
1014 // Check parameters.\r
1015 //\r
ad86a50a 1016 if (Buffer == NULL) {\r
1017 return EFI_INVALID_PARAMETER;\r
1018 }\r
1019\r
1020 if (BufferSize == 0) {\r
1021 return EFI_SUCCESS;\r
58727f29 1022 }\r
ad86a50a 1023\r
ad86a50a 1024 BlockSize = Media->BlockSize;\r
1025 if ((BufferSize % BlockSize) != 0) {\r
1026 return EFI_BAD_BUFFER_SIZE;\r
1027 }\r
58727f29 1028\r
ad86a50a 1029 NumberOfBlocks = BufferSize / BlockSize;\r
1030 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
1031 return EFI_INVALID_PARAMETER;\r
1032 }\r
1033\r
1034 IoAlign = Media->IoAlign;\r
1035 if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {\r
1036 return EFI_INVALID_PARAMETER;\r
1037 }\r
1038\r
1039 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
58727f29 1040\r
ad86a50a 1041 //\r
1042 // Invoke low level AtaDevice Access Routine.\r
1043 //\r
490b5ea1 1044 Status = AccessAtaDevice (AtaDevice, Buffer, Lba, NumberOfBlocks, IsWrite, Token);\r
58727f29 1045\r
ad86a50a 1046 gBS->RestoreTPL (OldTpl);\r
1047\r
1048 return Status;\r
1049}\r
1050\r
1051\r
1052/**\r
1053 Read BufferSize bytes from Lba into Buffer.\r
1054\r
1055 @param This Indicates a pointer to the calling context.\r
1056 @param MediaId Id of the media, changes every time the media is replaced.\r
1057 @param Lba The starting Logical Block Address to read from\r
1058 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
1059 @param Buffer A pointer to the destination buffer for the data. The caller is\r
1060 responsible for either having implicit or explicit ownership of the buffer.\r
1061\r
1062 @retval EFI_SUCCESS The data was read correctly from the device.\r
1063 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
1064 @retval EFI_NO_MEDIA There is no media in the device.\r
1065 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
1066 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
58727f29 1067 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
ad86a50a 1068 or the buffer is not on proper alignment.\r
1069\r
1070**/\r
1071EFI_STATUS\r
1072EFIAPI\r
1073AtaBlockIoReadBlocks (\r
1074 IN EFI_BLOCK_IO_PROTOCOL *This,\r
1075 IN UINT32 MediaId,\r
1076 IN EFI_LBA Lba,\r
1077 IN UINTN BufferSize,\r
1078 OUT VOID *Buffer\r
1079 )\r
1080{\r
490b5ea1 1081 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, FALSE);\r
ad86a50a 1082}\r
1083\r
1084\r
1085/**\r
1086 Write BufferSize bytes from Lba into Buffer.\r
1087\r
1088 @param This Indicates a pointer to the calling context.\r
1089 @param MediaId The media ID that the write request is for.\r
1090 @param Lba The starting logical block address to be written. The caller is\r
1091 responsible for writing to only legitimate locations.\r
1092 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
1093 @param Buffer A pointer to the source buffer for the data.\r
1094\r
1095 @retval EFI_SUCCESS The data was written correctly to the device.\r
1096 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
1097 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
1098 @retval EFI_NO_MEDIA There is no media in the device.\r
1099 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
1100 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
58727f29 1101 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
ad86a50a 1102 or the buffer is not on proper alignment.\r
1103\r
1104**/\r
1105EFI_STATUS\r
1106EFIAPI\r
1107AtaBlockIoWriteBlocks (\r
1108 IN EFI_BLOCK_IO_PROTOCOL *This,\r
1109 IN UINT32 MediaId,\r
1110 IN EFI_LBA Lba,\r
1111 IN UINTN BufferSize,\r
1112 IN VOID *Buffer\r
1113 )\r
1114{\r
490b5ea1 1115 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, TRUE);\r
ad86a50a 1116}\r
1117\r
1118\r
1119/**\r
1120 Flush the Block Device.\r
1121\r
1122 @param This Indicates a pointer to the calling context.\r
1123\r
1124 @retval EFI_SUCCESS All outstanding data was written to the device\r
1125 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
1126 @retval EFI_NO_MEDIA There is no media in the device.\r
1127\r
1128**/\r
1129EFI_STATUS\r
1130EFIAPI\r
1131AtaBlockIoFlushBlocks (\r
1132 IN EFI_BLOCK_IO_PROTOCOL *This\r
1133 )\r
1134{\r
1135 //\r
1136 // return directly\r
1137 //\r
1138 return EFI_SUCCESS;\r
1139}\r
1140\r
490b5ea1 1141/**\r
1142 Reset the Block Device.\r
1143\r
1144 @param[in] This Indicates a pointer to the calling context.\r
1145 @param[in] ExtendedVerification Driver may perform diagnostics on reset.\r
1146\r
1147 @retval EFI_SUCCESS The device was reset.\r
1148 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
1149 not be reset.\r
1150\r
1151**/\r
1152EFI_STATUS\r
1153EFIAPI\r
1154AtaBlockIoResetEx (\r
1155 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1156 IN BOOLEAN ExtendedVerification\r
1157 )\r
1158{\r
1159 EFI_STATUS Status;\r
1160 ATA_DEVICE *AtaDevice;\r
1161 EFI_TPL OldTpl;\r
1162\r
1163 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1164\r
1165 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);\r
1166\r
1167 Status = ResetAtaDevice (AtaDevice);\r
1168\r
1169 if (EFI_ERROR (Status)) {\r
1170 Status = EFI_DEVICE_ERROR;\r
1171 }\r
1172\r
1173 gBS->RestoreTPL (OldTpl);\r
1174 return Status;\r
1175}\r
1176\r
1177/**\r
1178 Read BufferSize bytes from Lba into Buffer.\r
1179\r
1180 @param[in] This Indicates a pointer to the calling context.\r
1181 @param[in] MediaId Id of the media, changes every time the media is replaced.\r
1182 @param[in] Lba The starting Logical Block Address to read from.\r
1183 @param[in, out] Token A pointer to the token associated with the transaction.\r
1184 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
1185 @param[out] Buffer A pointer to the destination buffer for the data. The caller is\r
1186 responsible for either having implicit or explicit ownership of the buffer.\r
1187\r
1188 @retval EFI_SUCCESS The read request was queued if Event is not NULL.\r
1189 The data was read correctly from the device if\r
1190 the Event is NULL.\r
1191 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
1192 the read.\r
1193 @retval EFI_NO_MEDIA There is no media in the device.\r
1194 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1195 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
1196 intrinsic block size of the device.\r
58727f29 1197 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
490b5ea1 1198 or the buffer is not on proper alignment.\r
1199 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
1200 of resources.\r
1201\r
1202**/\r
1203EFI_STATUS\r
1204EFIAPI\r
1205AtaBlockIoReadBlocksEx (\r
1206 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1207 IN UINT32 MediaId,\r
1208 IN EFI_LBA Lba,\r
1209 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
1210 IN UINTN BufferSize,\r
1211 OUT VOID *Buffer\r
1212 )\r
1213{\r
1214 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, FALSE);\r
1215}\r
1216\r
1217\r
1218/**\r
1219 Write BufferSize bytes from Lba into Buffer.\r
1220\r
1221 @param[in] This Indicates a pointer to the calling context.\r
1222 @param[in] MediaId The media ID that the write request is for.\r
1223 @param[in] Lba The starting logical block address to be written. The\r
1224 caller is responsible for writing to only legitimate\r
1225 locations.\r
1226 @param[in, out] Token A pointer to the token associated with the transaction.\r
1227 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
1228 @param[in] Buffer A pointer to the source buffer for the data.\r
ad86a50a 1229\r
490b5ea1 1230 @retval EFI_SUCCESS The data was written correctly to the device.\r
1231 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
1232 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
1233 @retval EFI_NO_MEDIA There is no media in the device.\r
1234 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
1235 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
58727f29 1236 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
490b5ea1 1237 or the buffer is not on proper alignment.\r
1238\r
1239**/\r
1240EFI_STATUS\r
1241EFIAPI\r
1242AtaBlockIoWriteBlocksEx (\r
1243 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1244 IN UINT32 MediaId,\r
1245 IN EFI_LBA Lba,\r
1246 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
1247 IN UINTN BufferSize,\r
1248 IN VOID *Buffer\r
1249 )\r
1250{\r
1251 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, TRUE);\r
1252}\r
1253\r
1254\r
1255/**\r
1256 Flush the Block Device.\r
1257\r
1258 @param[in] This Indicates a pointer to the calling context.\r
1259 @param[in, out] Token A pointer to the token associated with the transaction.\r
1260\r
1261 @retval EFI_SUCCESS All outstanding data was written to the device\r
1262 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
1263 @retval EFI_NO_MEDIA There is no media in the device.\r
1264\r
1265**/\r
1266EFI_STATUS\r
1267EFIAPI\r
1268AtaBlockIoFlushBlocksEx (\r
1269 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1270 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
1271 )\r
1272{\r
1273 //\r
3c063fed 1274 // Signal event and return directly.\r
490b5ea1 1275 //\r
1276 if (Token != NULL && Token->Event != NULL) {\r
1277 Token->TransactionStatus = EFI_SUCCESS;\r
1278 gBS->SignalEvent (Token->Event);\r
1279 }\r
1280 return EFI_SUCCESS;\r
1281}\r
ad86a50a 1282/**\r
1283 Provides inquiry information for the controller type.\r
58727f29 1284\r
ad86a50a 1285 This function is used by the IDE bus driver to get inquiry data. Data format\r
1286 of Identify data is defined by the Interface GUID.\r
1287\r
05a44e91 1288 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1289 @param[in, out] InquiryData Pointer to a buffer for the inquiry data.\r
1290 @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.\r
ad86a50a 1291\r
1292 @retval EFI_SUCCESS The command was accepted without any errors.\r
58727f29 1293 @retval EFI_NOT_FOUND Device does not support this data class\r
1294 @retval EFI_DEVICE_ERROR Error reading InquiryData from device\r
1295 @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough\r
ad86a50a 1296\r
1297**/\r
1298EFI_STATUS\r
1299EFIAPI\r
1300AtaDiskInfoInquiry (\r
1301 IN EFI_DISK_INFO_PROTOCOL *This,\r
1302 IN OUT VOID *InquiryData,\r
1303 IN OUT UINT32 *InquiryDataSize\r
1304 )\r
1305{\r
1306 return EFI_NOT_FOUND;\r
1307}\r
1308\r
1309\r
1310/**\r
1311 Provides identify information for the controller type.\r
1312\r
1313 This function is used by the IDE bus driver to get identify data. Data format\r
1314 of Identify data is defined by the Interface GUID.\r
1315\r
58727f29 1316 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL\r
ad86a50a 1317 instance.\r
05a44e91 1318 @param[in, out] IdentifyData Pointer to a buffer for the identify data.\r
1319 @param[in, out] IdentifyDataSize Pointer to the value for the identify data\r
ad86a50a 1320 size.\r
1321\r
1322 @retval EFI_SUCCESS The command was accepted without any errors.\r
58727f29 1323 @retval EFI_NOT_FOUND Device does not support this data class\r
1324 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device\r
1325 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough\r
ad86a50a 1326\r
1327**/\r
1328EFI_STATUS\r
1329EFIAPI\r
1330AtaDiskInfoIdentify (\r
1331 IN EFI_DISK_INFO_PROTOCOL *This,\r
1332 IN OUT VOID *IdentifyData,\r
1333 IN OUT UINT32 *IdentifyDataSize\r
1334 )\r
1335{\r
1336 EFI_STATUS Status;\r
1337 ATA_DEVICE *AtaDevice;\r
1338\r
1339 AtaDevice = ATA_DEVICE_FROM_DISK_INFO (This);\r
1340\r
1341 Status = EFI_BUFFER_TOO_SMALL;\r
3c063fed 1342 if (*IdentifyDataSize >= sizeof (ATA_IDENTIFY_DATA)) {\r
ad86a50a 1343 Status = EFI_SUCCESS;\r
3c063fed 1344 CopyMem (IdentifyData, AtaDevice->IdentifyData, sizeof (ATA_IDENTIFY_DATA));\r
ad86a50a 1345 }\r
3c063fed 1346 *IdentifyDataSize = sizeof (ATA_IDENTIFY_DATA);\r
ad86a50a 1347\r
1348 return Status;\r
1349}\r
1350\r
1351\r
1352/**\r
1353 Provides sense data information for the controller type.\r
58727f29 1354\r
1355 This function is used by the IDE bus driver to get sense data.\r
ad86a50a 1356 Data format of Sense data is defined by the Interface GUID.\r
1357\r
05a44e91 1358 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1359 @param[in, out] SenseData Pointer to the SenseData.\r
1360 @param[in, out] SenseDataSize Size of SenseData in bytes.\r
1361 @param[out] SenseDataNumber Pointer to the value for the sense data size.\r
ad86a50a 1362\r
1363 @retval EFI_SUCCESS The command was accepted without any errors.\r
1364 @retval EFI_NOT_FOUND Device does not support this data class.\r
1365 @retval EFI_DEVICE_ERROR Error reading SenseData from device.\r
1366 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.\r
1367\r
1368**/\r
1369EFI_STATUS\r
1370EFIAPI\r
1371AtaDiskInfoSenseData (\r
1372 IN EFI_DISK_INFO_PROTOCOL *This,\r
1373 IN OUT VOID *SenseData,\r
1374 IN OUT UINT32 *SenseDataSize,\r
1375 OUT UINT8 *SenseDataNumber\r
1376 )\r
1377{\r
1378 return EFI_NOT_FOUND;\r
1379}\r
1380\r
1381\r
1382/**\r
1383 This function is used by the IDE bus driver to get controller information.\r
1384\r
58727f29 1385 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
ad86a50a 1386 @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.\r
1387 @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.\r
1388\r
1389 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.\r
1390 @retval EFI_UNSUPPORTED This is not an IDE device.\r
1391\r
1392**/\r
1393EFI_STATUS\r
1394EFIAPI\r
1395AtaDiskInfoWhichIde (\r
1396 IN EFI_DISK_INFO_PROTOCOL *This,\r
1397 OUT UINT32 *IdeChannel,\r
1398 OUT UINT32 *IdeDevice\r
1399 )\r
1400{\r
1401 ATA_DEVICE *AtaDevice;\r
1402\r
1403 AtaDevice = ATA_DEVICE_FROM_DISK_INFO (This);\r
1404 *IdeChannel = AtaDevice->Port;\r
1405 *IdeDevice = AtaDevice->PortMultiplierPort;\r
1406\r
1407 return EFI_SUCCESS;\r
1408}\r
1409\r
c24097a5 1410/**\r
1411 Send a security protocol command to a device that receives data and/or the result\r
1412 of one or more commands sent by SendData.\r
1413\r
1414 The ReceiveData function sends a security protocol command to the given MediaId.\r
1415 The security protocol command sent is defined by SecurityProtocolId and contains\r
1416 the security protocol specific data SecurityProtocolSpecificData. The function\r
1417 returns the data from the security protocol command in PayloadBuffer.\r
1418\r
1419 For devices supporting the SCSI command set, the security protocol command is sent\r
1420 using the SECURITY PROTOCOL IN command defined in SPC-4.\r
1421\r
1422 For devices supporting the ATA command set, the security protocol command is sent\r
1423 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize\r
1424 is non-zero.\r
1425\r
1426 If the PayloadBufferSize is zero, the security protocol command is sent using the\r
1427 Trusted Non-Data command defined in ATA8-ACS.\r
1428\r
1429 If PayloadBufferSize is too small to store the available data from the security\r
1430 protocol command, the function shall copy PayloadBufferSize bytes into the\r
1431 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.\r
1432\r
1433 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,\r
1434 the function shall return EFI_INVALID_PARAMETER.\r
1435\r
1436 If the given MediaId does not support security protocol commands, the function shall\r
1437 return EFI_UNSUPPORTED. If there is no media in the device, the function returns\r
1438 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,\r
1439 the function returns EFI_MEDIA_CHANGED.\r
1440\r
1441 If the security protocol fails to complete within the Timeout period, the function\r
1442 shall return EFI_TIMEOUT.\r
1443\r
1444 If the security protocol command completes without an error, the function shall\r
1445 return EFI_SUCCESS. If the security protocol command completes with an error, the\r
1446 function shall return EFI_DEVICE_ERROR.\r
1447\r
1448 @param This Indicates a pointer to the calling context.\r
1449 @param MediaId ID of the medium to receive data from.\r
1450 @param Timeout The timeout, in 100ns units, to use for the execution\r
1451 of the security protocol command. A Timeout value of 0\r
1452 means that this function will wait indefinitely for the\r
1453 security protocol command to execute. If Timeout is greater\r
1454 than zero, then this function will return EFI_TIMEOUT\r
1455 if the time required to execute the receive data command\r
1456 is greater than Timeout.\r
1457 @param SecurityProtocolId The value of the "Security Protocol" parameter of\r
1458 the security protocol command to be sent.\r
1459 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
1460 of the security protocol command to be sent.\r
1461 @param PayloadBufferSize Size in bytes of the payload data buffer.\r
1462 @param PayloadBuffer A pointer to a destination buffer to store the security\r
1463 protocol command specific payload data for the security\r
1464 protocol command. The caller is responsible for having\r
1465 either implicit or explicit ownership of the buffer.\r
1466 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the\r
1467 data written to the payload data buffer.\r
1468\r
1469 @retval EFI_SUCCESS The security protocol command completed successfully.\r
1470 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available\r
1471 data from the device. The PayloadBuffer contains the truncated data.\r
1472 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.\r
1473 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.\r
1474 @retval EFI_NO_MEDIA There is no media in the device.\r
1475 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1476 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and\r
1477 PayloadBufferSize is non-zero.\r
1478 @retval EFI_TIMEOUT A timeout occurred while waiting for the security\r
1479 protocol command to execute.\r
1480\r
1481**/\r
1482EFI_STATUS\r
1483EFIAPI\r
1484AtaStorageSecurityReceiveData (\r
1485 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,\r
1486 IN UINT32 MediaId,\r
1487 IN UINT64 Timeout,\r
1488 IN UINT8 SecurityProtocolId,\r
1489 IN UINT16 SecurityProtocolSpecificData,\r
1490 IN UINTN PayloadBufferSize,\r
1491 OUT VOID *PayloadBuffer,\r
1492 OUT UINTN *PayloadTransferSize\r
1493 )\r
1494{\r
1495 EFI_STATUS Status;\r
1496 ATA_DEVICE *Private;\r
3c063fed 1497 EFI_TPL OldTpl;\r
c24097a5 1498\r
1499 DEBUG ((EFI_D_INFO, "EFI Storage Security Protocol - Read"));\r
1500 if ((PayloadBuffer == NULL || PayloadTransferSize == NULL) && PayloadBufferSize != 0) {\r
1501 return EFI_INVALID_PARAMETER;\r
1502 }\r
1503\r
1504 Status = EFI_SUCCESS;\r
1505 Private = ATA_DEVICE_FROM_STORAGE_SECURITY (This);\r
1506\r
1507 if (MediaId != Private->BlockIo.Media->MediaId) {\r
1508 return EFI_MEDIA_CHANGED;\r
1509 }\r
1510\r
1511 if (!Private->BlockIo.Media->MediaPresent) {\r
1512 return EFI_NO_MEDIA;\r
1513 }\r
1514\r
3c063fed 1515 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1516\r
c24097a5 1517 Status = TrustTransferAtaDevice (\r
1518 Private,\r
1519 PayloadBuffer,\r
1520 SecurityProtocolId,\r
1521 SecurityProtocolSpecificData,\r
1522 PayloadBufferSize,\r
1523 FALSE,\r
1524 Timeout,\r
1525 PayloadTransferSize\r
1526 );\r
1527\r
3c063fed 1528 gBS->RestoreTPL (OldTpl);\r
c24097a5 1529 return Status;\r
1530}\r
1531\r
1532/**\r
1533 Send a security protocol command to a device.\r
1534\r
1535 The SendData function sends a security protocol command containing the payload\r
1536 PayloadBuffer to the given MediaId. The security protocol command sent is\r
1537 defined by SecurityProtocolId and contains the security protocol specific data\r
1538 SecurityProtocolSpecificData. If the underlying protocol command requires a\r
1539 specific padding for the command payload, the SendData function shall add padding\r
1540 bytes to the command payload to satisfy the padding requirements.\r
1541\r
1542 For devices supporting the SCSI command set, the security protocol command is sent\r
1543 using the SECURITY PROTOCOL OUT command defined in SPC-4.\r
1544\r
1545 For devices supporting the ATA command set, the security protocol command is sent\r
1546 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize\r
1547 is non-zero. If the PayloadBufferSize is zero, the security protocol command is\r
1548 sent using the Trusted Non-Data command defined in ATA8-ACS.\r
1549\r
1550 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall\r
1551 return EFI_INVALID_PARAMETER.\r
1552\r
1553 If the given MediaId does not support security protocol commands, the function\r
1554 shall return EFI_UNSUPPORTED. If there is no media in the device, the function\r
1555 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the\r
1556 device, the function returns EFI_MEDIA_CHANGED.\r
1557\r
1558 If the security protocol fails to complete within the Timeout period, the function\r
1559 shall return EFI_TIMEOUT.\r
1560\r
1561 If the security protocol command completes without an error, the function shall return\r
1562 EFI_SUCCESS. If the security protocol command completes with an error, the function\r
1563 shall return EFI_DEVICE_ERROR.\r
1564\r
1565 @param This Indicates a pointer to the calling context.\r
1566 @param MediaId ID of the medium to receive data from.\r
1567 @param Timeout The timeout, in 100ns units, to use for the execution\r
1568 of the security protocol command. A Timeout value of 0\r
1569 means that this function will wait indefinitely for the\r
1570 security protocol command to execute. If Timeout is greater\r
1571 than zero, then this function will return EFI_TIMEOUT\r
1572 if the time required to execute the receive data command\r
1573 is greater than Timeout.\r
1574 @param SecurityProtocolId The value of the "Security Protocol" parameter of\r
1575 the security protocol command to be sent.\r
1576 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
1577 of the security protocol command to be sent.\r
1578 @param PayloadBufferSize Size in bytes of the payload data buffer.\r
1579 @param PayloadBuffer A pointer to a destination buffer to store the security\r
1580 protocol command specific payload data for the security\r
1581 protocol command.\r
1582\r
1583 @retval EFI_SUCCESS The security protocol command completed successfully.\r
1584 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.\r
1585 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.\r
1586 @retval EFI_NO_MEDIA There is no media in the device.\r
1587 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1588 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.\r
1589 @retval EFI_TIMEOUT A timeout occurred while waiting for the security\r
1590 protocol command to execute.\r
1591\r
1592**/\r
1593EFI_STATUS\r
1594EFIAPI\r
1595AtaStorageSecuritySendData (\r
1596 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,\r
1597 IN UINT32 MediaId,\r
1598 IN UINT64 Timeout,\r
1599 IN UINT8 SecurityProtocolId,\r
1600 IN UINT16 SecurityProtocolSpecificData,\r
1601 IN UINTN PayloadBufferSize,\r
1602 IN VOID *PayloadBuffer\r
1603 )\r
1604{\r
1605 EFI_STATUS Status;\r
1606 ATA_DEVICE *Private;\r
3c063fed 1607 EFI_TPL OldTpl;\r
c24097a5 1608\r
1609 DEBUG ((EFI_D_INFO, "EFI Storage Security Protocol - Send"));\r
1610 if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {\r
1611 return EFI_INVALID_PARAMETER;\r
1612 }\r
1613\r
1614 Status = EFI_SUCCESS;\r
1615 Private = ATA_DEVICE_FROM_STORAGE_SECURITY (This);\r
1616\r
1617 if (MediaId != Private->BlockIo.Media->MediaId) {\r
1618 return EFI_MEDIA_CHANGED;\r
1619 }\r
1620\r
3c063fed 1621 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
c24097a5 1622 Status = TrustTransferAtaDevice (\r
1623 Private,\r
1624 PayloadBuffer,\r
1625 SecurityProtocolId,\r
1626 SecurityProtocolSpecificData,\r
1627 PayloadBufferSize,\r
1628 TRUE,\r
1629 Timeout,\r
1630 NULL\r
1631 );\r
1632\r
3c063fed 1633 gBS->RestoreTPL (OldTpl);\r
c24097a5 1634 return Status;\r
1635}\r
ad86a50a 1636\r
1637/**\r
1638 The user Entry Point for module AtaBus. The user code starts with this function.\r
1639\r
1640 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1641 @param[in] SystemTable A pointer to the EFI System Table.\r
1642\r
1643 @retval EFI_SUCCESS The entry point is executed successfully.\r
1644 @retval other Some error occurs when executing this entry point.\r
1645\r
1646**/\r
1647EFI_STATUS\r
1648EFIAPI\r
1649InitializeAtaBus(\r
1650 IN EFI_HANDLE ImageHandle,\r
1651 IN EFI_SYSTEM_TABLE *SystemTable\r
1652 )\r
1653{\r
1654 EFI_STATUS Status;\r
90398d55 1655 UINTN DataSize;\r
ad86a50a 1656\r
1657 //\r
1658 // Install driver model protocol(s).\r
1659 //\r
1660 Status = EfiLibInstallDriverBindingComponentName2 (\r
1661 ImageHandle,\r
1662 SystemTable,\r
1663 &gAtaBusDriverBinding,\r
1664 ImageHandle,\r
1665 &gAtaBusComponentName,\r
1666 &gAtaBusComponentName2\r
1667 );\r
1668 ASSERT_EFI_ERROR (Status);\r
1669\r
90398d55 1670 //\r
1671 // Get the MorControl bit.\r
1672 //\r
1673 DataSize = sizeof (mMorControl);\r
1674 Status = gRT->GetVariable (\r
1675 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
1676 &gEfiMemoryOverwriteControlDataGuid,\r
1677 NULL,\r
1678 &DataSize,\r
1679 &mMorControl\r
1680 );\r
1681\r
1682 if (EFI_ERROR (Status)) {\r
1683 DEBUG ((EFI_D_INFO, "AtaBus:gEfiMemoryOverwriteControlDataGuid doesn't exist!!***\n"));\r
90398d55 1684 mMorControl = 0;\r
1685 Status = EFI_SUCCESS;\r
1686 } else {\r
1687 DEBUG ((EFI_D_INFO, "AtaBus:Get the gEfiMemoryOverwriteControlDataGuid = %x!!***\n", mMorControl));\r
90398d55 1688 }\r
1689\r
ad86a50a 1690 return Status;\r
1691}\r
90398d55 1692\r
1693/**\r
1694 Send TPer Reset command to reset eDrive to lock all protected bands.\r
1695 Typically, there are 2 mechanism for resetting eDrive. They are:\r
1696 1. TPer Reset through IEEE 1667 protocol.\r
1697 2. TPer Reset through native TCG protocol.\r
1698 This routine will detect what protocol the attached eDrive comform to, TCG or\r
1699 IEEE 1667 protocol. Then send out TPer Reset command separately.\r
1700\r
1701 @param[in] AtaDevice ATA_DEVICE pointer.\r
1702\r
1703**/\r
1704VOID\r
1705InitiateTPerReset (\r
1706 IN ATA_DEVICE *AtaDevice\r
1707 )\r
1708{\r
1709\r
1710 EFI_STATUS Status;\r
1711 UINT8 *Buffer;\r
1712 UINTN XferSize;\r
1713 UINTN Len;\r
1714 UINTN Index;\r
1715 BOOLEAN TcgFlag;\r
1716 BOOLEAN IeeeFlag;\r
1717 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
1718 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp;\r
1719 SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA *Data;\r
1720\r
1721 Buffer = NULL;\r
1722 TcgFlag = FALSE;\r
1723 IeeeFlag = FALSE;\r
1724 Ssp = &AtaDevice->StorageSecurity;\r
1725 BlockIo = &AtaDevice->BlockIo;\r
1726\r
1727 //\r
1728 // ATA8-ACS 7.57.6.1 indicates the Transfer Length field requirements a multiple of 512.\r
1729 // If the length of the TRUSTED RECEIVE parameter data is greater than the Transfer Length,\r
1730 // then the device shall return the TRUSTED RECEIVE parameter data truncated to the requested Transfer Length.\r
1731 //\r
1732 Len = ROUNDUP512(sizeof(SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA));\r
1733 Buffer = AllocateZeroPool(Len);\r
1734\r
1735 if (Buffer == NULL) {\r
1736 return;\r
1737 }\r
1738\r
1739 //\r
1740 // When the Security Protocol field is set to 00h, and SP Specific is set to 0000h in a TRUSTED RECEIVE\r
1741 // command, the device basic information data shall be returned.\r
1742 //\r
1743 Status = Ssp->ReceiveData (\r
1744 Ssp,\r
1745 BlockIo->Media->MediaId,\r
1746 100000000, // Timeout 10-sec\r
1747 0, // SecurityProtocol\r
1748 0, // SecurityProtocolSpecifcData\r
1749 Len, // PayloadBufferSize,\r
1750 Buffer, // PayloadBuffer\r
1751 &XferSize\r
1752 );\r
1753 if (EFI_ERROR (Status)) {\r
1754 goto Exit;\r
1755 }\r
1756\r
1757 //\r
1758 // In returned data, the ListLength field indicates the total length, in bytes,\r
1759 // of the supported security protocol list.\r
1760 //\r
1761 Data = (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA*)Buffer;\r
1762 Len = ROUNDUP512(sizeof (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA) +\r
1763 (Data->SupportedSecurityListLength[0] << 8) +\r
1764 (Data->SupportedSecurityListLength[1])\r
1765 );\r
1766\r
1767 //\r
1768 // Free original buffer and allocate new buffer.\r
1769 //\r
1770 FreePool(Buffer);\r
1771 Buffer = AllocateZeroPool(Len);\r
1772 if (Buffer == NULL) {\r
1773 return;\r
1774 }\r
1775\r
1776 //\r
1777 // Read full supported security protocol list from device.\r
1778 //\r
1779 Status = Ssp->ReceiveData (\r
1780 Ssp,\r
1781 BlockIo->Media->MediaId,\r
1782 100000000, // Timeout 10-sec\r
1783 0, // SecurityProtocol\r
1784 0, // SecurityProtocolSpecifcData\r
1785 Len, // PayloadBufferSize,\r
1786 Buffer, // PayloadBuffer\r
1787 &XferSize\r
1788 );\r
1789\r
1790 if (EFI_ERROR (Status)) {\r
1791 goto Exit;\r
1792 }\r
1793\r
1794 Data = (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA*)Buffer;\r
1795 Len = (Data->SupportedSecurityListLength[0] << 8) + Data->SupportedSecurityListLength[1];\r
1796\r
1797 //\r
1798 // Iterate full supported security protocol list to check if TCG or IEEE 1667 protocol\r
1799 // is supported.\r
1800 //\r
1801 for (Index = 0; Index < Len; Index++) {\r
1802 if (Data->SupportedSecurityProtocol[Index] == SECURITY_PROTOCOL_TCG) {\r
1803 //\r
1804 // Found a TCG device.\r
1805 //\r
1806 TcgFlag = TRUE;\r
1807 DEBUG ((EFI_D_INFO, "This device is a TCG protocol device\n"));\r
1808 break;\r
1809 }\r
1810\r
1811 if (Data->SupportedSecurityProtocol[Index] == SECURITY_PROTOCOL_IEEE1667) {\r
1812 //\r
1813 // Found a IEEE 1667 device.\r
1814 //\r
1815 IeeeFlag = TRUE;\r
1816 DEBUG ((EFI_D_INFO, "This device is a IEEE 1667 protocol device\n"));\r
1817 break;\r
1818 }\r
1819 }\r
1820\r
1821 if (!TcgFlag && !IeeeFlag) {\r
1822 DEBUG ((EFI_D_INFO, "Neither a TCG nor IEEE 1667 protocol device is found\n"));\r
1823 goto Exit;\r
1824 }\r
1825\r
1826 if (TcgFlag) {\r
1827 //\r
1828 // As long as TCG protocol is supported, send out a TPer Reset\r
1829 // TCG command to the device via the TrustedSend command with a non-zero Transfer Length.\r
1830 //\r
1831 Status = Ssp->SendData (\r
1832 Ssp,\r
1833 BlockIo->Media->MediaId,\r
1834 100000000, // Timeout 10-sec\r
1835 SECURITY_PROTOCOL_TCG, // SecurityProtocol\r
1836 0x0400, // SecurityProtocolSpecifcData\r
1837 512, // PayloadBufferSize,\r
1838 Buffer // PayloadBuffer\r
1839 );\r
1840\r
1841 if (!EFI_ERROR (Status)) {\r
1842 DEBUG ((EFI_D_INFO, "Send TPer Reset Command Successfully !\n"));\r
1843 } else {\r
1844 DEBUG ((EFI_D_INFO, "Send TPer Reset Command Fail !\n"));\r
1845 }\r
1846 }\r
1847\r
1848 if (IeeeFlag) {\r
1849 //\r
1850 // TBD : Perform a TPer Reset via IEEE 1667 Protocol\r
1851 //\r
1852 DEBUG ((EFI_D_INFO, "IEEE 1667 Protocol didn't support yet!\n"));\r
1853 }\r
1854\r
1855Exit:\r
1856\r
1857 if (Buffer != NULL) {\r
1858 FreePool(Buffer);\r
1859 }\r
1860}\r