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