diff options
Diffstat (limited to 'Core/EM/HddSecurity/IdeSecurity.c')
-rw-r--r-- | Core/EM/HddSecurity/IdeSecurity.c | 2939 |
1 files changed, 2939 insertions, 0 deletions
diff --git a/Core/EM/HddSecurity/IdeSecurity.c b/Core/EM/HddSecurity/IdeSecurity.c new file mode 100644 index 0000000..cfa9d89 --- /dev/null +++ b/Core/EM/HddSecurity/IdeSecurity.c @@ -0,0 +1,2939 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2015, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/HddSecurity/IdeSecurity.c 43 4/22/15 3:57a Anbuprakashp $ +// +// $Revision: 43 $ +// +// $Date: 4/22/15 3:57a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/HddSecurity/IdeSecurity.c $ +// +// 43 4/22/15 3:57a 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 +// +// 42 3/16/15 5:50a Rameshr +// [TAG] EIP208331 +// [Category] Improvement +// [Description] Avoid sending freeze Lock command to the device if the +// HDD already in frozen state +// [Files] IdeSecurity.c, HddPassword.c +// +// 41 6/09/14 9:30a Anbuprakashp +// [TAG] EIP172445 +// [Category] Improvement +// [Description] Runtime attribute set for the some of the variable used +// by Aptio-4 HddSecurity driver and needs to be reviewed +// [Files] IdeSecurity.c +// +// 40 4/07/14 2:39a Nimishsv +// [TAG] EIP151848 +// [Category] Improvement +// [Description] [HDD security]Clear HDD security data related variable +// when secuirty disabled +// [Files] IdeSecurity.c +// +// 39 3/25/14 6:21a Rameshr +// [TAG] EIP160499 +// [Category] Improvement +// [Description] Do not get HDD password variable if HDD is in lock +// state +// [Files] IdeSecurity.c +// +// 38 3/25/14 6:12a Rameshr +// [TAG] EIP124591 +// [Category] Improvement +// [Description] Before sending the freeze lock command for the HDD, +// check the Hdd security status (locked or unlocked) and if the hdd is +// unlocked state, send the freeze lock command to hdd +// [Files] IdeSecurity.c +// +// 37 12/18/13 4:05a 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 +// +// 36 1/17/12 12:50a Jittenkumarp +// [TAG] EIP78432 +// [Category] Bug Fix +// [Symptom] The password set for OEM_MASTER_PASSWORD_TAG token is not +// authenticated when the token SETUP_PASSWORD_NON_CASE_SENSITIVE is set +// to 1. +// [RootCause] When SETUP_PASSWORD_NON_CASE_SENSITIVE token is 1, input +// password is always converted to Uppercase but OEM_MASTER_PASSWORD_TAG +// is in lower case. +// [Solution] OEM_MASTER_PASSWORD_TAG is converted into Uppercase before +// storing in memory. +// [Files] IdSecurity.c +// +// 35 1/05/12 6:25a Anandakrishnanl +// [TAG] EIP79637 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Enhanced Erase Mode not Working +// [RootCause] IdeSecurity Module SecurityEraseUnit did not handle Bit1 +// of Control Word to identify if it is a normal erase or Enhanced erase +// [Solution] [IdeSecurity Module]SIECURITY ERASE UNIT command needs +// Enhanced mode support +// Code changed from Control &= 0x1; // Bit0 is valid to Control &= 0x3; +// // Bit0 and Bit 1 is valid +// to make EnhancedErase functional. +// [Files] IdeSecurity.c +// +// 34 12/19/11 1:06a Rameshr +// [TAG] EIP77527 +// [Category] Improvement +// [Description] IdeSecurity, IdeAcoustic and IdeSmart changes should be +// done based on the Core Version checking. +// [Files] IdeSecurity.c, IdeSmart.c , Acoustic.c +// +// 33 12/05/11 6:24p Rajkumarkc +// [TAG] EIP77142 +// [Category] Improvement +// [Description] Added the function 'IdeNonDataCommandExp' in the +// 'IDE_BUS_PROTOCOL' and removed the existing function +// 'IdeNonDataCommand' for supporting the upper 24bits of LBA. +// [Files] +// Ata.c, IdeBus.c, Idebus.h, PIDEBus.h, Acoustic.c, IdeSecurity.c, +// IdeSMART.c +// +// 32 10/21/11 4:11a Rameshr +// [TAG] EIP69247 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Several IdeSecurity.sdl tokens are not working properly +// [RootCause] Several IdeSecurity.sdl tokens are not working properly +// [Solution] Removed unwanted SDL token and verified all the SDL token +// function. +// [Files] IdeSecurity.c, IdeSecurity.sdl, IdeSecurity.sdl +// +// 31 10/21/11 2:22a Rameshr +// [TAG] EIP70395 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] When an Empty Master Password string is entered for the +// first time(when no password was installed before), the +// IDEPasswordUpdateHdd returns a Boolean "TRUE" +// [RootCause] SecurityDisablePassword function returns the status of +// SetDefaultMasterPassword function which is EFI_SUCCESS instead of +// returning the status of SecurityCommonRoutine which will fail. +// [Solution] SecurityCommonRoutine function status returned as the +// status for SecurityDisablePassword function. +// [Files] IdeSecurity.c +// +// 30 10/11/11 1:54a Rameshr +// [TAG] EIP69246 +// [Category] Improvement +// [Description] Made the SECURITY_SUPPORT as the Master token and +// removed the IdeSecurity_Support token. +// +// [Files] IdeSecurity.c, IdeSecurity.h, IdeSecurity.mak, +// IdeSecurity.sdl +// +// 29 10/11/11 1:34a Rameshr +// [TAG] EIP70918 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] On S3 resume system will throw blue screen error, when HDD +// password is set +// [RootCause] Ld assume that the data is UINT64. But the actual data is +// UINT32. +// [Solution] To display d should be enough as the DataId is UINT32 +// [Files] IdeSecurity.c +// +// 28 4/27/11 6:03a Anandakrishnanl +// [TAG] EIP54315 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] SugarBay IdeSecurity increase S3 Resume time +// [RootCause] Setting the MASTER_PASSWORD_ENABLE sdl token in Ide +// security Module saves the password in Smm all the time in reboots. This +// causes the system to ask for master password even when it is not locked +// which causes Long Timeout in S3 resume. +// [Solution] Fix by not saving the master pasword in SMM at the time +// of Set password. Only Unlock password will save validated password in +// SMM area. +// [Files] IdeSecurity.c +// +// 27 4/06/11 12:52a Rameshr +// [TAG]- EIP 57341 +// [Category]-IMPROVEMENT +// [Description]- Added Support for SMM PI 1.1 in HDDSecurity eModule. +// [Files]- IdeSecurity.c , IdeSecurity.h, IdeSecurity.dxs +// +// 26 12/03/10 12:23a Rameshr +// [TAG] - EIP 48770 +// [Category]- BUG FIX +// [Severity]- Minor +// [Symptom] - HddSecurity build error when disable the IDEBUS module.. +// [RootCause]- IdebusLib used with IdeSecurity Module. +// [Solution] - Removed IdebusLib usage from source and mak file. +// [Files] - Idesecurity.c, IdeSecurity.mak +// +// 25 10/20/10 2:49a Rameshr +// [TAG]- EIP 43492 +// [Category]-IMPROVEMENT +// [Description]- Added the INTEL_IDE_PROTOCOL also to support old Core +// and drivers. +// [Files]- IdeSecurity.c +// +// 24 10/11/10 6:36p Krishnakumarg +// [TAG] - EIP 44603 +// [Category] - Enhancement +// [Severity] - Minor +// [Symptom] - No Hdd Password in Nvram once enable +// FORCE_HDD_PASSWORD_PROMPT +// [RootCause]- Password not stored in NVRAM on enabling the +// FORCE_HDD_PASSWORD_PROMPT token. +// [Solution] - Password will be stored in nvram based on +// HDD_PASSWORD_ON_NVRAM token. +// [Files] - IdeSecurity.c, IdeSecurity.sdl +// +// 23 10/11/10 10:59a 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 +// +// 22 9/13/10 1:37a 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 +// +// 21 9/13/10 1:31a Rameshr +// [TAG]- EIP 43492 +// [Category]-IMPROVEMENT +// [Description]- Change the INTEL_IDE_PROTOCOL into EFI_IDE_PROTOCOL in +// IdeSecurity.c +// [Files]- IdeSecurity.c +// +// 20 6/07/10 7:18p Krishnakumarg +// Build error in "4.6.3_HddSecurity_011" label.EIP#39531 +// +// 19 5/06/10 4:39p Yul +// Refer to EIP 37975 IdeSecurity related fixes. +// +// 18 2/19/10 12:47p Yul +// Delete the comment out codes +// +// 17 1/21/10 12:06p Yul +// Refer to EIP 33848. +// LegacyBios protocol is not needed here. +// +// 16 1/15/10 10:20a Yul +// Coding Standard +// +// 15 12/22/09 3:22p Krishnakumarg +// Update for chm file. Added some more comments in function headers +// +// 14 12/09/09 12:17p Krishnakumarg +// EIP 31797 : IDE Security API documentation. Added comments whereever +// possible and modified files for coding standard +// +// 13 11/25/09 6:02p Krishnakumarg +// Updated the file with comments to comply with AMI coding standard. +// +// 12 10/14/09 12:49p Krishnakumarg +// CloseEvent funtion used instead of a static variable in callback +// routines - EIP 27065 +// +// 11 7/09/09 4:52p Fasihm +// Update Identify Data before checking the Security Status of the Hard +// Disk. +// +// 10 4/28/09 6:52p Rameshr +// HDD password support in RAID mode +// EIP:20421 +// +// 9 3/31/09 7:02p Davidd +// Added FORCE_HDD_PASSWORD_PROMPT token and Device Configuration Freeze +// Lock programming. +// +// 8 3/29/09 11:11a Rameshr +// Security Erase command timeout value should be from the Identify packet +// command word 89. Added code in Ahci and IDE drivers. So removed the +// Extra timeout checking code from here. +// EIP 20630 +// +// 7 3/18/09 11:24a Fredericko +// EIP19618 removed dependency on foundation.lib +// +// 6 3/13/09 3:41p Fredericko +// +// 1 10/17/08 7:28p Fasihm +// This is the Initial check-in for the complete AMI Aptio source for the +// Calpella Crb platform based on Clarksfield and Ibex Peak - M chipsets. +// +// 5 9/15/08 9:01p Rameshraju +// Password Buffer is cleard before saving the password. +// +// 4 4/11/08 4:24p Rameshraju +// 1)Enter the Emptry string for the master password, will set the default +// OEM password and in setup password status will be not installed. +// 2)If the revision code is not 0, then SecuritySetPassword will use +// revision code from the input parameters. +// 3)HddSecutiyData Nvram variable master password cleared when we set +// user password and user password cleared when we set master password. +// 4)When we disable the password, HddSecutiyData Nvram variable also +// updated properly. +// 5)Password lenght stored in HddSecData structure. +// +// 3 4/09/08 4:22p Rameshraju +// Build error resolved when the MASTER_PASSWORD_ENABLED. +// +// 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. +// +// 15 10/23/07 4:17p Felixp +// IDE Security support moved from Sources to Binary +// +// 14 9/25/07 3:24p Rameshraju +// Set the OEM default master password when the HDD is in unlocked and Not +// Frozen State +// +// 13 14/08/07 1:57p Anandakrishnanl +// Changes made for: +// 1. Prompt for current password inside setup. +// 2. Display HardDisk Security Status information. +// 3. Master Password Verification Logic modified. +// 4. Added Password install status in ReturnIdePasswordFlags +// protocol function. +// +// 12 22/06/07 12:40p 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. +// +// 11 13/04/07 3:05p Anandakrishnanl +// Ide Bus Module - Update source files to comply with AMI coding +// standard"!!! +// +// 10 12/20/06 1:25p Felixp +// Warning fixed +// +// 9 12/18/06 11:59a Srinin +// Moved CreateReadytoBootEvent little later so that Ide Controller is +// restored first before HDD is unlocked during S3 Resume. +// +// 8 11/17/06 3:41p Ambikas +// +// 7 10/12/06 9:42a Felixp +// UEFI2.0 compliance: use CreateReadyToBootEvent instead of CreateEvent +// +// 6 3/21/06 4:47p Srinin +// Build error fixed. +// +// 5 3/13/06 2:21a Felixp +// +// 4 1/09/06 11:36a Felixp +// +// 2 12/14/05 3:09p Srinin +// HDD password unlock during S3 resume support added. +// +// 1 12/01/05 9:43a Felixp +// +// 6 3/04/05 11:35a Mandal +// +// 5 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 3 1/13/05 4:25p Srinin +// Procedure names modified. +// +// 2 1/10/05 11:31a Srinin +// IDESecurity Interface changed. +// +// 1 1/05/05 11:22a Srinin +// IDE Password Support added. +// +// +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: IDESecurityServices.c +// +// Description: IDE Security Support +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include "IdeSecurity.h" + + + +static EFI_GUID gHddSecurityInitProtocolGuid + = HDD_SECURITY_INIT_PROTOCOL_GUID; +static EFI_GUID gEfiBootScriptSaveGuid + = EFI_BOOT_SCRIPT_SAVE_GUID; +static EFI_GUID gIdeSecurityPwNvguid + = IDE_SECURITY_PWNV_GUID; +static EFI_GUID gSecurityModeProtocolGuid + = IDE_SECURITY_INTERFACE_GUID; +static EFI_GUID gEfiBlockIoProtocolGuid + = EFI_BLOCK_IO_PROTOCOL_GUID; + +extern EFI_DRIVER_BINDING_PROTOCOL gIdeBusDriverBinding; +extern EFI_EVENT gIDEBusEvtMiscSmmFeatures; +EFI_EVENT BootEvent = NULL; +EFI_EVENT gIDEBusEvtBootScript = NULL; + +const CHAR16 *sOemMasterPasswordTag + = CONVERT_TO_WSTRING( OEM_MASTER_PASSWORD_TAG ); +const CHAR16 *sDefaultMasterPasswordTag + = CONVERT_TO_WSTRING( DEFAULT_MASTER_PASSWORD_TAG ); + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) +EFI_SMM_CONTROL2_PROTOCOL *mSmmCtl=NULL; +#else +EFI_SMM_CONTROL_PROTOCOL *mSmmCtl=NULL; +#endif + +HDD_PASSWORD *gHDDPasswordBuffer = NULL; +EFI_SMM_COMMUNICATION_PROTOCOL *gSmmCommunication = NULL; + +#ifdef SW_SMI_IO_ADDRESS +UINT8 SwSmiPort=SW_SMI_IO_ADDRESS; +#else +// +// Default Sw Smi port +// +UINT8 SwSmiPort=0xB2; +#endif + +EFI_STATUS +HDDPortReset( + IN VOID *BusInterface, + IN BOOLEAN ModeFlag +); + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: InstallSecurityInterface +// +// Description: Checks whether the device supports Security mode or not. +// If yes, installs SecurityProtocol. +// +// Input: +// IN VOID *BusInterface, +// IN BOOLEAN ModeFlag +// +// Output: +// EFI_SUCCESS : Security Mode supported. +// EFI_DEVICE_ERROR/EFI_UNSUPPORTED : Not supported. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InstallSecurityInterface( + IN VOID *BusInterface, + IN BOOLEAN ModeFlag ) +{ + EFI_STATUS Status; + SECURITY_PROTOCOL *IdeSecurityInterface; + EFI_HANDLE IdeDeviceHandle; + IDENTIFY_DATA IdentifyData; + + #if MASTER_PASSWORD_ENABLE + UINT32 IdePasswordFlags = 0; + #endif + + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + if ( ModeFlag == FALSE ) + { + IdentifyData = IdeBusInterface->IdeDevice.IdentifyData; + IdeDeviceHandle = IdeBusInterface->IdeDeviceHandle; + } + else { + IdentifyData = SataDevInterface->IdentifyData; + IdeDeviceHandle = SataDevInterface->IdeDeviceHandle; + } + + if ((IdentifyData.Command_Set_Supported_82 & 0x2) == 0 ) + { + return EFI_UNSUPPORTED; + } + + Status = pBS->AllocatePool( EfiBootServicesData, + sizeof(SECURITY_PROTOCOL), + (VOID**)&IdeSecurityInterface ); + + if ( EFI_ERROR( Status )) + { + return Status; + } + + // + // gHDDPasswordBuffer is allocated only once. The same buffer will be used for all devices. + // + if ( gHDDPasswordBuffer == NULL ) + { + Status = pBS->AllocatePool( EfiBootServicesData, + sizeof(HDD_PASSWORD), + (VOID**)&gHDDPasswordBuffer ); + + if ( EFI_ERROR( Status )) + { + return Status; + } + } + + if ( ModeFlag == FALSE ) + { + IdeBusInterface->IdeSecurityInterface = IdeSecurityInterface; + IdeSecurityInterface->BusInterface = IdeBusInterface; + } + else { + SataDevInterface->IdeSecurityInterface = IdeSecurityInterface; + IdeSecurityInterface->BusInterface = SataDevInterface; + } + + IdeSecurityInterface->ReturnSecurityStatus = ReturnSecurityStatus; + IdeSecurityInterface->SecuritySetPassword = SecuritySetPassword; + IdeSecurityInterface->SecurityUnlockPassword = SecurityUnlockPassword; + IdeSecurityInterface->SecurityDisablePassword = SecurityDisablePassword; + IdeSecurityInterface->SecurityFreezeLock = SecurityFreezeLock; + IdeSecurityInterface->SecurityEraseUnit = SecurityEraseUnit; + IdeSecurityInterface->ReturnIdePasswordFlags = ReturnIdePasswordFlags; + IdeSecurityInterface->pHDDPasswordBuffer = gHDDPasswordBuffer; + + // + // Set ModeFlag to FALSE if IdeBus else TRUE for Ahci Bus. + // + IdeSecurityInterface->ModeFlag = ModeFlag; // Ide Bus + + // + // Install the protocol on the device + // + Status = pBS->InstallMultipleProtocolInterfaces( + &IdeDeviceHandle, + &gSecurityModeProtocolGuid, IdeSecurityInterface, + NULL ); + + if ( gIDEBusEvtBootScript == NULL ) + { + // + // Create event for boot script + // + Status = CreateReadyToBootEvent( + TPL_CALLBACK, + IdeBusCallbackBootScript, + NULL, + &gIDEBusEvtBootScript + ); + ASSERT_EFI_ERROR( Status ); + } + + // + // Install the Readytoboot event to locate the AhciSMM protocol interface for IdeSmm driver. + // AhciSmm protocol is valid only on AHCI mode. Other mode Callback is not needed + // + if ((BootEvent == NULL) && (ModeFlag)) + { + + // Send data to SMM. + Status = pBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &gSmmCommunication); + if (EFI_ERROR(Status)) { + gSmmCommunication=NULL; + } + + // + // Create event for boot script + // + Status = CreateReadyToBootEvent( + TPL_CALLBACK, + LocateAhciSmmServiceEvent, + NULL, + &BootEvent + ); + ASSERT_EFI_ERROR( Status ); + } + + #if MASTER_PASSWORD_ENABLE + // + // Check if OEM_DEFAULT_MASTER_PASSWORD is enabled and + // DISPLAY_MASTER_PASSWORD is Disabled + // + Status = ReturnIdePasswordFlags( + (IDE_SECURITY_PROTOCOL*)IdeSecurityInterface, + &IdePasswordFlags + ); + + ASSERT_EFI_ERROR( Status ); + + if ((IdePasswordFlags & 0x0800) && (!(IdePasswordFlags & 0x0008))) + { + Status = OEMSetMasterPassword( + (IDE_SECURITY_PROTOCOL*)IdeSecurityInterface ); + ASSERT_EFI_ERROR( Status ); + } + #endif + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: StopSecurityModeSupport +// +// Description: Stops the security mode support by uninstalling the +// security interface. +// +// Input: +// IN VOID *BusInterface, +// IN BOOLEAN ModeFlag +// +// Output: +// EFI_SUCCESS : Security Mode supported +// EFI_DEVICE_ERROR : Not supported +// +// Referrals: ReturnSecurityStatus +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS StopSecurityModeSupport( + IN VOID *BusInterface, + IN BOOLEAN ModeFlag ) +{ + EFI_STATUS Status; + EFI_HANDLE IdeDeviceHandle; + SECURITY_PROTOCOL *IdeSecurityInterface; + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + if ( ModeFlag == FALSE ) + { + IdeSecurityInterface = IdeBusInterface->IdeSecurityInterface; + IdeDeviceHandle = IdeBusInterface->IdeDeviceHandle; + } + else { + IdeSecurityInterface = SataDevInterface->IdeSecurityInterface; + IdeDeviceHandle = SataDevInterface->IdeDeviceHandle; + } + + if ( IdeSecurityInterface == NULL ) + { + return EFI_SUCCESS; + } + + // + // Install Devicepath and BLOCK_IO on a new handle + // + Status = pBS->UninstallMultipleProtocolInterfaces( + IdeDeviceHandle, + &gSecurityModeProtocolGuid, + IdeSecurityInterface, + NULL ); + + if ( Status == EFI_SUCCESS ) + { + pBS->FreePool( IdeSecurityInterface ); + IdeSecurityInterface = NULL; + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: IdeBusCallbackBootScript +// +// Description: Saves the IDE registers in a boot script. +// +// Input: +// IN EFI_EVENT Event +// IN VOID *Context +// +// Output: +// None +// +// Referrals: SmmHDDPasswordInterface +// +// Notes: Will be called only if HDD loses power in S3 state. A SW SMI will +// be created during S3 resume, to unlock the HDD and put it in +// Freeze state. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IdeBusCallbackBootScript( + IN EFI_EVENT Event, + IN VOID *Context ) +{ + EFI_BOOT_SCRIPT_SAVE_PROTOCOL *BootScriptSave; + EFI_STATUS Status; + UINT8 Value = SW_SMI_HDD_UNLOCK_PASSWORD; + + + Status = pBS->LocateProtocol( + &gEfiBootScriptSaveGuid, + NULL, + &BootScriptSave + ); + + if ( EFI_ERROR( Status )) + { + return; + } + + BOOT_SCRIPT_S3_IO_WRITE_MACRO( + BootScriptSave, + EfiBootScriptWidthUint8, + SwSmiPort, + 1, + &Value + ); + + // + //Kill the Event + // + pBS->CloseEvent( Event ); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: IdeBusMiscSmmFeatureCallback +// +// Description: Saves the IDE registers in a boot script. +// +// Input: +// IN EFI_EVENT Event +// IN VOID *Context +// +// Output: +// None +// +// Referrals: SmmHDDPasswordInterface +// +// Notes: Will be called only if HDD is in AHCI Mode or SWSP is Disabled +// A SW SMI will be created during S3 resume, to Freeze the HDD in AHCI +// or Disable SWSP command through Set feature command is Issued. +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID IdeBusMiscSmmFeatureCallback( + IN EFI_EVENT Event, + IN VOID *Context ) +{ + EFI_BOOT_SCRIPT_SAVE_PROTOCOL *BootScriptSave; + EFI_STATUS Status; + UINT8 Value = SW_SMI_HDD_MISC_SMM_FEATURES; + + static BOOLEAN S3DataSaved = FALSE; + + if ( S3DataSaved ) + { + return; + } + + Status = pBS->LocateProtocol( + &gEfiBootScriptSaveGuid, + NULL, + &BootScriptSave + ); + + if ( EFI_ERROR( Status )) + { + return; + } + + BOOT_SCRIPT_S3_IO_WRITE_MACRO( + BootScriptSave, + EfiBootScriptWidthUint8, + SwSmiPort, + 1, + &Value + ); + + S3DataSaved = TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IdeSecurityEntryPoint +// +// Description: This function is the entry point for IDE SECURITY Driver. +// +// Input: +// EFI_HANDLE ImageHandle Image handle. +// EFI_SYSTEM_TABLE *SystemTable Pointer to the EFI system table. +// +// Output: +// EFI_SUCCESS Security interface installed. +// EFI_ERROR Security interface not installed or unable to locate +// some protocol. +// +// Notes: +// Entry Points are used to locate or install protocol interfaces and +// notification events. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS IdeSecurityEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable ) +{ + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + + InitAmiLib( ImageHandle, SystemTable ); + + Status = pBS->AllocatePool( EfiBootServicesData, + sizeof(HDD_SECURITY_INIT_PROTOCOL), + (VOID**)&gHddSecurityInitProtocol ); + + if ( EFI_ERROR( Status )) + { + return Status; + } + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + Status = pBS->LocateProtocol(&gEfiSmmControl2ProtocolGuid, NULL, &mSmmCtl); +#else + Status = pBS->LocateProtocol(&gEfiSmmControlProtocolGuid, NULL, &mSmmCtl); +#endif + + if ( EFI_ERROR( Status )) { + return EFI_UNSUPPORTED; + } + + gHddSecurityInitProtocol->InstallSecurityInterface + = InstallSecurityInterface; + gHddSecurityInitProtocol->StopSecurityModeSupport + = StopSecurityModeSupport; + + Status = pBS->InstallProtocolInterface( + &Handle, + &gHddSecurityInitProtocolGuid, + EFI_NATIVE_INTERFACE, + gHddSecurityInitProtocol + ); + ASSERT_EFI_ERROR( Status ); + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: ReturnSecurityStatus +// +// Description: Returns whether the Device supports Security Mode or not. +// If supported, the current status of the device is returned. +// Security status information will be retrieved from buffer +// updated by IDENTIFY DEVICE(Command Code : 0xEC) command. +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// UINT16 *SecurityStatus +// +// Output: +// EFI_SUCCESS : Security Mode supported +// EFI_UNSUPPORTED : Not supported +// +// UINT16 *SecurityStatus +// Bit 0 : Security Supported +// Bit 1 : Security Enabled +// Bit 2 : Security Locked +// Bit 3 : Security Frozen +// Bit 4 : Security Count Expired +// Bit 5 : Enhanced Security Erase supported +// Bit 6 : Enhanced Security Erase supported +// Bit 8 : Security Level 0:High, 1:Maximum +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS ReturnSecurityStatus( + IN IDE_SECURITY_PROTOCOL *This, + UINT16 *SecurityStatus ) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + IDENTIFY_DATA IdentifyData; + VOID *BusInterface + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag = ((SECURITY_PROTOCOL* )This)->ModeFlag; + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + if ( ModeFlag == FALSE ) + { + IdentifyData = IdeBusInterface->IdeDevice.IdentifyData; + } + else { + IdentifyData = SataDevInterface->IdentifyData; + } + + // + // Check if Word 82 Bit 1 is set + // + if ( IdentifyData.Command_Set_Supported_82 & 0x2 ) + { + Status = EFI_SUCCESS; + *SecurityStatus = IdentifyData.Security_Status_128; + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SecuritySetPassword +// +// Description: Sets User/Master Password using SECURITY_SET_PASSWORD +// (Commnd Code : 0xF1) security command. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// UINT16 Control, +// UINT8 *Buffer (32 Bytes) +// UINT8 RevisionCode (Valid when Control +// Bit 0 = 1 of Master Password) +// +// Control : Bit 0 : 0/1 User/Master Password +// Bit 8 : 0/1 High/Maximum Security level +// +// Output: +// EFI_SUCCESS : Password set. +// EFI_ERROR : Error in setting Password. +// +// Notes: +// 1. Buffer should be 32 bytes long (Mandatory). Even if Password is not 32 +// bytes long,pad it with zeros to create a buffer of 32 bytes. +// 2. If a MasterPassword with a valid Revision code(0x0001 through 0xFFFE) +// already exists, a new MasterPassword with a different revisioncode +// cannot be installed.MasterPassword needs to be unlocked, disabled and +// then a new password can be installed. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SecuritySetPassword( + IN IDE_SECURITY_PROTOCOL *This, + UINT16 Control, + UINT8 *Buffer, + UINT16 RevisionCode ) +{ + EFI_STATUS Status; + + #if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM + UINT32 HddDataId = 0; + UINT16 UserMaster = 0; + #endif + UINT16 Temp = 1; + + VOID *BusInterface + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag = ((SECURITY_PROTOCOL* )This)->ModeFlag; + IDENTIFY_DATA IdentifyData; + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + Control &= 0x0101; // Bit0 and Bit 8 are valid + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + if ( ModeFlag == FALSE ) + { + IdentifyData = IdeBusInterface->IdeDevice.IdentifyData; + } + else { + IdentifyData = SataDevInterface->IdentifyData; + } + + if ((Control & 1) && (RevisionCode == 0)) + { + RevisionCode = DEFAULT_MASTER_PASSWORD_REVISION; + + #if MASTER_PASSWORD_REVISION_SWITCH == 1 + RevisionCode = CHANGED_MASTER_PASSWORD_REVISION; + #endif + + #if MASTER_PASSWORD_REVISION_SWITCH == 2 + Temp = (IdentifyData.Master_Password_Rev_92)++; + + if ((Temp == 0) || (Temp == 0xFFFF)) + { + Temp++; + + if ( Temp == 0xFFFF ) + { + Temp++; + } + } + RevisionCode = Temp; + #endif + + if ( RevisionCode == DISABLED_MASTER_PASSWORD_REVISION ) + { + RevisionCode++; + + if ((RevisionCode == 0) || (RevisionCode == 0xFFFF)) + { + RevisionCode++; + + if ( RevisionCode == 0xFFFF ) + { + RevisionCode++; + } + } + } + } + + Status = SecurityCommonRoutine( + BusInterface, + Control, + Buffer, + SECURITY_SET_PASSWORD, + RevisionCode, + ModeFlag + ); + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + // + // If Password is set successfully, save it. + // + if ( !EFI_ERROR( Status )) + { + if(!(Control & 1)) { + SmmHDDPasswordInterface( This, + Control, + Buffer, + SW_SMI_HDD_PASSWORD_SAVE ); + } + + #if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM + Status = GatherIdeInfo( BusInterface, ModeFlag, &HddDataId ); + ASSERT_EFI_ERROR( Status ); + + Status = SetHddSecDataInNvram( BusInterface, + &HddDataId, + Control, + Buffer ); + ASSERT_EFI_ERROR( Status ); + #endif + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SecurityUnlockPassword +// +// Description: Unlocks the devices for media access using +// SECURITY_UNLOCK(Command Code : 0xF2) security command. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// UINT16 Control, +// UINT8 *Buffer (32 Bytes). +// +// Control : Bit 0 : 0/1 User/Master Password +// Buffer : Pointer to password buffer which will be used to unlock the +// drive. +// +// Output: +// EFI_SUCCESS : Hard disk is unlocked. +// EFI_DEVICE_ERROR : Failed to unlock the drive. +// +// Notes: +// 1. Buffer should be 32 bytes long (Mandatory). Even if Password is not +// 32 bytes long, pad it with zeros to create a buffer of 32 bytes. +// 2. If the password compare fails then the device returns command aborted +// to the host and decrements the unlock counter. This counter is initially +// set to five and is decremented for each password mismatch when SECURITY +// UNLOCK is issued and the device is locked. When this counter reaches +// zero then SECURITY UNLOCK and SECURITY ERASE UNIT commands are command +// aborted until a power-on reset or a hardware reset.SECURITY UNLOCK +// commands issued when the device is unlocked have no effect on the unlock +// counter. +// 3. SECURITY_DISABLE_PASSWORD and SECURITY_SET_PASSWORD commands used when +// security password is set and HDD is in unlocked state. This is done to +// have consistency of output from this function. +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SecurityUnlockPassword( + IN IDE_SECURITY_PROTOCOL *This, + UINT16 Control, + UINT8 *Buffer ) +{ + EFI_STATUS Status; + + #if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM + UINT32 HddDataId = 0; + UINT16 UserMaster = 0; + #endif + UINT16 RevisionCode = 0; + EFI_STATUS Status1; + VOID *BusInterface \ + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag \ + = ((SECURITY_PROTOCOL* )This)->ModeFlag; + UINT16 SecurityStatus = 0; + #if MASTER_PASSWORD_ENABLE + UINT32 IdePasswordFlags = 0; + #endif + + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + Status = ReturnSecurityStatus( This, &SecurityStatus ); + + Control &= 0x1; // Bit0 is valid + // + // When in Setup, Current Password is prompted for consistency when Setting a New Password + // Or Disabling the Existing Password. Follow a Special Path only in this case. + //*****This Case Applies on only when (1)Password is Set & Security Enabled + // (2)Unlocked + + + if ((SecurityStatus & BIT01) && (!(SecurityStatus & BIT02))) + { + if ( !(Control & 1)) + { + // + // (a)For Changing or Clearing User Password. + // 1.Send a disable Password Command from the String Obtained from user. + // 2.If Success Set the Password Same Password. + // 3.Suitable if Logged in as Both User or Master + // + Status = SecurityCommonRoutine( + BusInterface, + Control, + Buffer, + SECURITY_DISABLE_PASSWORD, + 0, + ModeFlag + ); + + if ( !EFI_ERROR( Status )) + { + SecurityCommonRoutine( + BusInterface, + Control, + Buffer, + SECURITY_SET_PASSWORD, + RevisionCode, + ModeFlag + ); + } + return Status; + } + + } + + Status = SecurityCommonRoutine( + BusInterface, + Control, + Buffer, + SECURITY_UNLOCK, + 0, + ModeFlag + ); + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + if ( !EFI_ERROR( Status )) + { + // + // Save the Password if unlocked Successfully. + // + SmmHDDPasswordInterface( This, + Control, + Buffer, + SW_SMI_HDD_PASSWORD_SAVE ); + + #if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM + Status = GatherIdeInfo( BusInterface, ModeFlag, &HddDataId ); + ASSERT_EFI_ERROR( Status ); + + Status = SetHddSecDataInNvram( BusInterface, + &HddDataId, + Control, + Buffer ); + ASSERT_EFI_ERROR( Status ); + #endif + + // + // After unlock the HDD set the OEM default master password + // Check if OEM_DEFAULT_MASTER_PASSWORD is enabled and + // DISPLAY_MASTER_PASSWORD is Disabled. + // + #if MASTER_PASSWORD_ENABLE + Status = ReturnIdePasswordFlags( This, &IdePasswordFlags ); + ASSERT_EFI_ERROR( Status ); + + if ((IdePasswordFlags & 0x0800) && (!(IdePasswordFlags & 0x0008))) + { + Status = OEMSetMasterPassword( This ); + ASSERT_EFI_ERROR( Status ); + } + #endif + + if ( ModeFlag == FALSE ) { + + // + // Check if BlockIO Protocol is already present on this device. + // + Status1 = pBS->HandleProtocol(IdeBusInterface->IdeDeviceHandle, + &gEfiBlockIoProtocolGuid, + &BlockIo + ); + + // + // Connect only if BloCkIO protocol is not installed on the device. + // + if ( EFI_ERROR( Status1 )) { + #if EFI_IDE_PROTOCOL || INTEL_IDE_PROTOCOL + pBS->ConnectController( + IdeBusInterface->IdeControllerInterfaceHandle, + NULL, + NULL, + TRUE + ); + #else + pBS->ConnectController( + IdeBusInterface->IdeControllerInterface->ControllerHandle, + NULL, + NULL, + TRUE + ); + #endif + } + } + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SecurityDisablePassword +// +// Description: Disables Password authentification before media access. +// SECURITY_DISABLE_PASSWORD(Command Code : 0xF6) security +// command is used to remove the user password. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// UINT16 Control, +// UINT8 *Buffer (32 Bytes) +// +// Control : Bit 0 : 0/1 User/Master Password +// +// Buffer : Pointer to password buffer which will be used to when sending +// SECURITY_DISABLE_PASSWORD command. +// +// +// Output: +// EFI_SUCCESS : Security mode feature disabled. +// EFI_DEVICE_ERROR : Security command failed. +// +// Notes: +// 1. Buffer should be 32 bytes long (Mandatory). Even if Password is not +// 32 bytes long,pad it with zeros to create a buffer of 32 bytes. +// 2. Password should be unlocked before disabling it. +// 3. SECURITY_DISABLE_PASSWORD command does not change the Master password +// that may be reactivated later by setting a User password. +// 4. Normal erase mode is selected, the SECURITY ERASE UNIT command writes +// binary zeroes to all user data areas. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SecurityDisablePassword( + IN IDE_SECURITY_PROTOCOL *This, + UINT16 Control, + UINT8 *Buffer ) +{ + EFI_STATUS Status; + VOID *BusInterface \ + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag \ + = ((SECURITY_PROTOCOL* )This)->ModeFlag; + + #if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM + UINT32 HddDataId = 0; + UINT8 EmptyBuffer[IDE_PASSWORD_LENGTH]; + #endif + + Control &= 0x1; // Bit0 is valid + + #if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM + // + //Update the Nvram buffer with NULL string. + // + pBS->SetMem( EmptyBuffer, IDE_PASSWORD_LENGTH, 0 ); + + Status = GatherIdeInfo( BusInterface, ModeFlag, &HddDataId ); + ASSERT_EFI_ERROR( Status ); + + Status = SetHddSecDataInNvram( BusInterface, &HddDataId, Control, EmptyBuffer ); + ASSERT_EFI_ERROR( Status ); + #endif + + Status = SecurityCommonRoutine( BusInterface, + Control, + Buffer, + SECURITY_DISABLE_PASSWORD, + 0, + ModeFlag + ); + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + if ( !EFI_ERROR( Status )) + { + SmmHDDPasswordInterface( This, + Control, + Buffer, + SW_SMI_HDD_PASSWORD_REMOVE ); + } + + // + // If the Empty string entered for the master password, Set the OEM + // disable password with Disabled revision code. + // + if ( Control & 01 ) + { + EFI_STATUS DefaultStatus; + DefaultStatus = SetDefaultMasterPassword( This ); + ASSERT_EFI_ERROR( DefaultStatus ); + } + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SetDefaultMasterPassword +// +// Description: Sets the Default Password String provided by OEM as +// Master Password. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This +// +// Output: +// EFI_SUCCESS : Default master password is set. +// EFI_ERROR : Default master password is not set. +// +// Notes: +// DEFAULT_MASTER_PASSWORD_TAG token string will be set as master password. +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SetDefaultMasterPassword( + IN IDE_SECURITY_PROTOCOL *This ) +{ + EFI_STATUS Status; + UINT8 Buffer[IDE_PASSWORD_LENGTH]; + UINT16 Control = 1; + UINT16 RevisionCode = DISABLED_MASTER_PASSWORD_REVISION; + UINTN i; + UINT16 SecurityStatus = 0; + + MemSet( &Buffer, IDE_PASSWORD_LENGTH, 0 ); + + for ( i = 0; i < IDE_PASSWORD_LENGTH; i++ ) + { + Buffer[i] = (UINT8)sDefaultMasterPasswordTag[i]; + + if ( sDefaultMasterPasswordTag[i] == L'\0' ) + { + break; + } + } + // + // Set the OEM master password if the HDD is not in Frozen or locked state. + // + Status = ReturnSecurityStatus( This, &SecurityStatus ); + + if ( !((SecurityStatus & 0x04) || (SecurityStatus & 0x08))) + { + Status = SecuritySetDefaultMasterPassword( This, + Control, + Buffer, + RevisionCode ); + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SecuritySetDefaultMasterPassword +// +// Description: Sets default Master Password with disabled revision code. +// SECURITY_SET_PASSWORD(Command code : 0xF1) security command +// used to set default master password. +// +// Input: +// IN IDE_BUS_PROTOCOL *This, +// UINT16 Control, +// UINT8 *Buffer (32 Bytes) +// UINT8 RevisionCode (Valid when +// Control Bit 0 = 1 of Master Password) +// +// Control : Bit 0 : 0/1 User/Master Password +// Bit 8 : 0/1 High/Maximum Security level +// +// Output: +// EFI_SUCCESS : Password set +// EFI_ERROR : Error in setting Password +// +// Notes: +// 1. Buffer should be 32 bytes long (Mandatory). Even if Password is not +// 32 bytes long,pad it with zeros to create a buffer of 32 bytes. +// +// 2. If a MasterPassword with a valid Revision code already exists, a new +// MasterPassword with a different revisioncode cannot be installed. +// MasterPassword needs to be unlocked, disabled and then a new password +// can be installed. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SecuritySetDefaultMasterPassword( + IN IDE_SECURITY_PROTOCOL *This, + UINT16 Control, + UINT8 *Buffer, + UINT16 RevisionCode ) +{ + VOID *BusInterface = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag = ((SECURITY_PROTOCOL* )This)->ModeFlag; + EFI_STATUS Status; + + #if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM + UINT32 HddDataId = 0; + UINT16 UserMaster = 0; + #endif + + Control &= 0x0101; // Bit0 and Bit 8 are valid + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + Status = SecurityCommonRoutine( + BusInterface, + Control, + Buffer, + SECURITY_SET_PASSWORD, + RevisionCode, + ModeFlag + ); + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + // + // If Password is set successfully, save it. + // + if ( !EFI_ERROR( Status )) + { + SmmHDDPasswordInterface( + This, + Control, + Buffer, + SW_SMI_HDD_PASSWORD_SAVE + ); + + #if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM + Status = GatherIdeInfo( BusInterface, ModeFlag, &HddDataId ); + ASSERT_EFI_ERROR( Status ); + + Status = SetHddSecDataInNvram( BusInterface, + &HddDataId, + Control, + Buffer ); + ASSERT_EFI_ERROR( Status ); + #endif + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SecurityFreezeLock +// +// Description: Prevents any further alteration of security status on the +// device leaving the hard disk in Frozen mode. Frozen mode is +// disabled by power-off or hardware reset. SECURITY_FREEZE_LOCK +// (Command Code : 0xF5)security command is used to freeze hard disk. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// +// Output: +// EFI_SUCCESS : Hard disk is successdully kept in FROZEN state. +// EFI_ERROR : Security Freeze command failed. +// +// Notes: +// Commands disabled by SECURITY FREEZE LOCK are: +// - SECURITY SET PASSWORD +// - SECURITY UNLOCK +// - SECURITY DISABLE PASSWORD +// - SECURITY ERASE PREPARE +// - SECURITY ERASE UNIT +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SecurityFreezeLock( + IN IDE_SECURITY_PROTOCOL *This ) +{ + EFI_STATUS Status; + VOID *BusInterface + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag + = ((SECURITY_PROTOCOL* )This)->ModeFlag; + UINT16 SecurityStatus = 0; + + COMMAND_STRUCTURE CommandStructure; +#if !DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT + IDENTIFY_DATA IdentifyData; +#endif + + Status=ReturnSecurityStatus( This, &SecurityStatus ); + if(EFI_ERROR(Status)) { + return Status; + } + + // Freeze Lock command will not work with the HDD is in Locked State. + // So return with success if the HDD is locked state or already frozen state + if ( SecurityStatus & 0xc ) { + return EFI_SUCCESS; + } + + ZeroMemory( &CommandStructure, sizeof(COMMAND_STRUCTURE)); + CommandStructure.Command = SECURITY_FREEZE_LOCK; + +#if !DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT + if ( ModeFlag == FALSE ) { + IdentifyData = ((IDE_BUS_PROTOCOL*)BusInterface)->IdeDevice.IdentifyData; + } else { + IdentifyData = ((SATA_DEVICE_INTERFACE*)BusInterface)->IdentifyData; + } + if ( SecurityStatus & 2 ) + { + if ( IdentifyData.Reserved_76_79[3] & 0x0040 ) + { + Status = TransferPwDataFromNvramToSmram( This ); + ASSERT_EFI_ERROR( Status ); + } + } +#endif + + Status = CommonNonDataHook( BusInterface, + CommandStructure, + ModeFlag ); + ASSERT_EFI_ERROR (Status); + CommandStructure.Features = DEV_CONFIG_FREEZE_LOCK_FEATURES; + CommandStructure.Command = DEV_CONFIG_FREEZE_LOCK; + Status = CommonNonDataHook( BusInterface, + CommandStructure, + ModeFlag ); + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SecurityEraseUnit +// +// Description: Erases the Device content.SECURITY_ERASE_UNIT +// (Command code : 0xF4) security command is used for device +// erasing. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// UINT16 Control, +// UINT8 *Buffer +// +// Control : Bit 0 : 0/1 User/Master Password +// Bit 1 : 0/1 Normal Erase/ Enhanced Erase +// Buffer : Pointer to password buffer which will be used to when sending +// SECURITY_ERASE_UNIT command. +// +// Output: +// EFI_SUCCESS : Successfull completion of Erase command. +// EFI_DEVICE_ERROR : EraseUnit command failed to complete. +// +// Notes: +// If a device is locked with USER PASSWORD and Maximum security level set +// then only way to unlock the device with MASTER password is to erase the +// contents of the device. +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SecurityEraseUnit( + IN IDE_SECURITY_PROTOCOL *This, + UINT16 Control, + UINT8 *Buffer ) +{ + EFI_STATUS Status; + + VOID *BusInterface \ + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag \ + = ((SECURITY_PROTOCOL* )This)->ModeFlag; + COMMAND_STRUCTURE CommandStructure; + + ZeroMemory( &CommandStructure, sizeof(COMMAND_STRUCTURE)); + CommandStructure.Command = SECURITY_ERASE_PREPARE; + + Status = CommonNonDataHook( BusInterface, CommandStructure, ModeFlag ); + + // + // Issue Security Erase Unit + // + Control &= 0x3; // Bit0 and Bit 1 is valid + Status = SecurityCommonRoutine( + BusInterface, + Control, + Buffer, + SECURITY_ERASE_UNIT, + 0, + ModeFlag + ); + + // + // Update the Identify device buffer + // + UpdateIdentifyData( BusInterface, ModeFlag ); + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: ReturnIdePasswordFlags +// +// Description: Returns Ide Password Variables and Flags. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// UINT32 *IdePasswordFlags +// +// Output: +// EFI_SUCCESS : IDEPassword Status Flag is returned in IdePasswordFlags. +// EFI_ERROR : Error while retrieving the SecurityStatus. +// +// +// Referrals: +// +// IdePasswordFlags: +// **TBD Only Bit0, Bit03, Bit11, Bit16, Bit17 are Supported Currently +// +// BIT0 User Password Support; +// BIT1 Master Password Support; +// BIT2 Display User Password; +// BIT3 Display Master Password; +// BIT4 Display User Password Status; +// BIT5 Display Master Password Status; +// BIT6 Freeze Lock Hdds; +// BIT7 Single User Password; +// BIT8 Single Master Password; +// BIT9 System User Password as Hdd User Password; +// BIT10 System Admin Password as Hdd Master Password; +// BIT11 OEM Default Master Password +// BIT12 Prompt for User Password in Post +// BIT13 Prompt for Master Password in Post +// BIT14 Display Security Status in Setup +// BIT15 DUMMY Security Token. +// BIT16 MasterPassword Set Status. +// BIT17 UserPassword Set Status. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS ReturnIdePasswordFlags( + IN IDE_SECURITY_PROTOCOL *This, + UINT32 *IdePasswordFlags ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 Temp = 0; + UINT16 MasterPwdRev = 0; + UINT16 SecurityStatus = 0; + VOID *BusInterface + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag + = ((SECURITY_PROTOCOL* )This)->ModeFlag; + IDENTIFY_DATA IdentifyData; + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + if ( ModeFlag == FALSE ) + { + IdentifyData = IdeBusInterface->IdeDevice.IdentifyData; + } + else { + IdentifyData = SataDevInterface->IdentifyData; + } + + + + #if MASTER_PASSWORD_ENABLE + Temp |= BIT01; + #endif + + + #if DISPLAY_MASTER_PASSWORD + Temp |= BIT03; + #endif + + #if OEM_DEFAULT_MASTER_PASSWORD + Temp |= BIT11; + #endif + + + MasterPwdRev = IdentifyData.Master_Password_Rev_92; + + if ((MasterPwdRev != 0x0000) && (MasterPwdRev != 0xFFFF) \ + && (MasterPwdRev != DISABLED_MASTER_PASSWORD_REVISION)) + { + Temp |= BIT16; + } + + Status = ReturnSecurityStatus( This, &SecurityStatus ); + + if ( EFI_ERROR( Status )) + { + return Status; + } + + if ( SecurityStatus & BIT01 ) + { + Temp |= BIT17; + } + + *IdePasswordFlags = (UINT32)Temp; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SecurityCommonRoutine +// +// Description: This is common security routine which will be called from +// security routines. It is from this routine most of the security +// commands are sent to the drive. +// +// Input: +// IN VOID *BusInterface, +// UINT16 Control, +// UINT8 *Buffer (32 Bytes), +// UINT8 SecurityCommand +// UINT8 RevisionCode +// (Valid for Master password) +// +// Control : Bit 0 : 0/1 User/Master Password +// Bit 1 : 0/1 Normal/Enhanced Erase +// Bit 8 : 0/1 High/Maximum Security level +// +// Buffer : Pointer to password buffer which will be used to when sending +// SecurityCommand. +// +// +// Output: +// EFI_STATUS : EFI_SUCCESS/EFI_DEVICE_ERROR +// +// Notes: +// 1. Buffer should be 32 bytes long (Mandatory). Even if Password is not +// 32 bytes long, pad it with zeros to create a buffer of 32 bytes. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SecurityCommonRoutine( + IN VOID *BusInterface, + UINT16 Control, + UINT8 *Buffer, + UINT8 SecurityCommand, + UINT16 RevisionCode, + BOOLEAN ModeFlag ) +{ + EFI_STATUS Status; + UINT16 *SecurityBuffer; + + // + // Allocate 512 Bytes + // + Status = pBS->AllocatePool( EfiBootServicesData, + SECURITY_BUFFER_LENGTH, + (VOID**)&SecurityBuffer ); + + if ( EFI_ERROR( Status )) + { + return Status; + } + + // + // Clear the Buffer + // + ZeroMemory( SecurityBuffer, SECURITY_BUFFER_LENGTH ); + + SecurityBuffer[0] = Control; + + // + // Copy 32 Bytes + // + pBS->CopyMem( &(SecurityBuffer[1]), Buffer, IDE_PASSWORD_LENGTH ); + + // + // If Security Set password command is for Master, then update the + // revision code. + // + if ((SecurityCommand == SECURITY_SET_PASSWORD) & (Control & 1)) + { + if ((RevisionCode != 0) || (RevisionCode != 0xFFFF)) + { + SecurityBuffer[17] = RevisionCode; + } + } + + // + // Write 512 Bytes + // + Status = CommonReadWritePioHook( + BusInterface, + SecurityBuffer, + SECURITY_BUFFER_LENGTH, + 0, + SecurityCommand, + TRUE, + ModeFlag + ); + + pBS->FreePool( SecurityBuffer ); + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmHDDPasswordInterface +// +// Description: Manages HDD Password in SMM area. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// UINT16 Control, +// UINT8 *Buffer +// UINT8 Action +// +// +// Control : Bit 0 : 0/1 User/Master Password +// +// Buffer : Pointer to password buffer which will be used to when sending +// SecurityCommand. +// +// Output: +// EFI_SUCCESS : Password saved which will be used to unlock the drive +// during S3 resume. +// EFI_DEVICE_ERROR : Error in saving Password. +// +// Notes: +// 1. Buffer should be 32 bytes long (Mandatory). Even if Password is not +// 32 bytes long, pad it with zeros to create a buffer of 32 bytes. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmHDDPasswordInterface( + IN IDE_SECURITY_PROTOCOL *This, + UINT16 Control, + UINT8 *Buffer, + UINT8 Action ) +{ +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + UINT8 DataSize = 1; +#else + UINTN DataSize = 1; +#endif + UINT8 SwSmiValue = Action; + UINTN i; + HDD_PASSWORD *HDDPasswordBuffer = gHDDPasswordBuffer; + VOID *BusInterface \ + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag \ + = ((SECURITY_PROTOCOL* )This)->ModeFlag; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN SegNum; + UINTN BusNum; + UINTN DevNum; + UINTN FuncNum; + EFI_STATUS Status; + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010014) + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicationHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(HDD_PASSWORD)]; + UINTN CommBufferSize; +#endif + + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + if ( ModeFlag == FALSE ) + { + // + // If HDD is not going to lose power in S3, no need to unlock password and put it in + // Freeze state during S3 resume. + // + if ( !(IdeBusInterface->IdeBusInitInterface->Flags \ + & S3_RESUME_UNLOCK_HDD_PASSWORD)) + { + return EFI_SUCCESS; + } + + HDDPasswordBuffer->BaseAddress + = IdeBusInterface->IdeDevice.Regs.CommandBlock.DataReg; + HDDPasswordBuffer->Device = IdeBusInterface->IdeDevice.Device; + HDDPasswordBuffer->DeviceControlReg + = IdeBusInterface->IdeDevice.Regs.ControlBlock.DeviceControlReg; + PciIo = IdeBusInterface->PciIO; + + } + else { + + PciIo=SataDevInterface->AhciBusInterface->PciIO; + HDDPasswordBuffer->PortNumber = SataDevInterface->PortNumber; + HDDPasswordBuffer->PMPortNumber = SataDevInterface->PMPortNumber; + } + + // + // Get PCI Bus/Device/Function number + // + Status = PciIo->GetLocation ( PciIo, + &SegNum, + &BusNum, + &DevNum, + &FuncNum + ); + + // + // Save it for IdeSmm to initilize the controller. + // + HDDPasswordBuffer->BusNo=(UINT8)BusNum; + HDDPasswordBuffer->DeviceNo=(UINT8)DevNum; + HDDPasswordBuffer->FunctionNo=(UINT8)FuncNum; + + HDDPasswordBuffer->Signature = '$HDD'; // 0x44444824; // + HDDPasswordBuffer->Control = Control; + HDDPasswordBuffer->ModeFlag = ModeFlag; + + // + // HDDPasswordBuffer->RevisionCode = RevisionCode; + // + if ( Control & 0x01 ) + { + for ( i = 0; i < sizeof (HDDPasswordBuffer->MasterPassword); i++ ) + { + HDDPasswordBuffer->MasterPassword[i] = Buffer[i]; + } // end of for + } + else { + for ( i = 0; i < sizeof (HDDPasswordBuffer->UserPassword); i++ ) + { + HDDPasswordBuffer->UserPassword[i] = Buffer[i]; + } // end of for + } + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010014) + + if(!gSmmCommunication) { + Status = pBS->LocateProtocol ( + &gEfiSmmCommunicationProtocolGuid, + NULL, + (VOID **)&gSmmCommunication + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + + SmmCommunicationHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; + + if(SwSmiValue == SW_SMI_HDD_PASSWORD_SAVE) { + pBS->CopyMem( &SmmCommunicationHeader->HeaderGuid, &gSaveHddPasswordGuid, sizeof( EFI_GUID ) ); + } else if( SwSmiValue == SW_SMI_HDD_PASSWORD_REMOVE ) { + pBS->CopyMem( &SmmCommunicationHeader->HeaderGuid, &gRemoveHddPasswordGuid, sizeof( EFI_GUID ) ); + } else { + // Unknown SwSmiValue + return EFI_UNSUPPORTED; + } + + SmmCommunicationHeader->MessageLength = sizeof(HDD_PASSWORD); + pBS->CopyMem( &SmmCommunicationHeader->Data, HDDPasswordBuffer, sizeof(HDD_PASSWORD) ); + + CommBufferSize = sizeof(CommBuffer); + Status = gSmmCommunication->Communicate (gSmmCommunication, &CommBuffer[0], &CommBufferSize); +#else + // Now Generate a SW SMI to log this data + mSmmCtl->Trigger( mSmmCtl, &SwSmiValue, &DataSize, 0, 0 ); +#endif + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: UpdateIdentifyData +// +// Description: Updates Identify command data.IDENTIFY_DATA(Command Code: 0xEC) +// command used to update the Identifydata buffer. +// +// Input: +// IN IDE_BUS_PROTOCOL *IdeBusInterface, +// IN BOOLEAN ModeFlag +// +// Output: +// EFI_SUCCESS : Identifydata updated successfully. +// EFI_ERROR : Failed to update the identifydata. +// +// Notes: ATA/ATAPI device type should have beeen known already. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS UpdateIdentifyData( + IN IDE_BUS_PROTOCOL *BusInterface, + IN BOOLEAN ModeFlag ) +{ + EFI_STATUS Status; + COMMAND_STRUCTURE CommandStructure; + + ZeroMemory( &CommandStructure, sizeof(COMMAND_STRUCTURE)); + + CommandStructure.ByteCount = sizeof(IDENTIFY_DATA); + CommandStructure.Command = IDENTIFY_COMMAND; + + Status = CommonPioDataHook( BusInterface, CommandStructure, ModeFlag ); + + return Status; +} + +#if MASTER_PASSWORD_ENABLE +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OEMSetMasterPassword +// +// Description: Sets the Default Password String provided by OEM as +// Master Password. SECURITY_SET_PASSWORD(Command Code : 0xF1) +// security command is used to set the master password. +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// +// Output: +// EFI_SUCCESS : OEM Master password set successfully. +// EFI_ERROR : Failed to set OEM Master passord to the hard disk. +// +// Notes: +// OEM_MASTER_PASSWORD_TAG token string will be set as oem master password. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OEMSetMasterPassword( + IN IDE_SECURITY_PROTOCOL *This ) +{ + EFI_STATUS Status = 0; + UINT8 Buffer[IDE_PASSWORD_LENGTH]; + UINT16 Control = 1; + UINT16 RevisionCode = 0xFFFE; + UINTN i; + UINT16 SecurityStatus = 0; + + MemSet( &Buffer, IDE_PASSWORD_LENGTH, 0 ); + + for ( i = 0; i < IDE_PASSWORD_LENGTH; i++ ) + { + Buffer[i] = (UINT8)sOemMasterPasswordTag[i]; + +#if defined SETUP_PASSWORD_NON_CASE_SENSITIVE && SETUP_PASSWORD_NON_CASE_SENSITIVE + Buffer[i] = ((Buffer[i]>='a')&&(Buffer[i]<='z'))?(Buffer[i]+'A'-'a'):Buffer[i]; +#endif + if ( sOemMasterPasswordTag[i] == L'\0' ) + { + break; + } + } + + // + //Set the OEM master password if the HDD is not in Frozen or locked state. + // + ReturnSecurityStatus( This, &SecurityStatus ); + + if ( !((SecurityStatus & 0x04) || (SecurityStatus & 0x08))) + { + Status = SecuritySetPassword( This, Control, Buffer, RevisionCode ); + } + + return Status; +} + +#endif + +#if (!DISABLE_SOFT_SET_PREV && !FORCE_HDD_PASSWORD_PROMPT ) || HDD_PASSWORD_ON_NVRAM +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GatherIdeInfo +// +// Description: Gathers Ide Device's Bus,Func,Device & PM/PS/SM/SS Info. +// +// Input: +// IN VOID *BusInterface, +// OUT UINT32 *HddDataId +// +// Output: +// EFI_SUCCESS : IDE info retrieved successfully. +// EFI_ERROR : Failed to get IDE info. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GatherIdeInfo( + IN VOID *BusInterface, + BOOLEAN ModeFlag, + OUT UINT32 *HddDataId ) +{ + EFI_STATUS Status; + UINTN SegNum; + UINTN BusNum; + UINTN DevNum; + UINTN FuncNum; + UINT16 wBDF; + UINT16 wPortPMModeFlag; + UINT8 ChannelorPort; + UINT8 DeviceorPMPort; + EFI_PCI_IO_PROTOCOL *PciIo; + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + if ( ModeFlag == FALSE ) + { + PciIo = IdeBusInterface->PciIO; + ChannelorPort = IdeBusInterface->IdeDevice.Channel; + DeviceorPMPort = IdeBusInterface->IdeDevice.Device; + } + else { + PciIo = SataDevInterface->AhciBusInterface->PciIO; + ChannelorPort = SataDevInterface->PortNumber; + DeviceorPMPort = SataDevInterface->PMPortNumber; + } + + Status = PciIo->GetLocation( PciIo, &SegNum, &BusNum, &DevNum, &FuncNum ); + + wBDF = (UINT16)((BusNum << 8) | (DevNum << 3) | FuncNum ); + wPortPMModeFlag = (UINT16)((ChannelorPort << 12) \ + | (DeviceorPMPort << 4) \ + | ((UINT8)ModeFlag)); + + *HddDataId = (UINT32)(((UINT16)wBDF << 16) + ((UINT16)wPortPMModeFlag)); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SetHddSecDataInNvram +// +// Description: Sets Hdd Security Data in NVRAM Area. +// +// Input: +// IN VOID *BusInterface, +// UINT32 *HddDataId +// UINT16 Control, +// UINT8 *Buffer +// +// Control : Bit 0 : 0/1 User/Master Password +// +// Buffer : Pointer to password buffer which will be used to when sending +// SecurityCommand. +// Output: +// EFI_SUCCESS : HDDPassword saved in NVram which later will be transfered to +// SMRAM. +// EFI_ERROR : Failed to save the HDD password in nvram. +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SetHddSecDataInNvram( + IN VOID *BusInterface, + UINT32 *HddDataId, + UINT16 Control, + UINT8 *Buffer ) +{ + EFI_STATUS Status; + HDDSECDATA *HddSecData=NULL; + UINTN i; + CHAR16 *HddSecutiyData = NULL; + UINT8 CryptBuffer[IDE_PASSWORD_LENGTH]; + UINTN HddSecDataSize = sizeof (HDDSECDATA); + UINT32 ParseIndex; + UINT32 Attribute = 0; + + pBS->AllocatePool( EfiBootServicesData, sizeof (HDDSECDATA), &HddSecData ); + pBS->SetMem( HddSecData, sizeof(HDDSECDATA), 0 ); + pBS->AllocatePool( EfiBootServicesData, + IDE_PASSWORD_LENGTH, + &HddSecutiyData ); + pBS->SetMem( HddSecutiyData, IDE_PASSWORD_LENGTH, 0 ); + ConvertHddDataIdToString( *HddDataId, HddSecutiyData ); + + // + // Get the password variable so that other password will be + // maintained in the nvram variable. + // + Status = pRS->GetVariable( + HddSecutiyData, + &gIdeSecurityPwNvguid, + &Attribute, + &HddSecDataSize, + HddSecData + ); + + if ( EFI_ERROR( Status )) + { + pBS->SetMem( HddSecData, sizeof(HDDSECDATA), 0 ); + if(Attribute == 0) { + Attribute = (UINT32)(EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS); + } + } + + + for ( ParseIndex = 0; ParseIndex < IDE_PASSWORD_LENGTH; ParseIndex++ ) + { + if ( Buffer[ParseIndex] == 0 ) + { + break; + } + } + + HddSecData->UserMaster = Control; + HddSecData->PasswordLength = ParseIndex; + + if ( Control & 0x01 ) + { + EncodeDecodePassword( Buffer, CryptBuffer, ParseIndex ); + + for ( i = 0; i < ParseIndex; i++ ) + { + HddSecData->HddMasterPassword[i] = CryptBuffer[i]; + } + + for ( i = ParseIndex; i < sizeof (HddSecData->HddMasterPassword); i++ ) + { + HddSecData->HddMasterPassword[i] = 00; + } + } + else { + EncodeDecodePassword( Buffer, CryptBuffer, ParseIndex ); + + for ( i = 0; i < ParseIndex; i++ ) + { + HddSecData->HddUserPassword[i] = CryptBuffer[i]; + } + + for ( i = ParseIndex; i < sizeof (HddSecData->HddUserPassword); i++ ) + { + HddSecData->HddUserPassword[i] = 00; + } + } + + Status = pRS->SetVariable( + HddSecutiyData, + &gIdeSecurityPwNvguid, + Attribute, + HddSecDataSize, + HddSecData + ); + + ASSERT_EFI_ERROR( Status ); + pBS->FreePool( HddSecData ); + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: TransferPwDataFromNvramToSmram +// +// Description: Transfers Stored Data from NVRAM to SMRAM. +// +// Input: +// IN IDE_SECURITY_PROTOCOL *This, +// +// Output: +// EFI_SUCCESS : Password saved in SMRAM. +// EFI_DEVICE_ERROR : Password not saved in SMRAM. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS TransferPwDataFromNvramToSmram( + IN IDE_SECURITY_PROTOCOL *This +) +{ + UINT32 HddDataId = 0; + UINT16 UserMaster = 0; + CHAR16 *HddSecutiyData = NULL; + HDDSECDATA *HddSecData = NULL; + VOID *BusInterface \ + = ((SECURITY_PROTOCOL* )This)->BusInterface; + BOOLEAN ModeFlag = ((SECURITY_PROTOCOL* )This)->ModeFlag; + EFI_STATUS Status; + UINT16 Control; + UINTN i; + UINTN HddSecDataSize = sizeof (HDDSECDATA); + UINT8 CryptBuffer[IDE_PASSWORD_LENGTH]; + UINT8 Buffer[IDE_PASSWORD_LENGTH]; + UINT16 SecurityStatus = 0; + + Status=ReturnSecurityStatus( This, &SecurityStatus ); + + if(EFI_ERROR(Status)) { + return Status; + } + + // Hdd Password Nvram Variable will not be avilable if the HDD is in locked state. + // So return without copying the password to Smram as the password + // data is not avilable + + if ( SecurityStatus & 4 ) { + return EFI_SUCCESS; + } + + Status = GatherIdeInfo( BusInterface, ModeFlag, &HddDataId ); + ASSERT_EFI_ERROR( Status ); + + pBS->AllocatePool( EfiBootServicesData, + IDE_PASSWORD_LENGTH, + &HddSecutiyData ); + pBS->SetMem( HddSecutiyData, IDE_PASSWORD_LENGTH, 0 ); + ConvertHddDataIdToString( HddDataId, HddSecutiyData ); + + pBS->AllocatePool( EfiBootServicesData, sizeof (HDDSECDATA), &HddSecData ); + pBS->SetMem( HddSecData, sizeof(HDDSECDATA), 0 ); + + pBS->SetMem( Buffer, IDE_PASSWORD_LENGTH, 0 ); + + Status = pRS->GetVariable( + HddSecutiyData, + &gIdeSecurityPwNvguid, + NULL, + &HddSecDataSize, + HddSecData + ); + + if(Status){ + Status = HDDPortReset(BusInterface,ModeFlag); + return Status; + } + + Control = HddSecData->UserMaster; + + if ( Control & 0x01 ) + { + for ( i = 0; i < sizeof (HddSecData->HddMasterPassword); i++ ) + { + CryptBuffer[i] = HddSecData->HddMasterPassword[i]; + } + + EncodeDecodePassword( CryptBuffer, Buffer, HddSecData->PasswordLength ); + } + else { + for ( i = 0; i < sizeof (HddSecData->HddUserPassword); i++ ) + { + CryptBuffer[i] = HddSecData->HddUserPassword[i]; + } + + EncodeDecodePassword( CryptBuffer, Buffer, HddSecData->PasswordLength ); + } + + SmmHDDPasswordInterface( This, + Control, + Buffer, + SW_SMI_HDD_PASSWORD_SAVE ); + + pBS->FreePool( HddSecData ); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: ConvertHddDataIdToString +// +// Description: Converts Integer HDD Data Id to String. +// +// Input: +// IN UINT32 DataId, +// OUT CHAR16 *String +// Output: +// None +// +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID ConvertHddDataIdToString( + IN UINT32 DataId, + OUT CHAR16 *String ) +{ + Swprintf( String, L"%*d", 0, DataId ); + return; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: EncodeDecodePassword +// +// Description: Encodes/Decodes Password. +// +// Input: +// IN UINT8 *InputString, +// OUT UINT8 *OutputString, +// IN UINT32 StringLen +// Output: +// None +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID EncodeDecodePassword( + IN UINT8 *InputString, + OUT UINT8 *OutputString, + IN UINT32 StringLength ) +{ + UINT8 *Key; + UINT32 i; + UINT32 KeyIndex; + UINT32 KeyLength; + + if ((InputString == NULL) || (StringLength == 0)) + { + return; + } + + KeyLength = (UINT32)( Strlen( HDD_PWD_ENCRYPTION_KEY )); + pBS->AllocatePool( EfiBootServicesData, KeyLength, (VOID**)&Key ); + pBS->SetMem( Key, KeyLength, 0 ); + pBS->CopyMem( Key, HDD_PWD_ENCRYPTION_KEY, KeyLength ); + ASSERT( Key != NULL ); + + for ( i = 0, KeyIndex = 0; i < StringLength; i++, KeyIndex++ ) + { + if ( KeyIndex == (KeyLength - 1)) + { + KeyIndex = 0; + } + OutputString[i] = (UINT8) ( InputString[i] ^ Key[KeyIndex] ); + } + + pBS->FreePool( Key ); + return; +} + +#endif + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CommonNonDataHook +// +// Description: Common Hook which Calls Non Data Command. +// +// Input: IN VOID* BusInterface, +// IN COMMAND_STRUCTURE CommandStructure, +// IN BOOLEAN ModeFlag +// +// Output: +// EFI_SUCCESS : Non Data command completed successfully. +// EFI_DEVICE_ERROR/EFI_UNSUPPORTED : Not supported. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CommonNonDataHook( + IN VOID *BusInterface, + IN COMMAND_STRUCTURE CommandStructure, + IN BOOLEAN ModeFlag ) +{ + EFI_STATUS Status; + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + if ( ModeFlag == FALSE ) + { + CommandStructure.Device = IdeBusInterface->IdeDevice.Device << 4; + + // + // Idebus API changed from Core 4.6.5.2. Added Core Version check for the OLD + // Core support. + // +#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028b) + Status = IdeBusInterface->IdeNonDataCommand( + IdeBusInterface, + CommandStructure.Features, + (UINT8)CommandStructure.SectorCount, + (UINT8)(CommandStructure.SectorCount >> 8), + CommandStructure.LBALow, + CommandStructure.LBALowExp, + CommandStructure.LBAMid, + CommandStructure.LBAMidExp, + CommandStructure.LBAHigh, + CommandStructure.LBAHighExp, + CommandStructure.Device, + CommandStructure.Command + ); +#else + Status = IdeBusInterface->IdeNonDataCommand( + IdeBusInterface, + CommandStructure.Features, + (UINT8)CommandStructure.SectorCount, + CommandStructure.LBALow, + CommandStructure.LBAMid, + CommandStructure.LBAHigh, + CommandStructure.Device, + CommandStructure.Command + ); + +#endif + } + else { + Status = SataDevInterface->AhciBusInterface->ExecuteNonDataCommand( + SataDevInterface, + CommandStructure + ); + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CommonPioDataHook +// +// Description: Common Hook which Calls Pio Data Command. +// +// Input: IN VOID* BusInterface, +// IN COMMAND_STRUCTURE CommandStructure, +// IN BOOLEAN ModeFlag +// +// Output: +// EFI_SUCCESS : Pio data command completed. +// EFI_DEVICE_ERROR/EFI_UNSUPPORTED : Not supported. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CommonPioDataHook( + IN VOID *BusInterface, + IN COMMAND_STRUCTURE CommandStructure, + IN BOOLEAN ModeFlag ) +{ + EFI_STATUS Status; + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + VOID *IdentifyBuffer = NULL; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + Status = pBS->AllocatePool( EfiBootServicesData, + sizeof(IDENTIFY_DATA), + (VOID**)&IdentifyBuffer + ); + // + // Read Identifydata + // + CommandStructure.Buffer = IdentifyBuffer; + + if ( ModeFlag == FALSE ) + { + CommandStructure.Device = IdeBusInterface->IdeDevice.Device << 4; + Status = IdeBusInterface->AtaPioDataIn( + IdeBusInterface, + CommandStructure + .Buffer, + CommandStructure + .ByteCount, + CommandStructure + .Features, + (UINT8) + CommandStructure.SectorCount, + CommandStructure + .LBALow, + CommandStructure + .LBAMid, + CommandStructure + .LBAHigh, + CommandStructure + .Device, + CommandStructure + .Command, + FALSE + ); + // + // Copy Identify Data + // + pBS->CopyMem( &(IdeBusInterface->IdeDevice.IdentifyData), + IdentifyBuffer, + sizeof(IDENTIFY_DATA) + ); + } + else { + Status = SataDevInterface->AhciBusInterface->ExecutePioDataCommand( + SataDevInterface, + &CommandStructure, + FALSE + ); + + // + // Copy Identify Data + // + pBS->CopyMem( &(SataDevInterface->IdentifyData), + IdentifyBuffer, + sizeof(IDENTIFY_DATA) + ); + } + + pBS->FreePool( IdentifyBuffer ); + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// +// Procedure: CommonReadWritePioHook +// +// Description: Common Hook which Calls Read Write PIO. +// +// Input: +// IN VOID *BusInterface, +// VOID *Buffer, +// UINTN ByteCount, +// UINT64 LBA +// IN UINT8 ReadWriteCommand, +// IN BOOLEAN ReadWrite Read/Write = 0/1 +// IN BOOLEAN ModeFlag +// +// Output: +// *Buffer updated from PIO command. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CommonReadWritePioHook( + IN VOID *BusInterface, + IN OUT VOID *Buffer, + IN UINTN ByteCount, + IN UINT64 LBA, + IN UINT8 ReadWriteCommand, + IN BOOLEAN ReadWrite, + IN BOOLEAN ModeFlag ) +{ + EFI_STATUS Status; + IDE_BUS_PROTOCOL *IdeBusInterface; + SATA_DEVICE_INTERFACE *SataDevInterface; + + IdeBusInterface = (IDE_BUS_PROTOCOL*)BusInterface; + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + + if ( ModeFlag == FALSE ) + { + Status = IdeBusInterface->AtaReadWritePio( + IdeBusInterface, + Buffer, + ByteCount, + 0, + ReadWriteCommand, + TRUE + ); + } + else { + Status = SataDevInterface->AhciBusInterface->SataReadWritePio( + SataDevInterface, + Buffer, + ByteCount, + 0, + ReadWriteCommand, + TRUE + ); + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: LocateAhciSmmServiceEvent +// +// Description: Generates the SwSMI to Locate the AhciSMM Protocol +// that is used by IdeSMM. +// +// Input: +// EFI_EVENT Event, +// VOID *Context +// +// Output: +// None +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID LocateAhciSmmServiceEvent( + EFI_EVENT Event, + VOID *Context ) +{ +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010014) + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(UINT8*)]; + UINTN CommBufferSize; + EFI_STATUS Status; +#elif defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + UINT8 DataSize = 1; +#else + UINTN DataSize = 1; +#endif + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010014) + + if(gSmmCommunication != NULL) { + Status = pBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &gSmmCommunication); + if (EFI_ERROR(Status)) { + ASSERT_EFI_ERROR(Status); + return ; + } + } + + // Copy Smm Communicate Header Here + SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommBuffer; + pBS->CopyMem( &SmmCommunicateHeader->HeaderGuid, &gLocateIdeAhciSmmProtocolGuid, sizeof( EFI_GUID ) ); + SmmCommunicateHeader->MessageLength = sizeof(UINT8 *); + + // Allocate the Buffer for the Passing the Password Data to + // Unlock command in SMM + Status = pBS->AllocatePool( EfiReservedMemoryType, + 512, + (VOID**)&SmmCommunicateHeader->Data ); + + // Calculate Size of Communication buffer + CommBufferSize = sizeof (CommBuffer); + + // Send data to SMM. + Status = gSmmCommunication->Communicate (gSmmCommunication, &CommBuffer[0], &CommBufferSize); + ASSERT_EFI_ERROR(Status); + +#else + UINT8 SwSmiValue = SW_SMI_AHCI_LOCATE_AHCI_SMM; + + // Now Generate a SW SMI to Locate all the SMM protocols used by IDESMM + mSmmCtl->Trigger( mSmmCtl, &SwSmiValue, &DataSize, 0, 0 ); +#endif + + return; +} + + +EFI_STATUS +HDDPortReset( + IN VOID *BusInterface, + IN BOOLEAN ModeFlag +) +{ + + EFI_STATUS Status; + AHCI_BUS_PROTOCOL *AhciBusInterface; + SATA_DEVICE_INTERFACE *SataDeviceInterface; + DLINK *dlink; + COMMAND_STRUCTURE CommandStructure = {0}; + SATA_DEVICE_INTERFACE *SataDevInterface; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Entries = NULL; + + + SataDevInterface = (SATA_DEVICE_INTERFACE*)BusInterface; + AhciBusInterface = SataDevInterface->AhciBusInterface; + + if ( ModeFlag == FALSE ) { + return EFI_UNSUPPORTED; + } + + // Issue Disable Software Preservation command all the Sata Devices connected. + dlink = AhciBusInterface->SataDeviceList.pHead; + if (dlink){ + do { + SataDeviceInterface = OUTTER(dlink, SataDeviceLink, SATA_DEVICE_INTERFACE); + if(SataDevInterface->PortNumber == SataDeviceInterface->PortNumber && + SataDevInterface->PMPortNumber == SataDeviceInterface->PMPortNumber) { + + // Send Disable Software Preservation command. + CommandStructure.Features = DISABLE_SATA2_SOFTPREV; + CommandStructure.SectorCount = 6; + CommandStructure.Command = SET_FEATURE_COMMAND; + Status = AhciBusInterface->ExecuteNonDataCommand(SataDeviceInterface, + CommandStructure); + break; + } + dlink = dlink-> pNext; + }while (dlink); + } + + // Reset the port to restore the initial State + Status = AhciBusInterface->GeneratePortReset( + AhciBusInterface, + SataDevInterface, + SataDevInterface->PortNumber, + SataDevInterface->PMPortNumber, + 0, + 0 + ); + + + // Disconnect the Controller Handle + Status = pBS->DisconnectController( + AhciBusInterface->ControllerHandle, + NULL, + NULL); + + // Connect Controller handle again to invoke the HDD Password Verfication + Status = pBS->ConnectController( + AhciBusInterface->ControllerHandle, + NULL, + NULL, + TRUE); + + // Send Enable Software Preservation command. + CommandStructure.Features = 0x10; + CommandStructure.SectorCount = 6; + CommandStructure.Command = SET_FEATURE_COMMAND; + Status = AhciBusInterface->ExecuteNonDataCommand(SataDeviceInterface, + CommandStructure); + + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |