Newer
Older
AMI-Aptio-BIOS-Reversed / HddSmart / HddSmart.md
@Ajax Dong Ajax Dong 2 days ago 9 KB Init

HddSmart

Function Table

Address Name Description
HddSmartInternalAllocateBuffer
HddSmartInternalFreeBuffer
LShiftU64
ReadUnaligned64
CompareHobGuid
HddSmartInitHobList
HddSmartGetDebugLevel
HddSmartDebugPrint
HddSmartAssert
HddSmartAtaCommand
HddSmartBlockIoRead
HddSmartHiiCallback
HddSmartDriverEntry
HddSmartTimerPoll
HddSmartNotify
HddSmartCheckStatus
HddSmartUninstall
HddSmartGetDeviceName
HddSmartStartController
HddSmartOpenController
HddSmartReadIdentify
HddSmartReadSmartData
HddSmartBlockIoReadExt
HddSmartBlockIoWriteExt
HddSmartDeferredTimer
ModuleEntryPoint
GUIDs referenced by the driver (defined in .rdata / HII package list)
extern EFI_GUID gHddSmartFormSetGuid;
HII Vendor Device Path (used to publish HII forms)
typedef struct {
Internal function prototypes (forward declarations)
Libc / BaseLib stubs provided by this module
Walk the HOB list to find the system-table HOB.
In the DXE phase the HOB list is cached elsewhere.
HOB / Protocol cache (sub_2064 family)
Scan the boot-services table for a HOB-format entry.
UINTN Index;
0x80000004 }
Only print if the current debug level matches.
if (gHddSmartInstance == NULL) {
No instance yet attempt to locate the debug protocol directly.
Status = gBS->LocateProtocol (&gEfiDebugPortProtocolGuid
Convert %s to %a in the format string (in-place modification).
ATA Pass-through Helpers
ATA Pass-through helper (sub_B7C)
For data-in commands, allocate a bounce buffer and issue the
if (DataBuffer != NULL && DataSize > 0) {
Block I/O wrapper (sub_5A4)
Calculate byte count, aligned to 4KB boundary.
Capacity = 1 << Device->SpinupTime; // Approximate capacity
Build IDENTIFY / READ command.
if (BlockCount == 1 && Lba == 0) {
IDENTIFY DEVICE
Will be resolved from the instance
HII callback (sub_D44)
Initialise a local 512-byte IDENTIFY buffer.
ZeroMem (SerialBuf, sizeof (SerialBuf));
Variable size for "Setup" variable
Refresh all drive data: copy IDENTIFY buffer into serial strings.
for (Index = 0; Index < Instance->DeviceCount; Index++) {
Copy the 512-byte IDENTIFY buffer into a 128-byte display area.
CopyMem (SerialBuf, Device->SerialNumber, 40);
Check return status from device.
Status = HddSmartCheckStatus (Device, Action, &PredictedFailure);
Read the "Setup" NVRAM variable to refresh the stored serial numbers.
Refresh SMART data for all devices.
If SMART data changed, fire the notification.
if (!PredictedFailure) {
If an action variable is set, post a deferred timer event.
if (Instance->Initialized) {
Driver entry point (sub_928)
Cache global pointers.
if (gST == NULL) {
Locate the HII Package List protocol on our own image handle.
Status = gBS->OpenProtocol (
Locate the HII Database protocol.
Status = gBS->LocateProtocol (
Register the HII package list with the database.
Status = HiiDatabase->NewPackageList (
Allocate the global instance structure.
Status = gBS->AllocatePool (
Register function pointers.
Publish the HII Config Access protocol.
ConfigAccess = (EFI_HII_CONFIG_ACCESS_PROTOCOL *)gHddSmartInstance;
Install the driver binding protocol.
Status = gBS->InstallMultipleProtocolInterfaces (
Register a notification for driver binding start.
Status = gBS->RegisterProtocolNotify (
Install HII formset package.
Status = gBS->InstallProtocolInterface (
Periodic timer callback (sub_758)
Enumerate all handles that support Block IO.
Status = gBS->LocateHandleBuffer (
Open the Block IO protocol on this handle.
Try to open ATA Pass-Through on this handle.
if (gHddSmartInstance->AtaPassThru == NULL) {
Read SMART data into a local buffer and check for failure.
ZeroMem (SmartBuf, sizeof (SmartBuf));
Check the first byte for the SMART threshold-exceeded indicator.
if ((SmartBuf[0] & 0x1F) != 0) {
Predictive failure detected fire the notification.
HddSmartNotify ();
Clear the local buffer for the next iteration.
Notification helper (sub_21C4)
If a platform SMI protocol is available, use it to signal the BIOS.
if (gHddSmartInstance != NULL && gHddSmartInstance->Initialized) {
Write the SMI trigger value (0x2080002 = SMI port, 0 = data).
SmiValue = 0x2080002;
Protocol is available send SMI via the ACPI enable register.
IoWrite32 (0xB2, 0x2080002);
Fall back: open the platform-specific protocol.
Status = HddSmartGetDebugLevel (); // Dummy call to init cache
SMART data interpretation (sub_1080 / sub_18D0 / sub_1A60)
For type 1 (IDENTIFY), check the IDENTIFY data words.
if (CommandType == 1) {
Initialise a 49-byte descriptor for SCSI pass-through.
SMART RETURN STATUS
Page code
Page control
Additional page code
Issue the SCSI pass-through command if available.
if (Device->SmartCapable == 1) {
Would call ExtScsiPassThru
Check if the device supports SMART (word 64 of IDENTIFY data).
if (Device->SmartCapable) {
For type 2, issue the SMART READ DATA command.
ZeroMem (Buffer, sizeof (Buffer));
Check word 0 (offline data structure revision) for threshold-exceeded.
HiiConfigAccess protocol callback wrapper (sub_1624)
Function dispatch / I/O wrapper (sub_16A0)
ATA SMART feature: READ LOG
Driver Binding start callback (sub_1714)
Build a 49-byte SCSI pass-through descriptor for IDENTIFY.
ZeroMem (Desc, sizeof (Desc));
ATA feature: IDENTIFY
Additional page length
Issue the ATA pass-through command.
return HddSmartCheckStatus (&Instance->Devices[0], 1, &SmartEnabled);
Driver Binding open controller (sub_17B4)
For IDE/legacy or RAID, issue a direct ATA READ SECTORS.
return HddSmartBlockIoRead (&Instance->Devices[0], 0, 1, *Buffer, NULL);
For native (AHCI), use the SCSI pass-through descriptor.
Timeout / flags
Timeout high byte
ATA feature: READ DATA
Remaining bytes zeroed by ZeroMem above
Read identify data (sub_18D0)
Allocate a 512-byte buffer for IDENTIFY data.
Status = gBS->AllocatePool (EfiBootServicesData, 512, &Buffer);
Build the SCSI pass-through descriptor.
READ DATA
Extract the power-on hours nibble at offset 363 (word 181).
Nibble = ((UINT8 *)Buffer)[363] >> 4;
No useful data; compute from word 0.
Invalid data mark as -1.
Error path.
Read SMART data (sub_1A70)
Check whether the flag byte indicates we should use the
SCSI pass-through or the direct ATA command path.
Build the 49-byte SCSI pass-through descriptor.
SMART ENABLE OPERATIONS
Issue the command via the protocol callback.
Status = HddSmartCheckStatus (Device, 1, &Predicted);
Block I/O wrapper (sub_1BFC)
return HddSmartBlockIoRead (&Instance->Devices[0], 0
Issue command via the Ext SCSI Pass Thru protocol.
if (Instance->Devices[0].ControllerType == 1) {
Dummy read to init
Block I/O write wrapper (sub_1D34)
Deferred timer callback (sub_1E70)
UEFI module entry point
UefiBootServicesTableLib and UefiRuntimeServicesTableLib
initialisation (handled by constructor in the library).
We also initialise our module-level copies.
return HddSmartDriverEntry (ImageHandle, SystemTable);
Utility functions
Overlapping and source precedes destination copy backward.
Src8 += n;
If both buffers are large enough and well-spaced, use 64-bit copies.
if **(n >= 8 && ((UINTN)Src8 - (UINTN)Dst8 >= 8 **
Align source to 8 bytes if needed.
Count = (UINTN)Src8 & 7;
Align both pointers to 8-byte boundary.
if (!Backward) {
Copy 8 bytes at a time.
Count = n >> 3;

Generated by HR650X BIOS Decompilation Project