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