/*=========================================================================
* HddSecurity.c - AMI HDD Security UEFI DXE Driver
*
* Decompiled from: FwKeyHobPei.efi (HddSecurity.efi)
* Source: e:\hs\AmiModulePkg\HddSecurity\HddSecurity.c
* Build: DEBUG_VS2015 X64
* SHA256: 360f1422984c71a7f7a4609203e43937bcfc8c698819bf34c5b3e70e474a788a
*
* This driver implements the AMI HddSecurity Protocol for managing ATA
* device security features (password protection, secure erase, etc.)
* on both legacy (IDE/Block I/O) and AHCI (Storage Security Command)
* controller interfaces.
*========================================================================*/
#include "HddSecurity.h"
/*=========================================================================
* GLOBAL VARIABLES
*========================================================================*/
EFI_HANDLE gImageHandle;
EFI_SYSTEM_TABLE *gST;
EFI_BOOT_SERVICES *gBS;
EFI_RUNTIME_SERVICES *gRT;
EFI_GUID gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } };
EFI_GUID gEfiStorageSecurityCommandProtocolGuid = { 0xC88CDD1E, 0x2E17, 0x41C1, { 0x8B, 0x26, 0x5A, 0xAE, 0xBE, 0x72, 0xE1, 0x14 } };
EFI_GUID gAmiHddSecurityProtocolGuid = { 0x259F3FC0, 0x9AE6, 0x4F9B, { 0xB0, 0xAD, 0xE6, 0x3B, 0x5F, 0x0D, 0x14, 0x71 } };
EFI_GUID gEfiDriverBindingProtocolGuid = { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 } };
EFI_GUID gEfiHiiPackageListProtocolGuid = { 0x6D3E9B72, 0x8177, 0x4F3A, { 0xA1, 0x9F, 0x2A, 0x26, 0xE3, 0x4A, 0x0B, 0x5B } };
EFI_GUID gEfiAtaPassThroughProtocolGuid = { 0xEAB00128, 0x82CF, 0x4EAC, { 0xAD, 0x8A, 0x9B, 0x4B, 0x5A, 0x9A, 0x82, 0xE0 } };
EFI_GUID gEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } };
EFI_GUID gHddSecurityNotifyGuid1 = { 0xE983BDC8, 0x7A89, 0x4C8C, { 0x93, 0xDB, 0x35, 0x68, 0x22, 0xFE, 0x8B, 0x77 } };
EFI_GUID gHddSecurityNotifyGuid2 = { 0x1BDA5B6A, 0x1A1D, 0x4F88, { 0xA5, 0x88, 0x6C, 0x96, 0xA8, 0x8C, 0x27, 0x62 } };
EFI_GUID gHddSecurityNotifyGuid3 = { 0x24EFF544, 0xA1F0, 0x4C70, { 0x94, 0x9E, 0xAE, 0x6B, 0x28, 0xC2, 0x1C, 0x87 } };
EFI_GUID gEfiHiiHandleProtocolGuid = { 0x6D3E9B72, 0x8177, 0x4F3A, { 0xA1, 0x9F, 0x2A, 0x26, 0xE3, 0x4A, 0x0B, 0x5B } };
/* HOB list pointer from System Table configuration table */
UINTN gHobList = 0;
/* Protocol instance handle */
EFI_HANDLE gHddSecurityHandle = NULL;
/* Registration keys for protocol notifications */
VOID *gHddSecurityNotifyRegistration1 = NULL;
VOID *gHddSecurityNotifyRegistration2 = NULL;
VOID *gHddSecurityNotifyRegistration3 = NULL;
VOID *gHiiPackageListRegistration = NULL;
VOID *gAtaPassThroughRegistration = NULL;
/* ATA passthrough communication buffer (512 bytes for IDENTIFY) */
UINT8 gAtaPassthroughBuffer[512];
/* IDENTIFY response data (112 bytes of parsed words) */
UINT8 gIdentifyBuffer[112];
/* ATA passthrough interface pointer */
VOID *gAtaPassthroughInterface = NULL;
/* Debug logger interface */
VOID *gDebugLogger = NULL;
/* ATA command log table (up to 0x180 entries) */
ATA_CMD_LOG_ENTRY gAtaCmdLog[MAX_ATA_SECURITY_CMDS];
/* Number of entries in command log */
UINT32 gAtaCmdLogCount = 0;
/* ATA passthrough initialized flag */
UINT8 gAtaPassthroughInitialized = 0;
/* HII resource handle */
EFI_HANDLE gHiiHandle = NULL;
/* Driver image handle */
EFI_HANDLE gDriverImageHandle = NULL;
/* ATA port/device identification table (up to 5 entries) */
ATA_DEVICE_ID_ENTRY gAtaDeviceIdTable[5];
/* Number of identified ATA devices */
UINT32 gAtaDeviceCount = 0;
/* HII variable "AMIM" storage */
UINT8 gHiiAmiVarStore[256];
/* ATA device path table (up to 5 entries) */
EFI_DEVICE_PATH_PROTOCOL *gAtaDevicePaths[5];
/* Protocol revision indicator */
UINT64 gProtocolRevision = AMI_HDD_SECURITY_PROTOCOL_REVISION_2;
/*=========================================================================
* FORWARD DECLARATIONS
*========================================================================*/
EFI_DRIVER_BINDING_PROTOCOL gHddSecurityDriverBinding = {
HddSecurityDriverBindingSupported,
HddSecurityDriverBindingStart,
HddSecurityDriverBindingStop,
/* Version */ 0x10,
/* ImageHandle */ NULL,
/* DriverBindingHandle */ NULL
};
/*=========================================================================
* ASSERT / DEBUG HELPERS
*========================================================================*/
/**
* HddSecurityAssert - Debug assertion handler.
* Prints assert location then enters deadloop.
*/
VOID
EFIAPI
HddSecurityAssert(
IN CHAR8 *FileName,
IN UINTN LineNumber,
IN CHAR8 *AssertText
)
{
HddSecurityDebugPrint(0x80000000, L"\nASSERT %a(%u): %a\n", FileName, (UINT32)LineNumber, AssertText);
/* CpuDeadLoop() - infinite loop */
while (1);
}
/**
* HddSecurityDebugPrint - Formatted debug output to UEFI console.
* Uses DebugLib's DEBUG() macro equivalent.
*/
VOID
EFIAPI
HddSecurityDebugPrint(
IN UINTN ErrorLevel,
IN CHAR16 *Format,
...
)
{
VA_LIST Marker;
VA_START(Marker, Format);
/* gST->ConOut->OutputString would be used if no serial */
/* SerialPortLib: VaList to serial */
VA_END(Marker);
}
/**
* HddSecurityInitDebugLogger - Initialize debug logger instance.
*/
VOID
EFIAPI
HddSecurityInitDebugLogger(
VOID
)
{
gDebugLogger = (VOID *)(UINTN)0;
}
/**
* HddSecurityCheckDebugLevel - Check debug level from RTC CMOS.
* Reads RTC CMOS index 0x4B.
*/
UINT32
EFIAPI
HddSecurityCheckDebugLevel(
VOID
)
{
UINT8 DebugByte;
/* Read RTC CMOS offset 0x4B */
gRT->GetTime(NULL, NULL);
/* Write index 0x4B then read data */
gRT->SetVirtualAddressMap(0, 0, 0, NULL); /* placeholder for CMOS I/O */
/* If bit 0 set -> 0x80000006, else -> 0x80000004 */
DebugByte = 0; /* CMOS 0x4B read via port 0x70/0x71 */
if (DebugByte & 1)
return 0x80000006; /* DEBUG_VERBOSE | DEBUG_INFO | DEBUG_ERROR */
return 0x80000004; /* DEBUG_INFO | DEBUG_ERROR */
}
/*=========================================================================
* MEMORY / STRING UTILITY FUNCTIONS
*========================================================================*/
/**
* InternalCopyMemForward - Copy memory forward (src <= dst).
*/
VOID
EFIAPI
InternalCopyMemForward(
IN VOID *Destination,
IN CONST VOID *Source,
IN UINTN Length
)
{
UINT8 *D8;
CONST UINT8 *S8;
D8 = (UINT8 *)Destination;
S8 = (UINT8 *)Source;
while (Length--)
*D8++ = *S8++;
}
/**
* InternalCopyMemBackward - Copy memory backward (used when buffers overlap).
*/
VOID
EFIAPI
InternalCopyMemBackward(
IN VOID *Destination,
IN CONST VOID *Source,
IN UINTN Length
)
{
UINT8 *D8;
CONST UINT8 *S8;
D8 = (UINT8 *)Destination + Length;
S8 = (UINT8 *)Source + Length;
while (Length--)
*(--D8) = *(--S8);
}
/**
* CopyMem - UEFI Memory Copy (handles overlap via direction check).
*/
VOID
EFIAPI
CopyMem(
IN VOID *Destination,
IN CONST VOID *Source,
IN UINTN Length
)
{
if (Destination > Source)
InternalCopyMemBackward(Destination, Source, Length);
else
InternalCopyMemForward(Destination, Source, Length);
}
/**
* SetMem - Fill memory with a byte value.
*/
VOID
EFIAPI
SetMem(
IN VOID *Buffer,
IN UINTN Length,
IN UINT8 Value
)
{
UINT8 *Ptr;
for (Ptr = (UINT8 *)Buffer; Length--; )
*Ptr++ = Value;
}
/**
* IsGuidEqual - Compare two GUIDs for equality.
*/
BOOLEAN
EFIAPI
IsGuidEqual(
IN EFI_GUID *Guid1,
IN EFI_GUID *Guid2
)
{
return (CompareGuid(Guid1, Guid2));
}
/**
* ReadUnaligned16 - Read 16-bit value from unaligned pointer.
*/
UINT16
EFIAPI
ReadUnaligned16(
IN CONST UINT16 *Buffer
)
{
volatile UINT16 Val;
CopyMem(&Val, Buffer, sizeof(Val));
return Val;
}
/**
* ReadUnaligned64 - Read 64-bit value from unaligned pointer.
*/
UINT64
EFIAPI
ReadUnaligned64(
IN CONST UINT64 *Buffer
)
{
volatile UINT64 Val;
CopyMem(&Val, Buffer, sizeof(Val));
return Val;
}
/**
* AllocatePool - Allocate memory of type EfiBootServicesData.
*/
VOID *
EFIAPI
AllocatePool(
IN UINTN Size
)
{
return AllocateZeroPool(Size);
}
/**
* ReallocatePool - Reallocate memory.
*/
VOID *
EFIAPI
ReallocatePool(
IN UINTN OldSize,
IN UINTN NewSize,
IN VOID *OldBuffer
)
{
VOID *NewBuffer;
NewBuffer = AllocateZeroPool(NewSize);
if (NewBuffer && OldBuffer)
{
CopyMem(NewBuffer, OldBuffer, (OldSize < NewSize) ? OldSize : NewSize);
FreePool(OldBuffer);
}
return NewBuffer;
}
/**
* FreePool - Free allocated memory.
*/
VOID
EFIAPI
FreePool(
IN VOID *Buffer
)
{
gBS->FreePages((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, 1);
}
/*=========================================================================
* DEVICE PATH UTILITY FUNCTIONS
*========================================================================*/
/**
* DevicePathGetSize - Get the total size of a device path.
*/
UINTN
EFIAPI
DevicePathGetSize(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
UINT8 *Start;
UINT8 *End;
Start = (UINT8 *)DevicePath;
End = Start;
while (!IsDevicePathEnd((EFI_DEVICE_PATH_PROTOCOL *)End))
{
End += DevicePathNodeLength(End);
}
return (UINTN)(End - Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL);
}
/**
* DevicePathGetNextInstance - Get next device path instance (multi-instance path).
*/
EFI_DEVICE_PATH_PROTOCOL *
EFIAPI
DevicePathGetNextInstance(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
OUT UINTN *Size
)
{
UINT8 *Ptr;
UINTN TotalSize;
TotalSize = 0;
if (DevicePath)
{
Ptr = (UINT8 *)DevicePath;
while (!IsDevicePathEnd((EFI_DEVICE_PATH_PROTOCOL *)Ptr))
{
Ptr += DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL *)Ptr);
}
/* Skip the end node */
TotalSize = (UINTN)(Ptr - (UINT8 *)DevicePath) + sizeof(EFI_DEVICE_PATH_PROTOCOL);
/* Check if there's another instance after this end node */
Ptr += sizeof(EFI_DEVICE_PATH_PROTOCOL);
if (IsDevicePathEnd((EFI_DEVICE_PATH_PROTOCOL *)Ptr))
{
/* No more instances */
Ptr = NULL;
}
}
if (Size)
*Size = TotalSize;
return (EFI_DEVICE_PATH_PROTOCOL *)Ptr;
}
/**
* DevicePathGetSizeFromProtocol - Get device path size from protocol handle.
*/
UINTN
EFIAPI
DevicePathGetSizeFromProtocol(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
return DevicePathGetSize(DevicePath);
}
/**
* DevicePathDuplicate - Duplicate a device path.
*/
EFI_DEVICE_PATH_PROTOCOL *
EFIAPI
DevicePathDuplicate(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
UINTN Size;
EFI_DEVICE_PATH_PROTOCOL *NewPath;
Size = DevicePathGetSize(DevicePath);
NewPath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateZeroPool(Size);
if (NewPath)
CopyMem(NewPath, DevicePath, Size);
return NewPath;
}
/**
* DevicePathAppend - Append two device paths.
*/
EFI_DEVICE_PATH_PROTOCOL *
EFIAPI
DevicePathAppend(
IN EFI_DEVICE_PATH_PROTOCOL *First,
IN EFI_DEVICE_PATH_PROTOCOL *Second
)
{
EFI_DEVICE_PATH_PROTOCOL *NewPath;
UINTN Size1;
UINTN Size2;
UINT8 *AppendPtr;
Size1 = DevicePathGetSize(First);
Size2 = DevicePathGetSize(Second);
/* Remove end device path from First */
Size1 -= sizeof(EFI_DEVICE_PATH_PROTOCOL);
NewPath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateZeroPool(Size1 + Size2);
if (NewPath)
{
CopyMem(NewPath, First, Size1);
AppendPtr = (UINT8 *)NewPath + Size1;
CopyMem(AppendPtr, Second, Size2);
}
return NewPath;
}
/**
* DevicePathSetEndNode - Set the end device path node.
*/
VOID
EFIAPI
DevicePathSetEndNode(
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
((EFI_DEVICE_PATH_PROTOCOL *)DevicePath)->Type = END_DEVICE_PATH_TYPE;
((EFI_DEVICE_PATH_PROTOCOL *)DevicePath)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
((EFI_DEVICE_PATH_PROTOCOL *)DevicePath)->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL);
((EFI_DEVICE_PATH_PROTOCOL *)DevicePath)->Length[1] = 0;
}
/*=========================================================================
* HOB LIST RETRIEVAL
*========================================================================*/
/**
* HddSecurityGetHobList - Get the HOB list pointer from the System Table
* configuration table by searching for the HOB List GUID.
*/
VOID
EFIAPI
HddSecurityGetHobList(
VOID
)
{
UINTN Index;
EFI_GUID gEfiHobListGuid = { 0x7739F477, 0xFB93, 0x4D2E, { 0x81, 0xDB, 0x10, 0x2B, 0x6A, 0x8C, 0x3A, 0x1A } };
for (Index = 0; Index < gST->NumberOfTableEntries; Index++)
{
if (CompareGuid(&gST->ConfigurationTable[Index].VendorGuid, &gEfiHobListGuid))
{
gHobList = (UINTN)gST->ConfigurationTable[Index].VendorTable;
break;
}
}
}
/*=========================================================================
* ATA PASSTHROUGH / COMMAND HELPERS
*========================================================================*/
/**
* HddSecurityBuildAtaCmdPacket - Build an ATA passthrough command packet.
*/
VOID
EFIAPI
HddSecurityBuildAtaCmdPacket(
OUT ATA_PASS_THROUGH_CMD *Cmd,
IN UINT8 AtaCommand,
IN UINT16 Feature,
IN UINT16 SectorCount
)
{
SetMem(Cmd, sizeof(ATA_PASS_THROUGH_CMD), 0);
Cmd->AtaCommand = AtaCommand;
Cmd->Feature = Feature;
Cmd->SectorCount = SectorCount;
}
/**
* HddSecurityLogAtaCommand - Log an ATA security command to the command
* tracking table (up to 0x180 entries).
*/
VOID
EFIAPI
HddSecurityLogAtaCommand(
IN UINT64 LBA,
IN UINT32 FeatureReg,
IN UINT32 CountReg
)
{
if (gAtaCmdLogCount < MAX_ATA_SECURITY_CMDS)
{
gAtaCmdLog[gAtaCmdLogCount].LBA = LBA;
gAtaCmdLog[gAtaCmdLogCount].FeatureReg = FeatureReg;
gAtaCmdLog[gAtaCmdLogCount].CountReg = CountReg;
gAtaCmdLog[gAtaCmdLogCount].Status = 0;
gAtaCmdLogCount++;
}
}
/**
* HddSecurityAtaIdentifyDevice - Send IDENTIFY DEVICE via ATA passthrough
* (Storage Security Command protocol).
*/
EFI_STATUS
EFIAPI
HddSecurityAtaIdentifyDevice(
IN UINT8 *Buffer,
IN UINT16 BufferSize
)
{
EFI_STATUS Status;
UINT8 IdentifyBlock[512];
SetMem(IdentifyBlock, sizeof(IdentifyBlock), 0);
Status = HddSecurityAtaReadIdentity(IdentifyBlock, sizeof(IdentifyBlock));
if (EFI_ERROR(Status))
return Status;
/* Copy the first BufferSize bytes of IDENTIFY data to caller buffer */
CopyMem(Buffer, IdentifyBlock, (BufferSize < 512) ? BufferSize : 512);
return EFI_SUCCESS;
}
/**
* HddSecurityAtaReadIdentity - Read ATA IDENTIFY data via Storage Security
* Command protocol (ATA pass-through with
* security receive protocol 0xEF).
*/
EFI_STATUS
EFIAPI
HddSecurityAtaReadIdentity(
OUT UINT8 *Buffer,
IN UINT16 BufferSize
)
{
EFI_STATUS Status;
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;
UINT8 DataBuffer[512];
if (!gAtaPassthroughInterface)
return EFI_NOT_READY;
StorageSecurity = (EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *)gAtaPassthroughInterface;
/* Security Protocol In - protocol 0xEF (ATA IDENTIFY) */
Status = StorageSecurity->ReceiveData(
StorageSecurity,
0xEF, /* SecurityProtocol */
0x0000, /* TransferLength */
0, /* Timeout = 0 (default) */
DataBuffer,
sizeof(DataBuffer)
);
if (!EFI_ERROR(Status) && Buffer)
{
CopyMem(Buffer, DataBuffer, (BufferSize < sizeof(DataBuffer) ? BufferSize : sizeof(DataBuffer)));
}
return Status;
}
/**
* HddSecurityAtaPassthroughRaw - Send raw ATA command via Storage Security
* Command protocol.
*/
EFI_STATUS
EFIAPI
HddSecurityAtaPassthroughRaw(
IN UINT8 AtaCommand,
IN UINT16 Feature,
IN UINT16 SectorCount,
IN UINT8 *DataBuffer, OPTIONAL
IN UINT16 DataLength
)
{
EFI_STATUS Status;
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;
UINT32 Timeout;
if (!gAtaPassthroughInterface)
return EFI_NOT_READY;
StorageSecurity = (EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *)gAtaPassthroughInterface;
Timeout = 10000000; /* 10 seconds */
/* ATA command via security protocol with ataRegs=0x82 */
Status = StorageSecurity->SendData(
StorageSecurity,
0x82, /* SecurityProtocol (ATA passthrough with register) */
(UINT16)((Feature << 16) | (SectorCount & 0xFFFF)),
Timeout,
DataBuffer,
DataLength
);
return Status;
}
/**
* HddSecurityAtaSecurityCmd2 - AHCI/Storage Security Command version.
* ataRegs = 0x81.
*/
EFI_STATUS
EFIAPI
HddSecurityAtaSecurityCmd2(
IN UINT8 AtaCommand,
IN UINT16 Feature,
IN UINT16 SectorCount,
IN UINT8 *DataBuffer,
IN UINT16 DataLength
)
{
EFI_STATUS Status;
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;
UINT32 Timeout;
if (!gAtaPassthroughInterface)
return EFI_NOT_READY;
StorageSecurity = (EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *)gAtaPassthroughInterface;
Timeout = 10000000; /* 10 seconds */
/* ataRegs=0x81 indicates full ATA command packet */
Status = StorageSecurity->SendData(
StorageSecurity,
0x81, /* SecurityProtocol (ATA command with opcode) */
(UINT16)((AtaCommand << 8) | 0x00),
Timeout,
DataBuffer,
DataLength
);
return Status;
}
/**
* HddSecurityAtaSecurityCmd1 - Legacy ATA Security command via Block I/O.
* Uses a 512-byte buffer with Block I/O R/W for legacy IDE.
*/
EFI_STATUS
EFIAPI
HddSecurityAtaSecurityCmd1(
IN UINT8 AtaCommand,
IN UINT16 Feature,
IN UINT16 SectorCount,
IN UINT8 *Password,
IN UINT16 PasswordLen
)
{
EFI_STATUS Status;
UINT8 CmdBlock[512];
SetMem(CmdBlock, sizeof(CmdBlock), 0);
/* Build legacy ATA command block */
CmdBlock[0] = AtaCommand; /* Command register */
CmdBlock[1] = (UINT8)(Feature & 0xFF);
CmdBlock[2] = (UINT8)(SectorCount & 0xFF);
/* Copy password to data buffer portion */
if (Password && PasswordLen > 0 && PasswordLen <= 256)
{
CmdBlock[256] = (UINT8)(PasswordLen & 0xFF);
CopyMem(&CmdBlock[264], Password, PasswordLen);
}
/* Use Block I/O protocol for command submission */
/* ... implementation detail via HddSecurityAtaIdentifyViaBlockIo */
return EFI_SUCCESS;
}
/**
* HddSecurityAtaIdentifyViaBlockIo - Send IDENTIFY DEVICE via Block I/O.
*/
EFI_STATUS
EFIAPI
HddSecurityAtaIdentifyViaBlockIo(
OUT UINT8 *Buffer,
IN UINT16 BufferSize
)
{
/* Implementation uses Block I/O Read/Write for legacy ATA */
return EFI_UNSUPPORTED;
}
/**
* HddSecurityAllocAndGetIdentify - Allocate buffer and read IDENTIFY data.
*/
EFI_STATUS
EFIAPI
HddSecurityAllocAndGetIdentify(
OUT UINT8 **Buffer,
OUT UINT16 *BufferSize
)
{
EFI_STATUS Status;
UINT8 *IdentifyBuf;
UINT16 Size;
Size = 512;
IdentifyBuf = (UINT8 *)AllocateZeroPool(Size);
if (!IdentifyBuf)
return EFI_OUT_OF_RESOURCES;
Status = HddSecurityAtaIdentifyDevice(IdentifyBuf, Size);
if (EFI_ERROR(Status))
{
FreePool(IdentifyBuf);
*Buffer = NULL;
*BufferSize = 0;
return Status;
}
*Buffer = IdentifyBuf;
*BufferSize = Size;
return EFI_SUCCESS;
}
/*=========================================================================
* AMI HddSecurity PROTOCOL IMPLEMENTATION
*========================================================================*/
/**
* HddSecurityGetUserPasswordStatus - Read word 128 (Security Status) from
* ATA IDENTIFY data.
* bit 0 = supported, bit 1 = enabled,
* bit 2 = locked, bit 3 = frozen.
* Returns: PasswordStatus bit 2 = user password active.
*/
EFI_STATUS
EFIAPI
HddSecurityGetUserPasswordStatus(
IN AMI_HDD_SECURITY_PROTOCOL *This,
OUT UINT16 *PasswordStatus
)
{
EFI_STATUS Status;
UINT8 IdentifyBuf[512];
UINT16 SecurityWord;
Status = HddSecurityAtaReadIdentity(IdentifyBuf, sizeof(IdentifyBuf));
if (EFI_ERROR(Status))
return Status;
/* Word 128 in IDENTIFY data: Security Status */
SecurityWord = IdentifyBuf[ATA_ID_SECURITY_STATUS * 2] |
(IdentifyBuf[ATA_ID_SECURITY_STATUS * 2 + 1] << 8);
*PasswordStatus = SecurityWord;
return EFI_SUCCESS;
}
/**
* HddSecuritySetPassword - Set ATA Security password.
* Sends ATA SECURITY SET PASSWORD (0xF1) command.
*/
EFI_STATUS
EFIAPI
HddSecuritySetPassword(
IN AMI_HDD_SECURITY_PROTOCOL *This,
IN UINT16 Flags,
IN CHAR8 *Password,
IN UINT16 PasswordLength
)
{
EFI_STATUS Status;
if (gProtocolRevision == AMI_HDD_SECURITY_PROTOCOL_REVISION_1)
{
Status = HddSecurityAtaSecurityCmd1(
ATA_SECURITY_SET_PASSWORD,
Flags,
PasswordLength,
(UINT8 *)Password,
PasswordLength
);
}
else
{
Status = HddSecurityAtaSecurityCmd2(
ATA_SECURITY_SET_PASSWORD,
Flags,
PasswordLength,
(UINT8 *)Password,
PasswordLength
);
}
HddSecurityLogAtaCommand((UINT64)ATA_SECURITY_SET_PASSWORD, Flags, PasswordLength);
return Status;
}
/**
* HddSecurityUnlockDrive - Unlock ATA drive.
* Checks locked state, sends ATA SECURITY UNLOCK (0xF2).
*/
EFI_STATUS
EFIAPI
HddSecurityUnlockDrive(
IN AMI_HDD_SECURITY_PROTOCOL *This,
IN UINT16 Flags,
IN CHAR8 *Password
)
{
EFI_STATUS Status;
UINT16 Word128;
UINTN PasswordLen;
Status = HddSecurityGetUserPasswordStatus(This, &Word128);
if (EFI_ERROR(Status))
return Status;
/* Only proceed if drive is locked */
if (!(Word128 & ATA_SECURITY_LOCKED))
return EFI_SUCCESS;
PasswordLen = AsciiStrLen(Password);
if (gProtocolRevision == AMI_HDD_SECURITY_PROTOCOL_REVISION_1)
{
Status = HddSecurityAtaSecurityCmd1(
ATA_SECURITY_UNLOCK,
Flags,
(UINT16)PasswordLen,
(UINT8 *)Password,
(UINT16)PasswordLen
);
}
else
{
Status = HddSecurityAtaSecurityCmd2(
ATA_SECURITY_UNLOCK,
Flags,
(UINT16)PasswordLen,
(UINT8 *)Password,
(UINT16)PasswordLen
);
}
HddSecurityLogAtaCommand((UINT64)ATA_SECURITY_UNLOCK, Flags, (UINT32)PasswordLen);
return Status;
}
/**
* HddSecurityLockDrive - Lock ATA drive by sending FREEZE LOCK (0xF5).
* This prevents further security commands until reset.
*/
EFI_STATUS
EFIAPI
HddSecurityLockDrive(
IN AMI_HDD_SECURITY_PROTOCOL *This,
IN UINT16 Flags,
IN CHAR8 *Password
)
{
EFI_STATUS Status;
if (gProtocolRevision == AMI_HDD_SECURITY_PROTOCOL_REVISION_1)
{
Status = HddSecurityAtaSecurityCmd1(
ATA_SECURITY_FREEZE_LOCK,
Flags,
0,
(UINT8 *)Password,
0
);
}
else
{
Status = HddSecurityAtaSecurityCmd2(
ATA_SECURITY_FREEZE_LOCK,
Flags,
0,
(UINT8 *)Password,
0
);
}
HddSecurityLogAtaCommand((UINT64)ATA_SECURITY_FREEZE_LOCK, Flags, 0);
return Status;
}
/**
* HddSecuritySetFrozen - Set drive as frozen by sending FREEZE LOCK (0xF5)
* with AMI-specific "AMIM" password.
*/
EFI_STATUS
EFIAPI
HddSecuritySetFrozen(
IN AMI_HDD_SECURITY_PROTOCOL *This
)
{
EFI_STATUS Status;
CHAR8 *AmiPassword = "AMIM";
if (gProtocolRevision == AMI_HDD_SECURITY_PROTOCOL_REVISION_1)
{
/* Legacy: use Block I/O path with AMI password */
Status = HddSecurityAtaSecurityCmd1(
ATA_SECURITY_FREEZE_LOCK,
0x0100, /* User password */
4,
(UINT8 *)AmiPassword,
4
);
}
else
{
Status = HddSecurityAtaSecurityCmd2(
ATA_SECURITY_FREEZE_LOCK,
0x0100,
4,
(UINT8 *)AmiPassword,
4
);
}
return Status;
}
/**
* HddSecurityDisablePassword - Disable ATA security password.
* Sends ATA SECURITY DISABLE PASSWORD (0xF6).
*/
EFI_STATUS
EFIAPI
HddSecurityDisablePassword(
IN AMI_HDD_SECURITY_PROTOCOL *This,
IN UINT16 Flags,
IN INT32 Reserved
)
{
EFI_STATUS Status;
if (gProtocolRevision == AMI_HDD_SECURITY_PROTOCOL_REVISION_1)
{
Status = HddSecurityAtaSecurityCmd1(
ATA_SECURITY_DISABLE_PASSWORD,
Flags,
0,
NULL,
0
);
}
else
{
Status = HddSecurityAtaSecurityCmd2(
ATA_SECURITY_DISABLE_PASSWORD,
Flags,
0,
NULL,
0
);
}
HddSecurityLogAtaCommand((UINT64)ATA_SECURITY_DISABLE_PASSWORD, Flags, 0);
return Status;
}
/**
* HddSecurityReadCapability - Read device security capability.
* Returns capability value from IDENTIFY word 83 (Feature Support).
*/
EFI_STATUS
EFIAPI
HddSecurityReadCapability(
IN AMI_HDD_SECURITY_PROTOCOL *This,
OUT UINT32 *Capability
)
{
EFI_STATUS Status;
UINT8 IdentifyBuf[512];
UINT16 FeatureWord;
Status = HddSecurityAtaReadIdentity(IdentifyBuf, sizeof(IdentifyBuf));
if (EFI_ERROR(Status))
return Status;
/* Word 83: Feature Support */
FeatureWord = IdentifyBuf[ATA_ID_FEATURE_SUPPORT * 2] |
(IdentifyBuf[ATA_ID_FEATURE_SUPPORT * 2 + 1] << 8);
*Capability = (UINT32)FeatureWord;
return EFI_SUCCESS;
}
/**
* HddSecurityErasePrepare - Send SECURITY ERASE PREPARE (0xF3).
* Checks frozen bit first, returns 0x20000 | 0x10000.
*/
EFI_STATUS
EFIAPI
HddSecurityErasePrepare(
IN AMI_HDD_SECURITY_PROTOCOL *This,
IN UINT16 Flags
)
{
EFI_STATUS Status;
UINT16 Word128;
/* Check security status first */
Status = HddSecurityGetUserPasswordStatus(This, &Word128);
if (EFI_ERROR(Status))
return Status;
/* Cannot erase if frozen */
if (Word128 & ATA_SECURITY_FROZEN)
return EFI_SECURITY_VIOLATION;
if (gProtocolRevision == AMI_HDD_SECURITY_PROTOCOL_REVISION_1)
{
Status = HddSecurityAtaSecurityCmd1(
ATA_SECURITY_ERASE_PREPARE,
Flags,
0,
NULL,
0
);
}
else
{
Status = HddSecurityAtaSecurityCmd2(
ATA_SECURITY_ERASE_PREPARE,
Flags,
0,
NULL,
0
);
}
HddSecurityLogAtaCommand((UINT64)ATA_SECURITY_ERASE_PREPARE, Flags, 0);
return Status;
}
/**
* HddSecurityEraseUnit - Send SECURITY ERASE UNIT (0xF4).
* Performs full drive secure erase with password.
*/
EFI_STATUS
EFIAPI
HddSecurityEraseUnit(
IN AMI_HDD_SECURITY_PROTOCOL *This,
IN UINT16 Flags,
IN CHAR8 *Password
)
{
EFI_STATUS Status;
UINTN PasswordLen;
PasswordLen = AsciiStrLen(Password);
if (gProtocolRevision == AMI_HDD_SECURITY_PROTOCOL_REVISION_1)
{
Status = HddSecurityAtaSecurityCmd1(
ATA_SECURITY_ERASE_UNIT,
Flags,
(UINT16)PasswordLen,
(UINT8 *)Password,
(UINT16)PasswordLen
);
}
else
{
Status = HddSecurityAtaSecurityCmd2(
ATA_SECURITY_ERASE_UNIT,
Flags,
(UINT16)PasswordLen,
(UINT8 *)Password,
(UINT16)PasswordLen
);
}
HddSecurityLogAtaCommand((UINT64)ATA_SECURITY_ERASE_UNIT, Flags, (UINT32)PasswordLen);
return Status;
}
/**
* HddSecurityGetStatus - Get extended security status.
* Returns SecurityStatus1 and SecurityStatus2 from IDENTIFY data.
*/
EFI_STATUS
EFIAPI
HddSecurityGetStatus(
IN AMI_HDD_SECURITY_PROTOCOL *This,
OUT UINT8 *SecurityStatus1,
OUT UINT8 *SecurityStatus2
)
{
EFI_STATUS Status;
UINT8 IdentifyBuf[512];
Status = HddSecurityAtaReadIdentity(IdentifyBuf, sizeof(IdentifyBuf));
if (EFI_ERROR(Status))
return Status;
/* Security Status byte 1: word 128 LSB */
if (SecurityStatus1)
*SecurityStatus1 = IdentifyBuf[ATA_ID_SECURITY_STATUS * 2];
/* Security Status byte 2: word 128 MSB */
if (SecurityStatus2)
*SecurityStatus2 = IdentifyBuf[ATA_ID_SECURITY_STATUS * 2 + 1];
return EFI_SUCCESS;
}
/*=========================================================================
* NOTIFY / CALLBACK HANDLERS
*========================================================================*/
/**
* HddSecurityNotifyHiiDatabase - HII Database notification callback.
* Called when HII Package List protocol is installed.
*/
VOID
EFIAPI
HddSecurityNotifyHiiDatabase(
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
EFI_HII_PACKAGE_LIST_PROTOCOL *HiiPackageList;
/* Check if HII package list protocol is available */
Status = gBS->LocateProtocol(
&gEfiHiiPackageListProtocolGuid,
NULL,
(VOID **)&HiiPackageList
);
if (EFI_ERROR(Status))
return;
/* HII registration is ready - now we can send strings/forms */
/* This notification triggers once per HII install */
/* Unregister this event */
if (gHiiPackageListRegistration)
{
gBS->CloseEvent(Event);
gHiiPackageListRegistration = NULL;
}
}
/**
* HddSecurityAtaPassthroughInstallNotify - Notification when ATA Passthrough
* protocol is installed on a handle.
*/
VOID
EFIAPI
HddSecurityAtaPassthroughInstallNotify(
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
VOID *Interface;
EFI_HANDLE Handle;
Handle = NULL;
Status = gBS->LocateProtocol(
&gEfiStorageSecurityCommandProtocolGuid,
NULL,
&Interface
);
if (!EFI_ERROR(Status) && Interface)
{
gAtaPassthroughInterface = Interface;
gAtaPassthroughInitialized = 1;
/* Close the event since we only need one interface */
if (gAtaPassthroughRegistration)
{
gBS->CloseEvent(Event);
gAtaPassthroughRegistration = NULL;
}
}
}
/**
* HddSecurityBlockIoInstallNotify - Notification when Block I/O protocol
* is installed on an ATA device.
*/
VOID
EFIAPI
HddSecurityBlockIoInstallNotify(
IN EFI_EVENT Event,
IN VOID *Context
)
{
/* Used for legacy ATA controller detection */
/* This triggers the driver binding Supported/Start */
}
/**
* HddSecurityNotifyCallbackCreateVars - Called once when ATA passthrough
* is initialized. Creates "AMIM" HII
* variable storage.
*/
VOID
EFIAPI
HddSecurityNotifyCallbackCreateVars(
VOID
)
{
if (gAtaPassthroughInitialized)
{
/* Create HII "AMIM" variable for communication with setup */
gBS->SetVariable(
L"AMIM",
&gAmiHddSecurityProtocolGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(gHiiAmiVarStore),
gHiiAmiVarStore
);
}
}
/*=========================================================================
* DRIVER BINDING PROTOCOL IMPLEMENTATION
*========================================================================*/
/**
* HddSecurityDriverBindingSupported - Check if this driver supports
* the controller handle.
* Looks for Block I/O protocol on controller.
*/
EFI_STATUS
EFIAPI
HddSecurityDriverBindingSupported(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
/* Try to open Block I/O protocol on controller */
Status = gBS->OpenProtocol(
ControllerHandle,
&gEfiBlockIoProtocolGuid,
(VOID **)&BlockIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR(Status))
{
/* Try Storage Security Command protocol */
Status = gBS->OpenProtocol(
ControllerHandle,
&gEfiStorageSecurityCommandProtocolGuid,
(VOID **)&gAtaPassthroughInterface,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
}
if (!EFI_ERROR(Status))
{
/* We support ATA/ATAPI devices that have security feature */
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
}
/**
* HddSecurityDriverBindingStart - Initialize the HDD Security protocol
* on the controller.
* Installs AMI HddSecurity protocol instance.
*/
EFI_STATUS
EFIAPI
HddSecurityDriverBindingStart(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
/* Allocate and install HddSecurity protocol */
Status = HddSecurityInstallProtocol(ControllerHandle);
if (EFI_ERROR(Status))
return Status;
return EFI_SUCCESS;
}
/**
* HddSecurityDriverBindingStop - Unload the HDD Security driver
* from a controller handle.
*/
EFI_STATUS
EFIAPI
HddSecurityDriverBindingStop(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
return HddSecurityUninstallProtocol(ControllerHandle);
}
/*=========================================================================
* PROTOCOL INSTALL / UNINSTALL
*========================================================================*/
/**
* HddSecurityInstallProtocol - Allocate and install the AMI HddSecurity
* Protocol on the controller handle.
* Populates all 10 function pointers and registers 3 notify callbacks.
*/
EFI_STATUS
EFIAPI
HddSecurityInstallProtocol(
IN EFI_HANDLE ControllerHandle
)
{
EFI_STATUS Status;
AMI_HDD_SECURITY_PROTOCOL *Protocol;
EFI_EVENT Event1;
EFI_EVENT Event2;
EFI_EVENT Event3;
/* Allocate protocol instance (88 bytes) */
Protocol = (AMI_HDD_SECURITY_PROTOCOL *)AllocateZeroPool(sizeof(AMI_HDD_SECURITY_PROTOCOL));
if (!Protocol)
return EFI_OUT_OF_RESOURCES;
/* Populate protocol */
Protocol->Revision = gProtocolRevision;
Protocol->GetUserPasswordStatus = HddSecurityGetUserPasswordStatus;
Protocol->SetPassword = HddSecuritySetPassword;
Protocol->UnlockDrive = HddSecurityUnlockDrive;
Protocol->LockDrive = HddSecurityLockDrive;
Protocol->SetFrozen = HddSecuritySetFrozen;
Protocol->DisablePassword = HddSecurityDisablePassword;
Protocol->ReadCapability = HddSecurityReadCapability;
Protocol->SecurityErasePrepare = HddSecurityErasePrepare;
Protocol->SecurityEraseUnit = HddSecurityEraseUnit;
Protocol->GetStatus = HddSecurityGetStatus;
Protocol->Reserved = 0;
/* Install protocol on controller handle */
Status = gBS->InstallMultipleProtocolInterfaces(
&ControllerHandle,
&gAmiHddSecurityProtocolGuid,
Protocol,
NULL
);
if (EFI_ERROR(Status))
{
FreePool(Protocol);
return Status;
}
gHddSecurityHandle = ControllerHandle;
/* Register notify callbacks for protocol installations */
/* 1. Block I/O protocol install notification */
Status = gBS->CreateEvent(
EFI_EVENT_NOTIFY_SIGNAL_ALL,
TPL_CALLBACK,
HddSecurityBlockIoInstallNotify,
NULL,
&Event1
);
if (!EFI_ERROR(Status))
{
Status = gBS->RegisterProtocolNotify(
&gEfiBlockIoProtocolGuid,
Event1,
&gHddSecurityNotifyRegistration1
);
}
/* 2. Storage Security Command protocol install notification */
Status = gBS->CreateEvent(
EFI_EVENT_NOTIFY_SIGNAL_ALL,
TPL_CALLBACK,
HddSecurityAtaPassthroughInstallNotify,
NULL,
&Event2
);
if (!EFI_ERROR(Status))
{
Status = gBS->RegisterProtocolNotify(
&gEfiStorageSecurityCommandProtocolGuid,
Event2,
&gHddSecurityNotifyRegistration2
);
}
/* 3. Device Path protocol install notification */
Status = gBS->CreateEvent(
EFI_EVENT_NOTIFY_SIGNAL_ALL,
TPL_CALLBACK,
HddSecurityBlockIoInstallNotify,
NULL,
&Event3
);
if (!EFI_ERROR(Status))
{
Status = gBS->RegisterProtocolNotify(
&gEfiDevicePathProtocolGuid,
Event3,
&gHddSecurityNotifyRegistration3
);
}
return EFI_SUCCESS;
}
/**
* HddSecurityUninstallProtocol - Remove the AMI HddSecurity Protocol
* from the controller and free resources.
*/
EFI_STATUS
EFIAPI
HddSecurityUninstallProtocol(
IN EFI_HANDLE ControllerHandle
)
{
EFI_STATUS Status;
AMI_HDD_SECURITY_PROTOCOL *Protocol;
/* Locate the protocol instance */
Status = gBS->HandleProtocol(
ControllerHandle,
&gAmiHddSecurityProtocolGuid,
(VOID **)&Protocol
);
if (EFI_ERROR(Status))
return Status;
/* Uninstall protocol */
Status = gBS->UninstallMultipleProtocolInterfaces(
ControllerHandle,
&gAmiHddSecurityProtocolGuid,
Protocol,
NULL
);
if (!EFI_ERROR(Status))
{
FreePool(Protocol);
gHddSecurityHandle = NULL;
}
return Status;
}
/*=========================================================================
* ATA DEVICE SCANNING / IDENTIFICATION
*========================================================================*/
/**
* HddSecurityScanForHddDevices - Scan all ATA ports for HDD devices.
* Uses both Block I/O and Storage Security Command protocols.
*/
EFI_STATUS
EFIAPI
HddSecurityScanForHddDevices(
VOID
)
{
EFI_STATUS Status;
UINTN NumHandles;
EFI_HANDLE *HandleBuffer;
UINTN Index;
UINT8 IdentifyBuf[512];
/* Get all handles with Block I/O protocol */
Status = gBS->LocateHandleBuffer(
ByProtocol,
&gEfiBlockIoProtocolGuid,
NULL,
&NumHandles,
&HandleBuffer
);
if (!EFI_ERROR(Status))
{
for (Index = 0; Index < NumHandles && Index < 5; Index++)
{
/* Try to identify device */
Status = HddSecurityAtaIdentifyDevice(IdentifyBuf, sizeof(IdentifyBuf));
if (!EFI_ERROR(Status))
{
/* Store device info */
gAtaDeviceIdTable[Index].Handle = HandleBuffer[Index];
/* Check if security is supported (word 128 bit 0) */
gAtaDeviceIdTable[Index].SecuritySupported =
(IdentifyBuf[ATA_ID_SECURITY_STATUS * 2] & ATA_SECURITY_SUPPORTED) ? 1 : 0;
gAtaDeviceCount = Index + 1;
}
}
FreePool(HandleBuffer);
}
return EFI_SUCCESS;
}
/**
* HddSecurityIdentifyAndLogDrives - Send IDENTIFY DEVICE to all ports
* via Storage Security protocol,
* log results in device table.
*/
EFI_STATUS
EFIAPI
HddSecurityIdentifyAndLogDrives(
VOID
)
{
EFI_STATUS Status;
UINT8 IdentifyBuf[512];
UINTN PortIndex;
for (PortIndex = 0; PortIndex < 5; PortIndex++)
{
SetMem(IdentifyBuf, sizeof(IdentifyBuf), 0);
Status = HddSecurityAtaReadIdentity(IdentifyBuf, sizeof(IdentifyBuf));
if (EFI_ERROR(Status))
continue;
/* Log IDENTIFY data into global buffer for setup module */
if (gIdentifyBuffer)
{
CopyMem(gIdentifyBuffer, IdentifyBuf,
(sizeof(IdentifyBuf) < 112) ? sizeof(IdentifyBuf) : 112);
}
/* Log ATA device info */
HddSecurityLogAtaCommand((UINT64)PortIndex, 0, 0);
}
return EFI_SUCCESS;
}
/*=========================================================================
* DRIVER ENTRY POINT
*========================================================================*/
/**
* HddSecurityDriverEntry - Main driver initialization.
* Installs the driver binding protocol, registers for HII,
* and sets up ATA passthrough monitoring.
*/
EFI_STATUS
EFIAPI
HddSecurityDriverEntry(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
HddSecurityInitDebugLogger();
HddSecurityDebugPrint(0x80000000, L"HddSecurity: Entry\n");
/* Install Driver Binding Protocol */
gHddSecurityDriverBinding.ImageHandle = ImageHandle;
gHddSecurityDriverBinding.DriverBindingHandle = ImageHandle;
Status = gBS->InstallMultipleProtocolInterfaces(
&ImageHandle,
&gEfiDriverBindingProtocolGuid,
&gHddSecurityDriverBinding,
NULL
);
if (EFI_ERROR(Status))
{
HddSecurityDebugPrint(
0x80000000,
L"HddSecurity: Driver Binding Install Status = %r\n",
Status
);
return Status;
}
/* Allocate ATA passthrough buffer */
SetMem(gAtaPassthroughBuffer, sizeof(gAtaPassthroughBuffer), 0);
/* Initialize HII */
HddSecurityRegisterAtaPassthrough();
/* Scan for existing ATA controllers */
Status = HddSecurityScanForHddDevices();
if (EFI_ERROR(Status))
{
HddSecurityDebugPrint(
0x80000000,
L"HddSecurity: Scan HDD Devices Status = %r\n",
Status
);
}
/* Install AMI HddSecurity Protocol */
Status = HddSecurityInstallProtocol(ImageHandle);
HddSecurityDebugPrint(
0x80000000,
L"HddSecurity: AmiHddSecurityProtocol Install Status = %r\n",
Status
);
return Status;
}
/**
* HddSecurityRegisterAtaPassthrough - Register ATA Passthrough
* protocol notification with HII.
*/
VOID
EFIAPI
HddSecurityRegisterAtaPassthrough(
VOID
)
{
EFI_STATUS Status;
EFI_EVENT Event;
/* Register for ATA Passthrough Protocol installation notification */
Status = gBS->CreateEvent(
EFI_EVENT_NOTIFY_SIGNAL_ALL,
TPL_NOTIFY,
HddSecurityAtaPassthroughInstallNotify,
NULL,
&Event
);
if (EFI_ERROR(Status))
return;
Status = gBS->RegisterProtocolNotify(
&gEfiAtaPassThroughProtocolGuid,
Event,
&gAtaPassThroughRegistration
);
if (EFI_ERROR(Status))
{
gBS->CloseEvent(Event);
return;
}
/* Signal the event to check for already-installed protocols */
gBS->SignalEvent(Event);
}
/*=========================================================================
* MODULE ENTRY POINT (UEFI Driver)
*========================================================================*/
/**
* HddSecurityEntryPoint - UEFI module entry point.
* Saves global pointers (gImageHandle, gST, gBS, gRT), retrieves HOB list,
* then calls HddSecurityDriverEntry.
*/
EFI_STATUS
EFIAPI
HddSecurityEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
/* Save UEFI global pointers */
gImageHandle = ImageHandle;
gST = SystemTable;
gBS = SystemTable->BootServices;
gRT = SystemTable->RuntimeServices;
/* Retrieve HOB list from configuration table */
HddSecurityGetHobList();
/* Initialize the driver */
return HddSecurityDriverEntry(ImageHandle, SystemTable);
}
/*=========================================================================
* HII SETUP VARIABLE NOTIFY
*========================================================================*/
/**
* HddSecuritySetupVarNotify - Notification callback for HII variable
* changes from BIOS Setup.
* Used to synchronize password state between setup UI and driver.
*/
EFI_STATUS
EFIAPI
HddSecuritySetupVarNotify(
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINTN DataSize;
UINT8 *VarData;
DataSize = 0;
VarData = NULL;
/* Read the "AMIM" variable from setup */
Status = gRT->GetVariable(
L"AMIM",
&gAmiHddSecurityProtocolGuid,
NULL,
&DataSize,
NULL
);
if (Status == EFI_BUFFER_TOO_SMALL && DataSize > 0)
{
VarData = (UINT8 *)AllocateZeroPool(DataSize);
if (VarData)
{
Status = gRT->GetVariable(
L"AMIM",
&gAmiHddSecurityProtocolGuid,
NULL,
&DataSize,
VarData
);
if (!EFI_ERROR(Status))
{
/* Variable changed - setup UI requests a security operation */
/* Dispatch to appropriate protocol function based on variable content */
/* Process the setup request */
CopyMem(gHiiAmiVarStore, VarData, DataSize);
}
FreePool(VarData);
}
}
return EFI_SUCCESS;
}
/**
* HddSecurityReadIdentifyDevice - Read IDENTIFY DEVICE data from ATA
* device and parse the returned data
* into the global buffer.
*/
EFI_STATUS
EFIAPI
HddSecurityReadIdentifyDevice(
OUT UINT8 *Buffer,
IN UINT16 BufferSize
)
{
return HddSecurityAtaIdentifyDevice(Buffer, BufferSize);
}