2 Opal password smm driver which is used to support Opal security feature at s3 path.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "OpalPasswordSmm.h"
17 #define SMM_SIZE_ALLOC_BYTES (512)
18 #define RESPONSE_SIZE (200)
20 #define PCI_CLASS_MASS_STORAGE_AHCI (0x06)
22 #define OPAL_PCIE_ROOTPORT_SAVESIZE (0x40)
23 #define STORE_INVALID_ROOTPORT_INDEX ((UINT8) -1)
24 #define OPAL_DEVICE_TYPE_SATA 0x1
25 #define OPAL_DEVICE_TYPE_NVME 0x2
26 #define OPAL_DEVICE_TYPE_UNKNOWN 0xFF
29 // To unlock the Intel SATA controller at S3 Resume, restored the following registers.
31 const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate
[] = {
32 {0x9, S3BootScriptWidthUint8
},
33 {0x10, S3BootScriptWidthUint32
},
34 {0x14, S3BootScriptWidthUint32
},
35 {0x18, S3BootScriptWidthUint32
},
36 {0x1C, S3BootScriptWidthUint32
},
37 {0x20, S3BootScriptWidthUint32
},
38 {0x24, S3BootScriptWidthUint32
},
39 {0x3c, S3BootScriptWidthUint8
},
40 {0x3d, S3BootScriptWidthUint8
},
41 {0x40, S3BootScriptWidthUint16
},
42 {0x42, S3BootScriptWidthUint16
},
43 {0x92, S3BootScriptWidthUint16
},
44 {0x94, S3BootScriptWidthUint32
},
45 {0x9C, S3BootScriptWidthUint32
},
46 {0x4, S3BootScriptWidthUint16
},
51 LIST_ENTRY
*mOpalDeviceList
;
52 LIST_ENTRY mSmmDeviceList
= INITIALIZE_LIST_HEAD_VARIABLE (mSmmDeviceList
);
54 BOOLEAN mSendBlockSID
= FALSE
;
58 EFI_AHCI_REGISTERS mAhciRegisters
;
59 VOID
*mBuffer
= NULL
; // DMA can not read/write Data to smram, so we pre-allocates Buffer from AcpiNVS.
62 NVME_CONTEXT mNvmeContext
;
65 Add new bridge node or nvme device info to the device list.
67 @param[in] BusNum The bus number.
68 @param[in] DevNum The device number.
69 @param[in] FuncNum The function number.
70 @param[in] Dev The device which need to add device node info.
82 PCI_DEVICE
*DeviceNode
;
84 DevList
= AllocateZeroPool (sizeof (PCI_DEVICE
) + Dev
->Length
);
85 ASSERT (DevList
!= NULL
);
87 if (Dev
->Length
!= 0) {
88 CopyMem (DevList
, Dev
->PciBridgeNode
, Dev
->Length
);
89 FreePool (Dev
->PciBridgeNode
);
92 DeviceNode
= (PCI_DEVICE
*) (DevList
+ Dev
->Length
);
94 DeviceNode
->BusNum
= BusNum
;
95 DeviceNode
->DevNum
= DevNum
;
96 DeviceNode
->FuncNum
= FuncNum
;
98 Dev
->Length
+= sizeof (PCI_DEVICE
);
99 Dev
->PciBridgeNode
= (PCI_DEVICE
*)DevList
;
103 Extract device info from the input device path.
105 @param[in] DevicePath Device path info for the device.
106 @param[in,out] Dev The device which new inputed.
110 ExtractDeviceInfoFromDevicePath (
111 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
112 IN OUT OPAL_SMM_DEVICE
*Dev
115 EFI_DEVICE_PATH_PROTOCOL
*TmpDevPath
;
116 EFI_DEVICE_PATH_PROTOCOL
*TmpDevPath2
;
117 PCI_DEVICE_PATH
*PciDevPath
;
118 SATA_DEVICE_PATH
*SataDevPath
;
119 NVME_NAMESPACE_DEVICE_PATH
*NvmeDevPath
;
122 TmpDevPath
= DevicePath
;
123 Dev
->DeviceType
= OPAL_DEVICE_TYPE_UNKNOWN
;
125 while (!IsDevicePathEnd(TmpDevPath
)) {
126 if (TmpDevPath
->Type
== MESSAGING_DEVICE_PATH
&& TmpDevPath
->SubType
== MSG_SATA_DP
) {
130 SataDevPath
= ( SATA_DEVICE_PATH
* )TmpDevPath
;
131 Dev
->SataPort
= SataDevPath
->HBAPortNumber
;
132 Dev
->SataPortMultiplierPort
= SataDevPath
->PortMultiplierPortNumber
;
133 Dev
->DeviceType
= OPAL_DEVICE_TYPE_SATA
;
135 } else if (TmpDevPath
->Type
== MESSAGING_DEVICE_PATH
&& TmpDevPath
->SubType
== MSG_NVME_NAMESPACE_DP
) {
139 NvmeDevPath
= ( NVME_NAMESPACE_DEVICE_PATH
* )TmpDevPath
;
140 Dev
->NvmeNamespaceId
= NvmeDevPath
->NamespaceId
;
141 Dev
->DeviceType
= OPAL_DEVICE_TYPE_NVME
;
144 TmpDevPath
= NextDevicePathNode (TmpDevPath
);
148 // Get bridge node info for the nvme device.
151 TmpDevPath
= DevicePath
;
152 TmpDevPath2
= NextDevicePathNode (DevicePath
);
153 while (!IsDevicePathEnd(TmpDevPath2
)) {
154 if (TmpDevPath
->Type
== HARDWARE_DEVICE_PATH
&& TmpDevPath
->SubType
== HW_PCI_DP
) {
155 PciDevPath
= (PCI_DEVICE_PATH
*) TmpDevPath
;
156 if ((TmpDevPath2
->Type
== MESSAGING_DEVICE_PATH
&& TmpDevPath2
->SubType
== MSG_NVME_NAMESPACE_DP
)||
157 (TmpDevPath2
->Type
== MESSAGING_DEVICE_PATH
&& TmpDevPath2
->SubType
== MSG_SATA_DP
)) {
158 Dev
->BusNum
= (UINT32
)BusNum
;
159 Dev
->DevNum
= PciDevPath
->Device
;
160 Dev
->FuncNum
= PciDevPath
->Function
;
162 AddPciDeviceNode((UINT32
)BusNum
, PciDevPath
->Device
, PciDevPath
->Function
, Dev
);
163 if (TmpDevPath2
->Type
== HARDWARE_DEVICE_PATH
&& TmpDevPath2
->SubType
== HW_PCI_DP
) {
164 BusNum
= PciRead8 (PCI_LIB_ADDRESS (BusNum
, PciDevPath
->Device
, PciDevPath
->Function
, NVME_PCIE_SEC_BNUM
));
169 TmpDevPath
= NextDevicePathNode (TmpDevPath
);
170 TmpDevPath2
= NextDevicePathNode (TmpDevPath2
);
176 The function returns whether or not the device is Opal Locked.
177 TRUE means that the device is partially or fully locked.
178 This will perform a Level 0 Discovery and parse the locking feature descriptor
180 @param[in] OpalDev Opal object to determine if locked
185 OPAL_SMM_DEVICE
*OpalDev
188 OPAL_SESSION Session
;
189 OPAL_DISK_SUPPORT_ATTRIBUTE SupportedAttributes
;
190 TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature
;
191 UINT16 OpalBaseComId
;
194 Session
.Sscp
= &OpalDev
->Sscp
;
197 Ret
= OpalGetSupportedAttributesInfo (&Session
, &SupportedAttributes
, &OpalBaseComId
);
198 if (Ret
!= TcgResultSuccess
) {
202 OpalDev
->OpalBaseComId
= OpalBaseComId
;
203 Session
.OpalBaseComId
= OpalBaseComId
;
205 Ret
= OpalGetLockingInfo(&Session
, &LockingFeature
);
206 if (Ret
!= TcgResultSuccess
) {
210 return OpalDeviceLocked (&SupportedAttributes
, &LockingFeature
);
214 Save/Restore RootPort configuration space.
216 @param[in] DeviceNode - The device node.
217 @param[in] SaveAction - TRUE: Save, FALSE: Restore
218 @param[in,out] PcieConfBufferList - Configuration space data buffer for save/restore
220 @retval - PCIE base address of this RootPort
223 SaveRestoreRootportConfSpace (
224 IN OPAL_SMM_DEVICE
*DeviceNode
,
225 IN BOOLEAN SaveAction
,
226 IN OUT UINT8
**PcieConfBufferList
232 UINT8
*StorePcieConfData
;
239 while (Length
< DeviceNode
->Length
) {
240 DevNode
= (PCI_DEVICE
*)((UINT8
*)DeviceNode
->PciBridgeNode
+ Length
);
241 RpBase
= PCI_LIB_ADDRESS (DevNode
->BusNum
, DevNode
->DevNum
, DevNode
->FuncNum
, 0x0);
243 if (PcieConfBufferList
!= NULL
) {
245 StorePcieConfData
= (UINT8
*) AllocateZeroPool (OPAL_PCIE_ROOTPORT_SAVESIZE
);
246 ASSERT (StorePcieConfData
!= NULL
);
247 OpalPciRead (StorePcieConfData
, RpBase
, OPAL_PCIE_ROOTPORT_SAVESIZE
);
248 PcieConfBufferList
[Index
] = StorePcieConfData
;
250 // Skip PCIe Command & Status registers
251 StorePcieConfData
= PcieConfBufferList
[Index
];
252 OpalPciWrite (RpBase
, StorePcieConfData
, 4);
253 OpalPciWrite (RpBase
+ 8, StorePcieConfData
+ 8, OPAL_PCIE_ROOTPORT_SAVESIZE
- 8);
255 FreePool (StorePcieConfData
);
259 Length
+= sizeof (PCI_DEVICE
);
267 Configure RootPort for downstream PCIe NAND devices.
269 @param[in] RpBase - PCIe configuration space address of this RootPort
270 @param[in] BusNumber - Bus number
271 @param[in] MemoryBase - Memory base address
272 @param[in] MemoryLength - Memory size
276 ConfigureRootPortForPcieNand (
279 IN UINT32 MemoryBase
,
280 IN UINT32 MemoryLength
285 DEBUG ((DEBUG_INFO
, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n",
286 BusNumber
, MemoryBase
, MemoryLength
));
288 if (MemoryLength
== 0) {
289 MemoryLimit
= MemoryBase
;
291 MemoryLimit
= MemoryBase
+ MemoryLength
+ 0xFFFFF; // 1M
295 /// Configue PCIE configuration space for RootPort
297 PciWrite8 (RpBase
+ NVME_PCIE_BNUM
+ 1, (UINT8
) BusNumber
); // Secondary Bus Number registers
298 PciWrite8 (RpBase
+ NVME_PCIE_BNUM
+ 2, (UINT8
) BusNumber
); // Subordinate Bus Number registers
299 PciWrite8 (RpBase
+ NVME_PCIE_IOBL
, 0xFF); // I/O Base registers
300 PciWrite8 (RpBase
+ NVME_PCIE_IOBL
+ 1, 0x00); // I/O Limit registers
301 PciWrite16 (RpBase
+ NVME_PCIE_MBL
, (UINT16
) RShiftU64 ((UINTN
)MemoryBase
, 16)); // Memory Base register
302 PciWrite16 (RpBase
+ NVME_PCIE_MBL
+ 2, (UINT16
) RShiftU64 ((UINTN
)MemoryLimit
, 16)); // Memory Limit register
303 PciWrite16 (RpBase
+ NVME_PCIE_PMBL
, 0xFFFF); // Prefetchable Memory Base registers
304 PciWrite16 (RpBase
+ NVME_PCIE_PMBL
+ 2, 0x0000); // Prefetchable Memory Limit registers
305 PciWrite32 (RpBase
+ NVME_PCIE_PMBU32
, 0xFFFFFFFF); // Prefetchable Memory Upper Base registers
306 PciWrite32 (RpBase
+ NVME_PCIE_PMLU32
, 0x00000000); // Prefetchable Memory Upper Limit registers
311 Dispatch function for a Software SMI handler.
313 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
314 @param[in] RegisterContext Points to an optional handler context which was specified when the
315 handler was registered.
316 @param[in, out] CommBuffer A pointer to a collection of Data in memory that will
317 be conveyed from a non-SMM environment into an SMM environment.
318 @param[in, out] CommBufferSize The Size of the CommBuffer.
320 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
321 should still be called.
322 @retval Others Other execution results.
326 SmmUnlockOpalPassword (
327 IN EFI_HANDLE DispatchHandle
,
328 IN CONST VOID
*RegisterContext
,
329 IN OUT VOID
*CommBuffer
,
330 IN OUT UINTN
*CommBufferSize
334 OPAL_SMM_DEVICE
*OpalDev
;
341 UINT8
*StorePcieConfDataList
[16];
345 OPAL_SESSION Session
;
347 ZeroMem (StorePcieConfDataList
, sizeof (StorePcieConfDataList
));
348 Status
= EFI_DEVICE_ERROR
;
351 // try to unlock all locked hdd disks.
353 for (Entry
= mSmmDeviceList
.ForwardLink
; Entry
!= &mSmmDeviceList
; Entry
= Entry
->ForwardLink
) {
354 OpalDev
= BASE_CR(Entry
, OPAL_SMM_DEVICE
, Link
);
360 /// Configure RootPort for PCIe AHCI/NVME devices.
362 if (OpalDev
->DeviceType
== OPAL_DEVICE_TYPE_NVME
) {
364 /// Save original RootPort configuration space to heap
366 RpBase
= SaveRestoreRootportConfSpace (
369 StorePcieConfDataList
371 MemoryBase
= mNvmeContext
.Nbar
;
373 ConfigureRootPortForPcieNand (RpBase
, OpalDev
->BusNum
, (UINT32
) MemoryBase
, (UINT32
) MemoryLength
);
376 /// Enable PCIE decode for RootPort
378 SataCmdSt
= PciRead8 (RpBase
+ NVME_PCIE_PCICMD
);
379 PciWrite8 (RpBase
+ NVME_PCIE_PCICMD
, 0x6);
381 SataCmdSt
= PciRead8 (PCI_LIB_ADDRESS (OpalDev
->BusNum
, OpalDev
->DevNum
, OpalDev
->FuncNum
, NVME_PCIE_PCICMD
));
382 PciWrite8 (PCI_LIB_ADDRESS (OpalDev
->BusNum
, OpalDev
->DevNum
, OpalDev
->FuncNum
, NVME_PCIE_PCICMD
), 0x6);
385 BaseClassCode
= PciRead8 (PCI_LIB_ADDRESS (OpalDev
->BusNum
, OpalDev
->DevNum
, OpalDev
->FuncNum
, 0x0B));
386 SubClassCode
= PciRead8 (PCI_LIB_ADDRESS (OpalDev
->BusNum
, OpalDev
->DevNum
, OpalDev
->FuncNum
, 0x0A));
387 ProgInt
= PciRead8 (PCI_LIB_ADDRESS (OpalDev
->BusNum
, OpalDev
->DevNum
, OpalDev
->FuncNum
, 0x09));
388 if (BaseClassCode
!= PCI_CLASS_MASS_STORAGE
) {
389 Status
= EFI_INVALID_PARAMETER
;
393 Status
= EFI_DEVICE_ERROR
;
394 if (OpalDev
->DeviceType
== OPAL_DEVICE_TYPE_SATA
) {
395 if ((SubClassCode
== PCI_CLASS_MASS_STORAGE_AHCI
) || (SubClassCode
== PCI_CLASS_MASS_STORAGE_RAID
)) {
396 Status
= GetAhciBaseAddress (OpalDev
->BusNum
, OpalDev
->DevNum
, OpalDev
->FuncNum
);
397 if (EFI_ERROR (Status
)) {
398 DEBUG ((DEBUG_ERROR
, "GetAhciBaseAddress error, Status: %r\n", Status
));
401 Status
= AhciModeInitialize ((UINT8
)OpalDev
->SataPort
);
402 ASSERT_EFI_ERROR (Status
);
403 if (EFI_ERROR (Status
)) {
404 DEBUG ((DEBUG_ERROR
, "AhciModeInitialize error, Status: %r\n", Status
));
408 DEBUG ((DEBUG_ERROR
, "SubClassCode not support for SATA device\n"));
410 } else if (OpalDev
->DeviceType
== OPAL_DEVICE_TYPE_NVME
) {
411 if (SubClassCode
== PCI_CLASS_MASS_STORAGE_NVM
) {
412 if (ProgInt
!= PCI_IF_NVMHCI
) {
413 DEBUG ((DEBUG_ERROR
, "PI not support, skipped\n"));
414 Status
= EFI_NOT_FOUND
;
418 mNvmeContext
.PciBase
= PCI_LIB_ADDRESS (OpalDev
->BusNum
, OpalDev
->DevNum
, OpalDev
->FuncNum
, 0x0);
419 mNvmeContext
.NvmeInitWaitTime
= 0;
420 mNvmeContext
.Nsid
= OpalDev
->NvmeNamespaceId
;
421 Status
= NvmeControllerInit (&mNvmeContext
);
423 DEBUG ((DEBUG_ERROR
, "SubClassCode not support for NVME device\n"));
426 DEBUG ((DEBUG_ERROR
, "Invalid Devicetype\n"));
430 Status
= EFI_DEVICE_ERROR
;
431 if (IsOpalDeviceLocked(OpalDev
)) {
432 ZeroMem(&Session
, sizeof(Session
));
433 Session
.Sscp
= &OpalDev
->Sscp
;
435 Session
.OpalBaseComId
= OpalDev
->OpalBaseComId
;
438 Result
= OpalBlockSid (&Session
, TRUE
);
439 if (Result
!= TcgResultSuccess
) {
444 Result
= OpalSupportUnlock (&Session
, OpalDev
->Password
, OpalDev
->PasswordLength
, NULL
);
445 if (Result
== TcgResultSuccess
) {
446 Status
= EFI_SUCCESS
;
450 if (OpalDev
->DeviceType
== OPAL_DEVICE_TYPE_NVME
) {
451 if (SubClassCode
== PCI_CLASS_MASS_STORAGE_NVM
) {
452 Status
= NvmeControllerExit (&mNvmeContext
);
457 if (OpalDev
->DeviceType
== OPAL_DEVICE_TYPE_NVME
) {
458 ASSERT (RpBase
!= 0);
459 PciWrite8 (RpBase
+ NVME_PCIE_PCICMD
, 0);
460 RpBase
= SaveRestoreRootportConfSpace (
463 StorePcieConfDataList
465 PciWrite8 (RpBase
+ NVME_PCIE_PCICMD
, SataCmdSt
);
467 PciWrite8 (PCI_LIB_ADDRESS (OpalDev
->BusNum
, OpalDev
->DevNum
, OpalDev
->FuncNum
, NVME_PCIE_PCICMD
), SataCmdSt
);
470 if (EFI_ERROR (Status
)) {
480 Main entry point for an SMM handler dispatch or communicate-based callback.
482 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
483 @param[in] Context Points to an optional handler context which was specified when the
484 handler was registered.
485 @param[in,out] CommBuffer A pointer to a collection of Data in memory that will
486 be conveyed from a non-SMM environment into an SMM environment.
487 @param[in,out] CommBufferSize The Size of the CommBuffer.
489 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
490 should still be called.
491 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
493 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
495 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
499 S3SleepEntryCallBack (
500 IN EFI_HANDLE DispatchHandle
,
501 IN CONST VOID
*Context OPTIONAL
,
502 IN OUT VOID
*CommBuffer OPTIONAL
,
503 IN OUT UINTN
*CommBufferSize OPTIONAL
514 S3_BOOT_SCRIPT_LIB_WIDTH Width
;
516 OPAL_DISK_AND_PASSWORD_INFO
*PciDev
;
517 OPAL_HC_PCI_REGISTER_SAVE
*HcRegisterSaveListPtr
;
519 OPAL_SMM_DEVICE
*SmmDev
;
522 Status
= EFI_SUCCESS
;
524 mOpalDeviceList
= OpalSupportGetOpalDeviceList();
526 for (Entry
= mOpalDeviceList
->ForwardLink
; Entry
!= mOpalDeviceList
; Entry
= Entry
->ForwardLink
) {
527 PciDev
= BASE_CR (Entry
, OPAL_DISK_AND_PASSWORD_INFO
, Link
);
529 SmmDev
= AllocateZeroPool (sizeof (OPAL_SMM_DEVICE
));
530 if (SmmDev
== NULL
) {
531 return EFI_OUT_OF_RESOURCES
;
533 SmmDev
->Signature
= OPAL_SMM_DEVICE_SIGNATURE
;
535 ExtractDeviceInfoFromDevicePath(&PciDev
->OpalDevicePath
, SmmDev
);
537 SmmDev
->PasswordLength
= PciDev
->PasswordLength
;
538 CopyMem(&(SmmDev
->Password
), PciDev
->Password
, OPAL_PASSWORD_MAX_LENGTH
);
540 SmmDev
->Sscp
.ReceiveData
= SecurityReceiveData
;
541 SmmDev
->Sscp
.SendData
= SecuritySendData
;
543 InsertHeadList (&mSmmDeviceList
, &SmmDev
->Link
);
545 if (SmmDev
->DeviceType
== OPAL_DEVICE_TYPE_NVME
) {
550 // Save register Data for S3. Sata controller only.
552 Bus
= SmmDev
->BusNum
;
553 Device
= SmmDev
->DevNum
;
554 Function
= SmmDev
->FuncNum
;
556 ASSERT (SmmDev
->DeviceType
== OPAL_DEVICE_TYPE_SATA
);
557 HcRegisterSaveListPtr
= (OPAL_HC_PCI_REGISTER_SAVE
*) mSataHcRegisterSaveTemplate
;
558 Count
= sizeof (mSataHcRegisterSaveTemplate
) / sizeof (OPAL_HC_PCI_REGISTER_SAVE
);
560 for (Index
= 0; Index
< Count
; Index
+= 1) {
561 Offset
= HcRegisterSaveListPtr
[Index
].Address
;
562 Width
= HcRegisterSaveListPtr
[Index
].Width
;
565 case S3BootScriptWidthUint8
:
566 Data
= (UINT32
)PciRead8 (PCI_LIB_ADDRESS(Bus
,Device
,Function
,Offset
));
568 case S3BootScriptWidthUint16
:
569 Data
= (UINT32
)PciRead16 (PCI_LIB_ADDRESS(Bus
,Device
,Function
,Offset
));
571 case S3BootScriptWidthUint32
:
572 Data
= PciRead32 (PCI_LIB_ADDRESS(Bus
,Device
,Function
,Offset
));
579 Address
= S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus
, Device
, Function
, Offset
);
580 Status
= S3BootScriptSavePciCfgWrite (Width
, Address
, 1, &Data
);
581 if (EFI_ERROR (Status
)) {
587 if (!IsListEmpty (mOpalDeviceList
)) {
588 Status
= S3BootScriptSaveIoWrite (S3BootScriptWidthUint8
, 0xB2, 1, &mSwSmiValue
);
589 ASSERT_EFI_ERROR (Status
);
596 Main entry for this driver.
598 @param ImageHandle Image handle this driver.
599 @param SystemTable Pointer to SystemTable.
601 @retval EFI_SUCESS This function always complete successfully.
606 OpalPasswordSmmInit (
607 IN EFI_HANDLE ImageHandle
,
608 IN EFI_SYSTEM_TABLE
*SystemTable
612 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SwDispatch
;
613 EFI_SMM_SX_DISPATCH2_PROTOCOL
*SxDispatch
;
615 EFI_SMM_SW_REGISTER_CONTEXT Context
;
616 EFI_HANDLE S3SleepEntryHandle
;
617 EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext
;
618 EFI_SMM_VARIABLE_PROTOCOL
*SmmVariable
;
619 OPAL_EXTRA_INFO_VAR OpalExtraInfo
;
621 EFI_PHYSICAL_ADDRESS Address
;
625 S3SleepEntryHandle
= NULL
;
626 ZeroMem (&mNvmeContext
, sizeof (NVME_CONTEXT
));
628 Status
= gSmst
->SmmLocateProtocol (
629 &gEfiSmmSwDispatch2ProtocolGuid
,
633 ASSERT_EFI_ERROR (Status
);
634 if (EFI_ERROR (Status
)) {
635 DEBUG((DEBUG_ERROR
, " SmmLocateProtocol gEfiSmmSwDispatch2ProtocolGuid fail, Status: %r\n", Status
));
639 Status
= gSmst
->SmmLocateProtocol (
640 &gEfiSmmSxDispatch2ProtocolGuid
,
644 ASSERT_EFI_ERROR (Status
);
645 if (EFI_ERROR (Status
)) {
646 DEBUG((DEBUG_ERROR
, " SmmLocateProtocol gEfiSmmSxDispatch2ProtocolGuid fail, Status: %r\n", Status
));
651 // Preallocate a 512 bytes Buffer to perform trusted I/O.
652 // Assume this is big enough for unlock commands
653 // It's because DMA can not access smmram stack at the cmd execution.
655 Address
= 0xFFFFFFFF;
656 Status
= gBS
->AllocatePages (
659 EFI_SIZE_TO_PAGES (SMM_SIZE_ALLOC_BYTES
),
662 if (EFI_ERROR (Status
)) {
663 DEBUG((DEBUG_ERROR
, " AllocatePages for SATA DAM fail, Status: %r\n", Status
));
664 return EFI_OUT_OF_RESOURCES
;
667 mBuffer
= (VOID
*)(UINTN
)Address
;
668 ZeroMem ((VOID
*)(UINTN
)mBuffer
, SMM_SIZE_ALLOC_BYTES
);
671 // Preallocate resource for AHCI transfer descriptor.
673 Status
= AhciAllocateResource ();
674 if (EFI_ERROR (Status
)) {
675 DEBUG((DEBUG_ERROR
, " AhciAllocateResource fail, Status: %r\n", Status
));
676 Status
= EFI_OUT_OF_RESOURCES
;
681 // Preallocate resource for NVMe configuration space.
683 Status
= NvmeAllocateResource (ImageHandle
, &mNvmeContext
);
684 if (EFI_ERROR (Status
)) {
685 DEBUG((DEBUG_ERROR
, " NvmeAllocateResource fail, Status: %r\n", Status
));
686 Status
= EFI_OUT_OF_RESOURCES
;
691 // Register a S3 entry callback function to store ATA host controller context to boot script.
692 // These boot scripts would be invoked at S3 path to recovery ATA host controller h/w context
693 // for executing HDD unlock cmd.
695 EntryRegisterContext
.Type
= SxS3
;
696 EntryRegisterContext
.Phase
= SxEntry
;
697 Status
= SxDispatch
->Register (
699 S3SleepEntryCallBack
,
700 &EntryRegisterContext
,
703 ASSERT_EFI_ERROR (Status
);
704 if (EFI_ERROR (Status
)) {
709 // Register Opal password smm unlock handler
711 Context
.SwSmiInputValue
= (UINTN
) -1;
712 Status
= SwDispatch
->Register (
714 SmmUnlockOpalPassword
,
718 ASSERT_EFI_ERROR (Status
);
719 if (EFI_ERROR (Status
)) {
720 DEBUG((DEBUG_ERROR
, " SwDispatch->Register fail, Status: %r\n", Status
));
725 // trigger smi to unlock hdd if it's locked.
727 mSwSmiValue
= (UINT8
) Context
.SwSmiInputValue
;
729 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&SmmVariable
);
730 if (!EFI_ERROR (Status
)) {
731 DataSize
= sizeof (OPAL_EXTRA_INFO_VAR
);
732 Status
= SmmVariable
->SmmGetVariable (
733 OPAL_EXTRA_INFO_VAR_NAME
,
734 &gOpalExtraInfoVariableGuid
,
739 if (!EFI_ERROR (Status
)) {
740 mSendBlockSID
= OpalExtraInfo
.EnableBlockSid
;
747 if (S3SleepEntryHandle
!= NULL
) {
748 SxDispatch
->UnRegister (SxDispatch
, S3SleepEntryHandle
);
753 NvmeFreeResource (&mNvmeContext
);
755 if (mBuffer
!= NULL
) {
756 gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
)(UINTN
) mBuffer
, EFI_SIZE_TO_PAGES (SMM_SIZE_ALLOC_BYTES
));
763 Provide Io action support.
765 @param[in] SmmDev the opal device need to perform trust io.
766 @param[in] IoType OPAL_IO_TYPE indicating whether to perform a Trusted Send or Trusted Receive.
767 @param[in] SecurityProtocol Security Protocol
768 @param[in] SpSpecific Security Protocol Specific
769 @param[in] TransferLength Transfer Length of Buffer (in bytes) - always a multiple of 512
770 @param[in] Buffer Address of Data to transfer
772 @retval TcgResultSuccess Perform the io action success.
773 @retval TcgResultFailure Perform the io action failed.
778 OPAL_SMM_DEVICE
*SmmDev
,
780 UINT8 SecurityProtocol
,
782 UINTN TransferLength
,
787 UINTN BufferSizeBlocks
;
788 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
790 Status
= EFI_DEVICE_ERROR
;
791 if (SmmDev
->DeviceType
== OPAL_DEVICE_TYPE_SATA
) {
792 BufferSizeBlocks
= TransferLength
/ 512;
794 ZeroMem( &AtaCommandBlock
, sizeof( EFI_ATA_COMMAND_BLOCK
) );
795 AtaCommandBlock
.AtaCommand
= ( IoType
== OpalSend
) ? ATA_COMMAND_TRUSTED_SEND
: ATA_COMMAND_TRUSTED_RECEIVE
;
796 AtaCommandBlock
.AtaSectorCount
= ( UINT8
)BufferSizeBlocks
;
797 AtaCommandBlock
.AtaSectorNumber
= ( UINT8
)( BufferSizeBlocks
>> 8 );
798 AtaCommandBlock
.AtaFeatures
= SecurityProtocol
;
799 AtaCommandBlock
.AtaCylinderLow
= ( UINT8
)( SpSpecific
>> 8 );
800 AtaCommandBlock
.AtaCylinderHigh
= ( UINT8
)( SpSpecific
);
801 AtaCommandBlock
.AtaDeviceHead
= ATA_DEVICE_LBA
;
804 ZeroMem( mBuffer
, HDD_PAYLOAD
);
805 ASSERT( TransferLength
<= HDD_PAYLOAD
);
807 if (IoType
== OpalSend
) {
808 CopyMem( mBuffer
, Buffer
, TransferLength
);
811 Status
= AhciPioTransfer(
813 (UINT8
) SmmDev
->SataPort
,
814 (UINT8
) SmmDev
->SataPortMultiplierPort
,
817 ( IoType
== OpalSend
) ? FALSE
: TRUE
, // i/o direction
821 (UINT32
)TransferLength
,
825 if (IoType
== OpalRecv
) {
826 CopyMem( Buffer
, mBuffer
, TransferLength
);
828 } else if (SmmDev
->DeviceType
== OPAL_DEVICE_TYPE_NVME
) {
829 Status
= NvmeSecuritySendReceive (
833 SwapBytes16(SpSpecific
),
838 DEBUG((DEBUG_ERROR
, "DeviceType(%x) not support.\n", SmmDev
->DeviceType
));
845 Send a security protocol command to a device that receives data and/or the result
846 of one or more commands sent by SendData.
848 The ReceiveData function sends a security protocol command to the given MediaId.
849 The security protocol command sent is defined by SecurityProtocolId and contains
850 the security protocol specific data SecurityProtocolSpecificData. The function
851 returns the data from the security protocol command in PayloadBuffer.
853 For devices supporting the SCSI command set, the security protocol command is sent
854 using the SECURITY PROTOCOL IN command defined in SPC-4.
856 For devices supporting the ATA command set, the security protocol command is sent
857 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
860 If the PayloadBufferSize is zero, the security protocol command is sent using the
861 Trusted Non-Data command defined in ATA8-ACS.
863 If PayloadBufferSize is too small to store the available data from the security
864 protocol command, the function shall copy PayloadBufferSize bytes into the
865 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
867 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
868 the function shall return EFI_INVALID_PARAMETER.
870 If the given MediaId does not support security protocol commands, the function shall
871 return EFI_UNSUPPORTED. If there is no media in the device, the function returns
872 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
873 the function returns EFI_MEDIA_CHANGED.
875 If the security protocol fails to complete within the Timeout period, the function
876 shall return EFI_TIMEOUT.
878 If the security protocol command completes without an error, the function shall
879 return EFI_SUCCESS. If the security protocol command completes with an error, the
880 function shall return EFI_DEVICE_ERROR.
882 @param This Indicates a pointer to the calling context.
883 @param MediaId ID of the medium to receive data from.
884 @param Timeout The timeout, in 100ns units, to use for the execution
885 of the security protocol command. A Timeout value of 0
886 means that this function will wait indefinitely for the
887 security protocol command to execute. If Timeout is greater
888 than zero, then this function will return EFI_TIMEOUT
889 if the time required to execute the receive data command
890 is greater than Timeout.
891 @param SecurityProtocolId The value of the "Security Protocol" parameter of
892 the security protocol command to be sent.
893 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
894 of the security protocol command to be sent.
895 @param PayloadBufferSize Size in bytes of the payload data buffer.
896 @param PayloadBuffer A pointer to a destination buffer to store the security
897 protocol command specific payload data for the security
898 protocol command. The caller is responsible for having
899 either implicit or explicit ownership of the buffer.
900 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the
901 data written to the payload data buffer.
903 @retval EFI_SUCCESS The security protocol command completed successfully.
904 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
905 data from the device. The PayloadBuffer contains the truncated data.
906 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
907 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
908 @retval EFI_NO_MEDIA There is no media in the device.
909 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
910 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
911 PayloadBufferSize is non-zero.
912 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
913 protocol command to execute.
918 SecurityReceiveData (
919 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
922 IN UINT8 SecurityProtocolId
,
923 IN UINT16 SecurityProtocolSpecificData
,
924 IN UINTN PayloadBufferSize
,
925 OUT VOID
*PayloadBuffer
,
926 OUT UINTN
*PayloadTransferSize
929 OPAL_SMM_DEVICE
*SmmDev
;
931 SmmDev
= OPAL_SMM_DEVICE_FROM_THIS (This
);
932 if (SmmDev
== NULL
) {
933 return EFI_DEVICE_ERROR
;
936 return PerformTrustedIo (
940 SecurityProtocolSpecificData
,
947 Send a security protocol command to a device.
949 The SendData function sends a security protocol command containing the payload
950 PayloadBuffer to the given MediaId. The security protocol command sent is
951 defined by SecurityProtocolId and contains the security protocol specific data
952 SecurityProtocolSpecificData. If the underlying protocol command requires a
953 specific padding for the command payload, the SendData function shall add padding
954 bytes to the command payload to satisfy the padding requirements.
956 For devices supporting the SCSI command set, the security protocol command is sent
957 using the SECURITY PROTOCOL OUT command defined in SPC-4.
959 For devices supporting the ATA command set, the security protocol command is sent
960 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
961 is non-zero. If the PayloadBufferSize is zero, the security protocol command is
962 sent using the Trusted Non-Data command defined in ATA8-ACS.
964 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
965 return EFI_INVALID_PARAMETER.
967 If the given MediaId does not support security protocol commands, the function
968 shall return EFI_UNSUPPORTED. If there is no media in the device, the function
969 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
970 device, the function returns EFI_MEDIA_CHANGED.
972 If the security protocol fails to complete within the Timeout period, the function
973 shall return EFI_TIMEOUT.
975 If the security protocol command completes without an error, the function shall return
976 EFI_SUCCESS. If the security protocol command completes with an error, the function
977 shall return EFI_DEVICE_ERROR.
979 @param This Indicates a pointer to the calling context.
980 @param MediaId ID of the medium to receive data from.
981 @param Timeout The timeout, in 100ns units, to use for the execution
982 of the security protocol command. A Timeout value of 0
983 means that this function will wait indefinitely for the
984 security protocol command to execute. If Timeout is greater
985 than zero, then this function will return EFI_TIMEOUT
986 if the time required to execute the send data command
987 is greater than Timeout.
988 @param SecurityProtocolId The value of the "Security Protocol" parameter of
989 the security protocol command to be sent.
990 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
991 of the security protocol command to be sent.
992 @param PayloadBufferSize Size in bytes of the payload data buffer.
993 @param PayloadBuffer A pointer to a destination buffer to store the security
994 protocol command specific payload data for the security
997 @retval EFI_SUCCESS The security protocol command completed successfully.
998 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
999 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
1000 @retval EFI_NO_MEDIA There is no media in the device.
1001 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1002 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
1003 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
1004 protocol command to execute.
1010 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
1013 IN UINT8 SecurityProtocolId
,
1014 IN UINT16 SecurityProtocolSpecificData
,
1015 IN UINTN PayloadBufferSize
,
1016 IN VOID
*PayloadBuffer
1019 OPAL_SMM_DEVICE
*SmmDev
;
1021 SmmDev
= OPAL_SMM_DEVICE_FROM_THIS (This
);
1022 if (SmmDev
== NULL
) {
1023 return EFI_DEVICE_ERROR
;
1026 return PerformTrustedIo (
1030 SecurityProtocolSpecificData
,