summaryrefslogtreecommitdiff
path: root/Core/EM/HddSecurity/IDESMM.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/HddSecurity/IDESMM.c')
-rw-r--r--Core/EM/HddSecurity/IDESMM.c1553
1 files changed, 1553 insertions, 0 deletions
diff --git a/Core/EM/HddSecurity/IDESMM.c b/Core/EM/HddSecurity/IDESMM.c
new file mode 100644
index 0000000..f898455
--- /dev/null
+++ b/Core/EM/HddSecurity/IDESMM.c
@@ -0,0 +1,1553 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/HddSecurity/IdeSmm/IDESMM.c 24 4/29/15 3:41a Anbuprakashp $
+//
+// $Revision: 24 $
+//
+// $Date: 4/29/15 3:41a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/HddSecurity/IdeSmm/IDESMM.c $
+//
+// 24 4/29/15 3:41a Anbuprakashp
+// [TAG] EIP215937
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System hang while SmmCommunication SMI trigger after enable
+// SmmChkEn bit
+// [RootCause] Bootservice call is used inside IDESMM driver
+// [Solution] Avoided using BootService call inide IDESMM driver
+// [Files] IDESMM.c
+//
+// 23 4/22/15 4:01a Anbuprakashp
+// [TAG] EIP212319
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System hang while SW_SMI_AHCI_LOCATE_AHCI_SMM SMI trigger
+// after enable SmmChkEn bit
+// [RootCause] Bootservice call used inside IdeSmm driver which causes
+// the Exception
+// [Solution] Changes made not to use BootService calls inside IdeSmm
+// driver
+// [Files] IdeSecurity.h
+// IdeSecurity.c
+// IDESMM.c
+//
+// 22 12/09/14 1:41a Anbuprakashp
+// [TAG] EIP193600
+// [Category] Improvement
+// [Description] Security Enhancement for SMIHandler in HddSecurity
+// module
+// [Files] IDESMM.mak, IDESMM.h, IDESMM.c
+//
+// 21 8/11/14 6:54a Anbuprakashp
+// [TAG] EIP178239
+// [Category] Improvement
+// [Description] S3 Resume fails when HDD password is set where platform
+// have more than one AHCI controller
+// [Files] AhciSmm.c,AhciSmm.sdl,IDESMM.c
+//
+// 20 12/18/13 4:07a Srikantakumarp
+// [TAG] EIP127356
+// [Category] Improvement
+// [Description] Flash NVRAM seems to cause HDD can't be unlocked when
+// S3 resume.
+// [Files] IdeSecurity.c, IDESMM.c, HddPassword.c, AhciBus.c, AhciBus.h
+//
+// 19 1/08/13 12:39a Rameshr
+// [TAG] EIP109495
+// [Category] Improvement
+// [Description] HddSecurity driver needs to be updated for PI
+// specification 1.2
+// [Files] IdeSmm.c, IdeSmm.dxs, IdeSmm.h, IdeSmm.cif
+//
+// 18 8/22/11 2:06a Anandakrishnanl
+// [TAG] EIP67738
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] IdeSmm.c File has been changed in the previous version to
+// remove AHCI Controller Init programming that issue controller reset in
+// S3. This causes various AMD platforms to not resume from S3 properly.
+// [RootCause] IdeSmm.c File has been changed in the previous version to
+// remove AHCI Controller Init programming that issue controller reset in
+// S3. This causes various AMD platforms to not resume from S3 properly.
+// [Solution] Reverted the Idesmm.c file to previous version that will
+// bring back the Ahci Controller initialization by issuing Controller
+// reset
+// [Files] IDESMM.C
+//
+// 17 12/22/10 11:52a Krishnakumarg
+// [TAG] - EIP 46081
+// [Category] - Action Item
+// [Description] - 64 bit PCI config space exception in AHCI driver.
+// [Files] - IDESmm.c
+//
+// 16 10/11/10 11:02a Krishnakumarg
+// [TAG]- EIP 43249
+// [Category]-IMPROVEMENT
+// [Description]- Non-Ascii character in comments causing build problem in
+// japanese XP
+// [Files]- IdeSecurity.c,IDESMM.c, InstallIdeSmi, Ata.c, Atapi.c,
+// IDEBusComponentName.c, IdeBusMaster.c, IdeHPA.c, IdePowerManagement.c
+//
+// 15 9/20/10 4:19a Rameshr
+// [TAG]- EIP 44182
+// [Category]-IMPROVEMENT
+// [Description]- Unable to build the project with HDDSecurity module and
+// without AHCI module.
+// [Files]- IdeSecurity.h, IdeSmm.c
+//
+// 14 9/13/10 1:40a Rameshr
+// [TAG]- EIP 43299
+// [Category]-IMPROVEMENT
+// [Description]- About IdeSecurity module. It use soft smi port 0xb2
+// directly.It will need to re-modify on all of AMD project.
+// 1) Added the SDL token for Sw SMI port address.
+// 2) Used Pciio protocol to get the device location and passed this
+// information to SMM driver.
+// [Files]- IdeSecurity.c, IdeSmm.c, PideBus.h
+//
+// 13 6/01/10 7:07p Krishnakumarg
+// Removed Tab spaces.
+//
+// 12 1/15/10 10:14a Yul
+// Coding Standard
+//
+// 11 11/02/09 6:04p Davidd
+// - Correct S3 resume hanging problem when IDE_PASSWORD_LENGTH is set to
+// some value other than 32 (EIP 27989).
+// - Correct S3 resume hanging problem in AHCI mode (EIP 29827).
+//
+// 10 6/05/09 2:47p Rameshr
+// x64 mode compilation error Resolved.
+// Eip:22710
+//
+// 9 5/11/09 9:39a Rameshr
+// Symptom: Unable to clear the HDD password.
+// Solution: SmmProtocols located on the remove HDD password SMI also.
+// EIP: 21668
+//
+// 8 4/28/09 6:56p Rameshr
+// HDD password support in RAID mode
+// EIP:20421
+//
+// 7 3/31/09 6:52p Davidd
+// Added Device Configuration Freeze Lock programming.
+//
+// 6 3/05/09 11:34a Rameshr
+// RemovedHddpassword doesn't work for Ahci mode- EIP 19935.
+//
+// 5 4/11/08 4:26p Rameshraju
+// s3 Resume time improved when is security not enabled.
+//
+// 2 3/24/08 6:37p Fasihm
+// Updated some missed protocols inside the build switchs.
+//
+// 4 24/03/08 6:34p Anandakrishnanl
+// Removed unwanted comment.
+//
+// 3 24/03/08 6:31p Anandakrishnanl
+// Corrected the SMM Thunk Protocols to Extended Thunk Protocols.
+//
+// 1 3/11/08 2:40p Fasihm
+// Changed the structure names to match with the new SMM module labeled.
+// Will have to remove this after updating the IdeSecurity module with
+// this change.
+//
+// 2 10/03/08 6:47p Anandakrishnanl
+// Removed FreezeLock related code from SMI for improving the S3 resume
+// time.
+//
+// 1 28/02/08 6:40p Anandakrishnanl
+// Created new HddSecurity module. Isolated IdeSecurity and IdeSmm from
+// IdeBus driver to be compatable with the AHCI Bus driver.
+//
+// 1 2/20/08 8:13p Fasihm
+// Added the code to fix the SATA freeze problem.
+//
+// 8 22/06/07 12:44p Anandakrishnanl
+// HardDisk Security Support Module Added.
+// Need ACPI Module and SB Module and under Core\Include we updated
+// Setup.h.
+// Also New IdeBus bin module.
+//
+// 7 13/04/07 3:06p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with AMI coding
+// standard"!!!
+//
+// 6 12/18/06 11:53a Srinin
+// Fixed issues with unlocking HDD password during S3 resume.
+//
+// 5 8/24/06 5:08p Felixp
+//
+// 4 8/24/06 5:07p Felixp
+// x64 support (warnings/errors fixed)
+//
+// 3 8/24/06 9:31a Felixp
+// x64 support (asm code removed)
+//
+// 2 1/04/06 9:36a Srinin
+// Access to Boot services during Runtime removed.
+//
+// 1 12/14/05 2:57p Srinin
+//
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IdeSMM.C
+//
+// Description: Provide functions to unlock HDD password during S3 resume
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "IDESMM.h"
+
+#if ( defined(AhciSrc_SUPPORT) && (AhciSrc_SUPPORT != 0) )
+EFI_GUID gAhciSmmProtocolGuid = AHCI_SMM_PROTOCOL_GUID;
+UINT8 *AhciSecurityBuffer = NULL;
+AHCI_BUS_SMM_PROTOCOL *mAhciSmm = NULL;
+#endif
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION>=0x4028B)
+#define RETURN(status) {return status;}
+#else
+#define RETURN(status) {return ;}
+#endif
+
+EFI_GUID gSecurityModeProtocolGuid = IDE_SECURITY_INTERFACE_GUID;
+DLIST gPasswordList;
+
+COMMAND_BUFFER *mCmdBuffer;
+UINT8 *mDataBuffer = NULL;
+UINT8 *mDataSmmBuffer = NULL;
+UINT8 *SecurityBuffer = NULL;
+BOOLEAN AhciInit = FALSE;
+
+SECURITY_PROTOCOL *IdeSecurityInterface = NULL;
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+ EFI_SMM_SYSTEM_TABLE2 *gSmst;
+#else
+ EFI_SMM_SYSTEM_TABLE *gSmst;
+#endif
+
+#define PCI_CFG_ADDR( bus, dev, func, reg ) \
+ ((VOID*)(UINTN) (PCIEX_BASE_ADDRESS\
+ + ((bus) << 20) + ((dev) << 15) + ((func) << 12) + reg))
+
+#define AHCI_BAR 0x24
+#define PCI_SCC 0x000A // Sub Class Code Register
+
+
+#if defined(EFI64) || defined(EFIx64)
+static UINT64 DivU64x32(
+ IN UINT64 Dividend,
+ IN UINTN Divisor,
+ OUT UINTN*Remainder OPTIONAL )
+{
+ UINT64 Result = Dividend / Divisor;
+
+ if ( Remainder )
+ {
+ *Remainder = Dividend % Divisor;
+ }
+ return Result;
+}
+
+#else
+
+static UINT64 DivU64x32(
+ IN UINT64 Dividend,
+ IN UINTN Divisor, //Can only be 31 bits.
+ OUT UINTN*Remainder OPTIONAL )
+{
+ UINT64 Result;
+ UINT32 Rem;
+
+ _asm
+ {
+ mov eax, dword ptr Dividend[0]
+ mov edx, dword ptr Dividend[4]
+ mov esi, Divisor
+ xor edi, edi ; Remainder
+ mov ecx, 64 ; 64 bits
+Div64_loop:
+ shl eax, 1 ;Shift dividend left. This clears bit 0.
+ rcl edx, 1
+ rcl edi, 1 ;Shift remainder left. Bit 0 = previous dividend bit 63.
+
+ cmp edi, esi ; If Rem >= Divisor, don't adjust
+ cmc ; else adjust dividend and subtract divisor.
+ sbb ebx, ebx ; if Rem >= Divisor, ebx = 0, else ebx = -1.
+ sub eax, ebx ; if adjust, bit 0 of dividend = 1
+ and ebx, esi ; if adjust, ebx = Divisor, else ebx = 0.
+ sub edi, ebx ; if adjust, subtract divisor from remainder.
+ loop Div64_loop
+
+ mov dword ptr Result[0], eax
+ mov dword ptr Result[4], edx
+ mov Rem, edi
+ }
+
+ if (Remainder) *Remainder = Rem;
+
+ return Result;
+}
+
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Stall
+//
+// Description: Stalls for the Required Amount of MicroSeconds
+//
+// Input:
+// UINTN Usec // Number of microseconds to delay
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+Stall (
+ UINTN Usec
+ )
+{
+ UINTN Counter, i;
+ UINT32 Data32, PrevData;
+ UINTN Remainder;
+
+ Counter = (UINTN)DivU64x32 ((Usec * 10), 3, &Remainder);
+
+ if (Remainder != 0) {
+ Counter++;
+ }
+
+ //
+ // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
+ // periods, thus attempting to ensure Microseconds of stall time.
+ //
+ if (Counter != 0) {
+
+ PrevData = IoRead32(PM_BASE_ADDRESS + 8);
+ for (i=0; i < Counter; ) {
+ Data32 = IoRead32(PM_BASE_ADDRESS + 8);
+ if (Data32 < PrevData) { // Reset if there is a overlap
+ PrevData=Data32;
+ continue;
+ }
+ i += (Data32 - PrevData);
+ PrevData = Data32;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ZeromemorySmm
+//
+// Description: Clears the buffer
+//
+// Input: void *Buffer,
+// UINTN Size
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+void
+ZeroMemorySmm (
+ void *Buffer,
+ UINTN Size
+ )
+{
+ UINT8 *Ptr;
+ Ptr = Buffer;
+ while (Size--) {
+ *(Ptr++) = 0;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SMMWaitforBitClear
+//
+// Description: Waits for the given bit to be clear
+//
+// Input: HDD_PASSWORD *pHddPassword,
+// UINT8 BitClear,
+// UINT32 Timeout
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SMMWaitforBitClear (
+ HDD_PASSWORD *pHddPassword,
+ UINT8 BitClear,
+ UINT32 Timeout
+ )
+{
+ UINT8 Delay;
+ UINT8 Data8;
+
+ for ( ; Timeout > 0; Timeout--) {
+ for ( Delay = 100; Delay > 0; Delay--) {
+ Data8 = IoRead8(pHddPassword->DeviceControlReg);
+ if (!(Data8 & BitClear)) return EFI_SUCCESS;
+ Stall(10); // 10 Usec
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SMMWaitforBitSet
+//
+// Description: Checks for a particular Bit to be set for a given amount
+// of time
+//
+// Input: HDD_PASSWORD *pHddPassword,
+// UINT8 BitSet,
+// UINT32 Timeout
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SMMWaitforBitSet (
+ HDD_PASSWORD *pHddPassword,
+ UINT8 BitSet,
+ UINT32 TimeOut
+ )
+{
+ UINT8 Delay;
+ UINT8 Data8;
+
+ for ( ; TimeOut > 0; TimeOut--) {
+ for ( Delay = 100; Delay > 0; Delay--) {
+ Data8 = IoRead8(pHddPassword->DeviceControlReg);
+ if (Data8 & BitSet) return EFI_SUCCESS;
+ Stall(10); // 10 Usec
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SMMWaitForCmdCompletion
+//
+// Description: Waits for BSY bit to get clear
+//
+// Input: HDD_PASSWORD *pHddPassword
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: Wait for BSY bit to get clear. Check for any errors.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SMMWaitForCmdCompletion (
+ HDD_PASSWORD *pHddPassword
+ )
+{
+ UINT8 Data8;
+ EFI_STATUS Status;
+
+// Read ATL_STATUS and ignore the result. Just a delay
+ Data8 = IoRead8(pHddPassword->DeviceControlReg);
+
+// Check for BSY bit to be clear
+ Status = SMMWaitforBitClear ( pHddPassword,
+ BSY,
+ DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT);
+
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+// Check for errors.
+ Data8 = IoRead8(pHddPassword->BaseAddress + 7);
+
+ if (Data8 & (ERR | DF)) return EFI_DEVICE_ERROR;
+
+ return EFI_SUCCESS;
+}
+
+#if ( defined(AhciSrc_SUPPORT) && (AhciSrc_SUPPORT != 0) )
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SMMAhciSecurityUnlockCommand
+//
+// Description: This Function unlocks HDD password during S3 resume in
+// Ahci Mode Using Int 13.
+//
+// Input: HDD_PASSWORD *pHddPassword
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SMMAhciSecurityUnlockCommand (
+ HDD_PASSWORD *pHddPassword
+ )
+{
+ UINT8 i;
+ UINT64 AhciBar = 0;
+ UINT8 SccReg;
+ BOOLEAN ControllerinAhciMode = FALSE;
+ UINT32 GlobalControl;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT32 NoofPorts=0;
+
+ if(mAhciSmm == NULL || !AhciSecurityBuffer) {
+ return EFI_NOT_FOUND;
+ }
+
+ // 1. Check if Controller is in AHCI Mode.
+ // 2. Read ABAR Offset and Get HbaAddress.
+ // 3. Disable AHCI_ENABLE.
+ // 4. Issue Controller Reset.
+ // 5. Wait for HBA Reset to Complete.
+ // 6. Enable AHCI_ENABLE.
+
+ AhciBar = *(UINT32*)PCI_CFG_ADDR( pHddPassword->BusNo,
+ pHddPassword->DeviceNo,
+ pHddPassword->FunctionNo,
+ AHCI_BAR);
+ AhciBar &= 0xFFFFFFF0;
+
+ // Store AhciBase address of HDD Drive before calling AhciSmmInitPortOnS3Resume() function
+ // of the "AHCI_BUS_SMM_PROTOCOL"
+ mAhciSmm->AhciBaseAddress=AhciBar;
+
+ // Find Number of Ports from BIT0:BIT4 of the HBA_CAP register
+ NoofPorts = ((MMIO_READ32(AhciBar + HBA_CAP)) & HBA_CAP_NP_MASK) + 1;
+
+ // Check if AHCI MMIO address space resides in SMRAM region. If yes, don't proceed.
+ if( AmiValidateMmioBuffer( (VOID*)mAhciSmm->AhciBaseAddress, HBA_PORTS_START + (NoofPorts * HBA_PORTS_REG_WIDTH) ) ) {
+ return EFI_NOT_FOUND;
+ }
+
+ if(!AhciInit) {
+ SccReg = *(UINT8*)PCI_CFG_ADDR(pHddPassword->BusNo,
+ pHddPassword->DeviceNo,
+ pHddPassword->FunctionNo,
+ PCI_SCC); // Get Scc Register;
+
+ if((SccReg & 0x06) || (SccReg & 0x04)) {
+ ControllerinAhciMode = TRUE;
+ }
+
+ if(ControllerinAhciMode) {
+
+ GlobalControl = MMIO_READ32(AhciBar + 0x04);
+
+ GlobalControl &= 0x7FFFFFFF;
+ MMIO_WRITE32(AhciBar + 0x04, GlobalControl);
+
+ GlobalControl = 0x01;
+ MMIO_WRITE32(AhciBar + 0x04, GlobalControl);
+
+ Stall(5000); // 5 milli Sec Delay
+
+ GlobalControl = 0x80000000;
+ MMIO_WRITE32(AhciBar + 0x04, GlobalControl);
+
+ Stall(1000000); // 1 Sec Delay
+ }
+ AhciInit=TRUE;
+ }
+
+ // Clear the Buffer
+ ZeroMemorySmm (AhciSecurityBuffer, 512);
+ AhciSecurityBuffer[0] = pHddPassword->Control & 1;;
+ if(AhciSecurityBuffer[0]) {
+ //Copy 32 Bytes of Password
+ for (i = 0; i < IDE_PASSWORD_LENGTH; i++) {
+ ((UINT8 *)AhciSecurityBuffer)[i + 2] = pHddPassword->MasterPassword[i];
+ }
+ } else {
+ //Copy 32 Bytes of Password
+ for (i = 0; i < IDE_PASSWORD_LENGTH; i++) {
+ ((UINT8 *)AhciSecurityBuffer)[i + 2] = pHddPassword->UserPassword[i];
+ }
+ }
+ //
+ //Resuming from S3. So bring back the AHCI controller to working state
+ //
+ mAhciSmm->AhciSmmInitPortOnS3Resume(mAhciSmm,pHddPassword->PortNumber);
+
+ //
+ //Setup the Unlock command
+ //
+ ZeroMemorySmm(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.SectorCount = 1;
+ CommandStructure.LBALow = 0;
+ CommandStructure.LBAMid = 0;
+ CommandStructure.LBAHigh = 0;
+ CommandStructure.Device = 0x40;
+ CommandStructure.Command = SECURITY_UNLOCK;
+ CommandStructure.Buffer = AhciSecurityBuffer;
+ CommandStructure.ByteCount = 512;
+ //
+ //Issue the unlock command
+ //
+ mAhciSmm->AhciSmmExecutePioDataCommand( mAhciSmm,
+ &CommandStructure,
+ pHddPassword->PortNumber,
+ 0xFF,
+ ATA,
+ TRUE);
+
+#if DISABLE_SOFT_SET_PREV
+ ZeroMemorySmm (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Features = DISABLE_SATA2_SOFTPREV; // Disable Software Preservation
+ CommandStructure.SectorCount = 6;
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+
+ mAhciSmm->AhciSmmExecuteNonDataCommand( mAhciSmm,
+ CommandStructure,
+ pHddPassword->PortNumber,
+ 0xFF,
+ ATA
+ );
+#endif
+
+ //
+ //Issue the Security Freeze lock command
+ //
+ ZeroMemorySmm(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SECURITY_FREEZE_LOCK;
+ mAhciSmm->AhciSmmExecuteNonDataCommand( mAhciSmm,
+ CommandStructure,
+ pHddPassword->PortNumber,
+ 0xFF,
+ ATA
+ );
+
+ //
+ //Issue the Device config Freeze lock command
+ //
+ ZeroMemorySmm (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = DEV_CONFIG_FREEZE_LOCK;
+ CommandStructure.Features = DEV_CONFIG_FREEZE_LOCK_FEATURES;
+ mAhciSmm->AhciSmmExecuteNonDataCommand( mAhciSmm,
+ CommandStructure,
+ pHddPassword->PortNumber,
+ 0xFF,
+ ATA
+ );
+
+ return EFI_SUCCESS;
+
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SMMSecurityUnlockCommand
+//
+// Description: This Function unlocks HDD password during S3 resume.
+//
+// Input: HDD_PASSWORD *pHddPassword
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SMMSecurityUnlockCommand (
+ HDD_PASSWORD *pHddPassword
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data8;
+ UINT8 i;
+ UINT16 Reg;
+
+ // Disable Interrupt
+ IoWrite8(pHddPassword->DeviceControlReg, 2);
+
+ // Select the drive
+ IoWrite8(pHddPassword->BaseAddress + 6, pHddPassword->Device << 4);
+
+ // Wait for BSY to go low
+ Status = SMMWaitforBitClear (pHddPassword, BSY, S3_BUSY_CLEAR_TIMEOUT);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ // Clear the Buffer
+ ZeroMemorySmm (SecurityBuffer, 512);
+
+ SecurityBuffer[0] = pHddPassword->Control & 1;;
+
+ if(SecurityBuffer[0]) {
+
+ // Copy 32 Bytes of Password
+
+ for (i = 0; i < IDE_PASSWORD_LENGTH; i++) {
+ ((UINT8 *)SecurityBuffer)[i + 2] = pHddPassword->MasterPassword[i];
+ }
+ } else {
+
+ // Copy 32 Bytes of Password
+ for (i = 0; i < IDE_PASSWORD_LENGTH; i++) {
+ ((UINT8 *)SecurityBuffer)[i + 2] = pHddPassword->UserPassword[i];
+ }
+ }
+
+ Status = SMMIdeNonDataCommand (pHddPassword,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ SECURITY_UNLOCK);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ // Wait for Command completion
+ Status = SMMWaitForCmdCompletion (pHddPassword);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ // Check for DRQ
+ Status = SMMWaitforBitSet(pHddPassword, DRQ, DRQ_TIMEOUT);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ Reg = pHddPassword->BaseAddress;
+
+ // Status = IdeWriteMultipleWord (pHddPassword->BaseAddress, 256, &SecurityBuffer);
+ IoWrite(
+ CpuIoWidthFifoUint16,
+ Reg,
+ 256,
+ SecurityBuffer
+ );
+
+ // Check for errors
+ Status = SMMWaitForCmdCompletion (pHddPassword);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ // Check for errors.
+ Data8 = IoRead8 ( pHddPassword->BaseAddress + 7);
+ if(Data8 & 0x21) { // ERR OR DF bit set ?
+ return EFI_DEVICE_ERROR;
+ }
+
+//IA32_DEBUG
+#if DISABLE_SOFT_SET_PREV || FORCE_HDD_PASSWORD_PROMPT
+ Status = SMMIdeNonDataCommand (pHddPassword,
+ DISABLE_SATA2_SOFTPREV,
+ 6,
+ 0,
+ 0,
+ 0,
+ SET_FEATURE_COMMAND);
+
+ // Check for errors
+ Status = SMMWaitForCmdCompletion (pHddPassword);
+ if (EFI_ERROR(Status)) return Status;
+#endif
+
+ Status = SMMIdeNonDataCommand (pHddPassword,
+ DEV_CONFIG_FREEZE_LOCK_FEATURES,
+ 0,
+ 0,
+ 0,
+ 0,
+ DEV_CONFIG_FREEZE_LOCK);
+
+ // Check for errors
+ Status = SMMWaitForCmdCompletion (pHddPassword);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SMMIdeNonDataCommand
+//
+// Description: Issues Set Feature command (Non Data)
+//
+// Input: HDD_PASSWORD *pHddPassword
+// UINT8 Command
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SMMIdeNonDataCommand (
+ HDD_PASSWORD *pHddPassword,
+ IN UINT8 Features,
+ IN UINT8 SectorCount,
+ IN UINT8 LBALow,
+ IN UINT8 LBAMid,
+ IN UINT8 LBAHigh,
+ IN UINT8 Command
+)
+{
+
+ EFI_STATUS Status;
+ UINT8 Data8;
+
+// Select the drive
+ IoWrite8(pHddPassword->BaseAddress + 6, pHddPassword->Device << 4);
+
+// Check for Controller presence
+ Data8 = IoRead8(pHddPassword->DeviceControlReg);
+ if (Data8 == 0xFF) {
+ ASSERT(Data8 == 0xFF);
+ return EFI_DEVICE_ERROR;
+ }
+
+// Before Writing to Sector Count Reg, BSY and DRQ bit should be zero
+ Status = SMMWaitforBitClear(pHddPassword, BSY, S3_BUSY_CLEAR_TIMEOUT);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+// Check for DRDY
+ Status = SMMWaitforBitSet(pHddPassword, DRDY, DRDY_TIMEOUT);
+ if (EFI_ERROR(Status)) return EFI_TIMEOUT;
+
+// Issue command
+
+ IoWrite8 ( pHddPassword->BaseAddress + 1, Features);
+ IoWrite8 ( pHddPassword->BaseAddress + 2, SectorCount);
+ IoWrite8 ( pHddPassword->BaseAddress + 3, LBALow);
+ IoWrite8 ( pHddPassword->BaseAddress + 4, LBAMid);
+ IoWrite8 ( pHddPassword->BaseAddress + 5, LBAHigh);
+ IoWrite8 ( pHddPassword->BaseAddress + 7, Command);
+
+ return EFI_SUCCESS;
+
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: LocateSMMServices
+//
+// Description: This function Locates the AhciSmm protocl from the Smm
+//
+// Input: None
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS LocateSMMServices(
+ IN EFI_GUID *VariableGuid,
+ IN VOID **VariablePointer
+)
+{
+ UINTN Index;
+
+ for (Index = 0; Index < gSmst->NumberOfTableEntries; ++Index) {
+ if (guidcmp(&gSmst->SmmConfigurationTable[Index].VendorGuid,VariableGuid) == 0) {
+ break;
+ }
+ }
+
+ if (Index != gSmst->NumberOfTableEntries) {
+ *VariablePointer = gSmst->SmmConfigurationTable[Index].VendorTable;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: LocateIdeSmmProtocols
+//
+// Description: This function Locates the protocols and saves in global pointe
+//
+// Input: None
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID LocateIdeSmmProtocols()
+{
+
+#if ( defined(AhciSrc_SUPPORT) && (AhciSrc_SUPPORT != 0) )
+ if(mAhciSmm == NULL && gSmst ) {
+ LocateSMMServices(&gAhciSmmProtocolGuid,(VOID **)&mAhciSmm);
+ }
+#endif
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SaveHDDPassword
+//
+// Description: This function saves the HDD password and other information
+// necessary to unlock HDD password during S3 Resume.
+//
+// Input: DispatchHandle Handle to the Dispatcher
+// DispatchContext SW SMM dispatcher context
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+EFI_STATUS SaveHDDPassword (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+#else
+VOID SaveHDDPassword (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+#endif
+)
+{
+
+ HDD_PASSWORD *pHddPassword=NULL, *StoredHDDList;
+ DLINK *dlink;
+ UINT8 i;
+ BOOLEAN UserOrMaster = FALSE;
+ BOOLEAN CheckFlag;
+ EFI_STATUS Status=EFI_SUCCESS;
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010014)
+ pHddPassword = (HDD_PASSWORD *)CommBuffer;
+#else
+ Status = pBS->LocateProtocol(&gSecurityModeProtocolGuid, NULL, &IdeSecurityInterface);
+ if(!EFI_ERROR(Status)) {
+ pHddPassword = IdeSecurityInterface->pHDDPasswordBuffer;
+ }
+#endif
+
+ if (!pHddPassword) {
+ RETURN(Status);
+ }
+
+ // Check if signature is present or not
+ if ((UINT32) pHddPassword->Signature != '$HDD') {
+ RETURN(Status);
+ }
+
+ // Check whether info about the HDD is already present
+ dlink = gPasswordList.pHead;
+ for ( ; dlink; dlink = dlink->pNext) {
+ StoredHDDList = OUTTER(dlink, LinkList, HDD_PASSWORD);
+ CheckFlag = FALSE;
+ if(StoredHDDList->ModeFlag) {
+ if (StoredHDDList->PortNumber == pHddPassword->PortNumber) {
+ CheckFlag = TRUE;
+ }
+ } else {
+ if ((StoredHDDList->BaseAddress == pHddPassword->BaseAddress) &&
+ (StoredHDDList->Device == pHddPassword->Device)) {
+ CheckFlag = TRUE;
+ }
+ }
+
+ if (CheckFlag) {
+ UserOrMaster = (BOOLEAN)((pHddPassword->Control) & 0x01);
+
+ if(UserOrMaster){
+ // Match has been found. Just copy the Password buffer
+ for (i = 0; i < sizeof (pHddPassword->MasterPassword); i++) {
+ StoredHDDList->MasterPassword[i] = pHddPassword->MasterPassword[i];
+ }
+ } else {
+ // Match has been found. Just copy the Password buffer
+ for (i = 0; i < sizeof (pHddPassword->UserPassword); i++) {
+ StoredHDDList->UserPassword[i] = pHddPassword->UserPassword[i];
+ }
+ }
+ RETURN(Status);
+ }
+ }
+
+ // Allocate memory needed while unlocking the Password. Done only once.
+ // Same buffer will be reused.
+ if (SecurityBuffer == NULL) {
+ pSmst->SmmAllocatePool(0, 512, &SecurityBuffer);
+ }
+
+ // Match has not been found. Allocate memory and copy the buffer.
+ if (pSmst->SmmAllocatePool(0, sizeof(HDD_PASSWORD), &StoredHDDList) != EFI_SUCCESS) {
+ RETURN(Status);
+ }
+ for (i = 0; i < sizeof (HDD_PASSWORD); i++) ((UINT8 *)StoredHDDList)[i] = ((UINT8 *)pHddPassword)[i];
+ DListAdd(&gPasswordList, &StoredHDDList->LinkList);
+
+ RETURN(Status);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UnlockHDDPassword
+//
+// Description: This Function unlocks HDD password during S3 resume.
+//
+// Input: DispatchHandle Handle to the Dispatcher
+// DispatchContext SW SMM dispatcher context
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+EFI_STATUS UnlockHDDPassword (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+#else
+VOID UnlockHDDPassword (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+#endif
+)
+{
+ HDD_PASSWORD *StoredHDDList;
+ DLINK *dlink;
+ EFI_STATUS Status=EFI_SUCCESS;
+
+ dlink = gPasswordList.pHead;
+ for ( ; dlink; dlink = dlink->pNext) {
+ StoredHDDList = OUTTER(dlink, LinkList, HDD_PASSWORD);
+ if (StoredHDDList->Signature == '$HDD') {
+ if(!StoredHDDList->ModeFlag) {
+ SMMSecurityUnlockCommand (StoredHDDList);
+ } else {
+#if ( defined(AhciSrc_SUPPORT) && (AhciSrc_SUPPORT != 0) )
+ SMMAhciSecurityUnlockCommand (StoredHDDList);
+#endif
+ }
+ }
+ }
+ AhciInit=FALSE;
+
+ RETURN(Status);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RemoveHDDPassword
+//
+// Description: This Function removes HDD password from the internal database
+//
+// Input: DispatchHandle Handle to the Dispatcher
+// DispatchContext SW SMM dispatcher context
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+EFI_STATUS RemoveHDDPassword (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+#else
+VOID RemoveHDDPassword (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+#endif
+)
+{
+ HDD_PASSWORD *pHddPassword, *StoredHDDList;
+ DLINK *dlink;
+ EFI_STATUS Status=EFI_SUCCESS;
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010014)
+ pHddPassword = (HDD_PASSWORD *)CommBuffer;
+#else
+ Status = pBS->LocateProtocol(&gSecurityModeProtocolGuid, NULL, &IdeSecurityInterface);
+ if(!EFI_ERROR(Status)) {
+ pHddPassword = IdeSecurityInterface->pHDDPasswordBuffer;
+ }
+#endif
+
+ if (!pHddPassword) {
+ RETURN(Status);
+ }
+
+// Check if signature is present or not
+ if ((UINT32) pHddPassword->Signature != '$HDD') {
+ RETURN(Status);
+ }
+
+// Check whether info about the HDD is already present
+ dlink = gPasswordList.pHead;
+ for ( ; dlink; dlink = dlink->pNext) {
+ StoredHDDList = OUTTER(dlink, LinkList, HDD_PASSWORD);
+ if(StoredHDDList->ModeFlag) {
+ if (StoredHDDList->PortNumber == pHddPassword->PortNumber) {
+ DListDelete(&gPasswordList, &StoredHDDList->LinkList);
+ }
+ } else {
+ if ((StoredHDDList->BaseAddress == pHddPassword->BaseAddress) &&
+ (StoredHDDList->Device == pHddPassword->Device)) {
+ DListDelete(&gPasswordList, &StoredHDDList->LinkList);
+ }
+ }
+
+ }
+ RETURN(Status);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IdeSmmMiscSmiPassword
+//
+// Description: This Function Freeze locks HDD, Issues Disable/Enable Software
+// Settings preservation Feature for Security Supported HDDs.
+// Input: DispatchHandle Handle to the Dispatcher
+// DispatchContext SW SMM dispatcher context
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+EFI_STATUS IdeSmmMiscSmiPassword (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+#else
+VOID IdeSmmMiscSmiPassword (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+#endif
+)
+{
+ EFI_STATUS Status;
+ HDD_PASSWORD *StoredHDDList;
+ DLINK *dlink;
+
+ dlink = gPasswordList.pHead;
+ for ( ; dlink; dlink = dlink->pNext) {
+ StoredHDDList = OUTTER(dlink, LinkList, HDD_PASSWORD);
+ if (StoredHDDList->Signature == '$HDD') {
+
+ Status = SMMIdeNonDataCommand (StoredHDDList,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ SECURITY_FREEZE_LOCK);
+
+ // Check for errors
+ Status = SMMWaitForCmdCompletion (StoredHDDList);
+ if (EFI_ERROR(Status)) {
+ RETURN(Status);
+ }
+
+#if DISABLE_SOFT_SET_PREV || FORCE_HDD_PASSWORD_PROMPT
+
+ Status = SMMIdeNonDataCommand (StoredHDDList,
+ DISABLE_SATA2_SOFTPREV,
+ 6,
+ 0,
+ 0,
+ 0,
+ SET_FEATURE_COMMAND);
+
+ // Check for errors
+ Status = SMMWaitForCmdCompletion (StoredHDDList);
+ if (EFI_ERROR(Status)) {
+ RETURN(Status);
+ }
+#endif
+ }
+ }
+
+ RETURN(Status);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: LocateAhciSMM
+//
+// Description: This function Locates the AhciSMM driver and save pointer globally.
+//
+// Input: DispatchHandle Handle to the Dispatcher
+// DispatchContext SW SMM dispatcher context
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+EFI_STATUS LocateAhciSMM (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+#else
+VOID LocateAhciSMM (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+#endif
+)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010014)
+ // Unlock command Buffer
+ AhciSecurityBuffer = (UINT8 *)(*(UINTN *)CommBuffer);
+#else
+ if(!AhciSecurityBuffer) {
+ Status = pBS->AllocatePool ( EfiReservedMemoryType,
+ 512,
+ (VOID**)&AhciSecurityBuffer );
+ }
+#endif
+
+ LocateIdeSmmProtocols();
+ RETURN(Status);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IdeSmmInSmmFunction
+//
+// Description: Called from InstallSmiHandler
+//
+// Input:
+//
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeSmmInSmmFunction(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_SMM_SW_REGISTER_CONTEXT Unlock_HDD_Password = {SW_SMI_HDD_UNLOCK_PASSWORD};
+ EFI_SMM_SW_REGISTER_CONTEXT IdeSmm_MiscSmi_Password = {SW_SMI_HDD_MISC_SMM_FEATURES};
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+ EFI_SMM_BASE2_PROTOCOL *pSmmBase2;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *pSwDispatch = NULL;
+
+#else
+ EFI_SMM_BASE_PROTOCOL *pSmmBase;
+ EFI_SMM_SW_DISPATCH_PROTOCOL *pSwDispatch = NULL;
+#endif
+
+#if defined(PI_SPECIFICATION_VERSION)&&!(PI_SPECIFICATION_VERSION>=0x00010014)
+ EFI_SMM_SW_REGISTER_CONTEXT Save_HDD_Password = {SW_SMI_HDD_PASSWORD_SAVE};
+ EFI_SMM_SW_REGISTER_CONTEXT Remove_HDD_Password = {SW_SMI_HDD_PASSWORD_REMOVE};
+ EFI_SMM_SW_REGISTER_CONTEXT Locate_Ahci_SMM = {SW_SMI_AHCI_LOCATE_AHCI_SMM};
+#endif
+
+ InitAmiBufferValidationLib(ImageHandle, SystemTable);
+ Status = InitAmiSmmLib( ImageHandle, SystemTable );
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+
+ Status = pBS->LocateProtocol(&gEfiSmmBase2ProtocolGuid, NULL, &pSmmBase2);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // We are in SMM, retrieve the pointer to SMM System Table
+ //
+ Status = pSmmBase2->GetSmstLocation( pSmmBase2, &gSmst);
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gSmst->SmmLocateProtocol( &gEfiSmmSwDispatch2ProtocolGuid, \
+ NULL, \
+ &pSwDispatch );
+
+#else
+
+ Status = pBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, NULL, &pSmmBase);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = pSmmBase->GetSmstLocation(pSmmBase,&gSmst);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = pBS->LocateProtocol(&gEfiSmmSwDispatchProtocolGuid, NULL, &pSwDispatch);
+#endif
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ DListInit(&gPasswordList);
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010014)
+
+ Status = gSmst->SmiHandlerRegister(
+ (VOID *)SaveHDDPassword,
+ &gSaveHddPasswordGuid,
+ &Handle
+ );
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ Status = gSmst->SmiHandlerRegister(
+ (VOID *)RemoveHDDPassword,
+ &gRemoveHddPasswordGuid,
+ &Handle
+ );
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ Status = gSmst->SmiHandlerRegister(
+ (VOID *)LocateAhciSMM,
+ &gLocateIdeAhciSmmProtocolGuid,
+ &Handle
+ );
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ }
+
+#else
+ Status = pSwDispatch->Register(
+ pSwDispatch,
+ SaveHDDPassword,
+ &Save_HDD_Password,
+ &Handle
+ );
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ Status = pSwDispatch->Register(
+ pSwDispatch,
+ RemoveHDDPassword,
+ &Remove_HDD_Password,
+ &Handle
+ );
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ Status = pSwDispatch->Register(
+ pSwDispatch,
+ LocateAhciSMM ,
+ &Locate_Ahci_SMM ,
+ &Handle
+ );
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+#endif
+
+ Status = pSwDispatch->Register(
+ pSwDispatch,
+ UnlockHDDPassword,
+ &Unlock_HDD_Password,
+ &Handle
+ );
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+
+ Status = pSwDispatch->Register(
+ pSwDispatch,
+ IdeSmmMiscSmiPassword ,
+ &IdeSmm_MiscSmi_Password ,
+ &Handle
+ );
+
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IdeHDDPasswordSMMInit
+//
+// Description: Initializes HDD Password SMM Drivers.
+//
+// Input:
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// Here is the control flow of this function:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+IdeHDDPasswordSMMInit(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ InitAmiLib(ImageHandle,SystemTable);
+ return InitSmmHandler(ImageHandle, SystemTable, IdeSmmInSmmFunction, NULL);
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2015, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+