Page 1 of 1

How to read HDD S.M.A.R.T data?

Posted: Thu Apr 26, 2018 2:14 am
by LeoHsieh
Does anyone know how to read S.M.A.R.T data through gEfiAtaPassThruProtocolGuid?

Here is my code snippet, it will reboot the system after it is executed

Code: Select all

        Status = gBS->HandleProtocol (
                AtaPassThruHandles[Index],
                &gEfiAtaPassThruProtocolGuid,
                (VOID **) &AtaPassThru
                );

        ZeroMem (&AtaPassThruCommandPacket, sizeof(EFI_ATA_PASS_THRU_COMMAND_PACKET));
        ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
        ZeroMem (&AtaStatusBlock, sizeof(EFI_ATA_STATUS_BLOCK));
        ZeroMem (&SmartData, 512);
        AtaCommandBlock.AtaCommand      = ATA_CMD_SMART;
        AtaCommandBlock.AtaSectorCount  = 0x01;
        AtaCommandBlock.AtaCylinderLow  = ATA_CONSTANT_4F;
        AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
        AtaCommandBlock.AtaFeatures     = ATA_SMART_READ_DATA;
        AtaCommandBlock.AtaDeviceHead   = 0xA0;

        AtaPassThruCommandPacket.Timeout            = EFI_TIMER_PERIOD_SECONDS (3);
        AtaPassThruCommandPacket.Length             = EFI_ATA_PASS_THRU_LENGTH_BYTES;
        AtaPassThruCommandPacket.Protocol           = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;
        AtaPassThruCommandPacket.OutTransferLength  = 0;
        AtaPassThruCommandPacket.OutDataBuffer      = NULL;
        AtaPassThruCommandPacket.InTransferLength   = 512;
        AtaPassThruCommandPacket.InDataBuffer       = SmartData;
        AtaPassThruCommandPacket.Acb                = &AtaCommandBlock;
        AtaPassThruCommandPacket.Asb                = &AtaStatusBlock;

        Status = AtaPassThru->PassThru (
                AtaPassThru,
                Port,
                PortMultiplierPort,
                &AtaPassThruCommandPacket,
                NULL
                );

Re: How to read HDD S.M.A.R.T data?

Posted: Thu Apr 26, 2018 1:52 pm
by BobJC
After HandleProtocol, you should check the return value to make sure the protocol instance is retrieved correctly.
Or else, invalid protocol pointer will lead to exception or reset.

Re: How to read HDD S.M.A.R.T data?

Posted: Fri Apr 27, 2018 3:24 am
by LeoHsieh
Yes, I have check status is EFI_SUCCESS.

Re: How to read HDD S.M.A.R.T data?

Posted: Fri Apr 27, 2018 11:24 am
by BobJC
Then check the validity of the protocol pointer, and use serial output or XDP/DCI to do live debugging to figure out the exact location of the reset.
We should not debug through the community forum, right? ;)

Re: How to read HDD S.M.A.R.T data?

Posted: Fri Apr 27, 2018 6:31 pm
by matt.huang
Cannot know the context since there is a small amount of snippet, there are couple of steps you need to check:
  • Current system state (DXE / SMM / runtime, etc)
  • Locate the right protocol instance
  • SMART supportive check, long story short, command_set_supported_83
  • If SMART is supported, does it enabled? command_set_supported_82
  • If SMART is supported and enabled, ATA_SMART_RETURN_STATUS / ATA_SMART_READ_DATA, do what you need to do.
If it still fails on you after checking all the above, maybe the hardware piece you're working on doesn't accept SMART under AtaPassThru (e.g. Some Intel RAID drivers), you can check that by filtering out AtaPassThru protocol under LegacyFree GUID.

Re: How to read HDD S.M.A.R.T data?

Posted: Mon May 07, 2018 5:56 am
by LeoHsieh
Hi Sir,

Thanks for your help.
I successfully read S.M.A.R.T. data.

My variable(SmartData) type declares an error and there is no problem after the correction.

Re: How to read HDD S.M.A.R.T data?

Posted: Mon May 07, 2018 1:27 pm
by BobJC
Hmm... buffer overflow... C language's curse. ;)
Anyway, good to hear that it is resolved.

Re: How to read HDD S.M.A.R.T data?

Posted: Mon May 07, 2018 2:52 pm
by matt.huang
lol I think I knew what went wrong, **var and *var, right :D