Newer
Older
AMI-Aptio-BIOS-Reversed / OpalSecurity / OpalSecurity.c
@Ajax Dong Ajax Dong 2 days ago 22 KB Init
/** @file OpalSecurity.c
 *  OpalSecurity DXE driver -- TCG Opal storage security for Lenovo HR650X.
 *
 *  Source: e:\hs\AmiModulePkg\OpalSecurity\OpalSecurity.c
 *
 *  This driver provides Opal Storage Security Protocol support for
 *  self-encrypting drives (SEDs) conforming to the TCG Storage Security
 *  Subsystem Class (Opal SSC).
 *
 *  It follows the UEFI driver binding model:
 *    1. OpalSecurityDriverInit       - Entry point (install protocol)
 *    2. OpalSecurityBindingStart     - Start binding (connect to device)
 *    3. OpalSecurityBindingStop      - Stop binding (disconnect from device)
 *
 *  The module communicates with storage devices using the TCG Storage
 *  IF-SEND/IF-RECV protocol at Level 0 (security protocol discovery)
 *  to identify Opal-capable devices and perform security operations.
 *
 *  Copyright (C) 2025 Lenovo. All rights reserved.
 */

#include "OpalSecurity.h"

//
// External global variables set by the UEFI Boot Services Table Library
//
extern EFI_HANDLE        gImageHandle;
extern EFI_SYSTEM_TABLE  *gST;
extern EFI_BOOT_SERVICES *gBS;

//
// Module-level global state
//
STATIC EFI_BOOT_SERVICES    *mBootServices             = NULL;
STATIC EFI_RUNTIME_SERVICES *mRuntimeServices           = NULL;
STATIC EFI_SYSTEM_TABLE     *mSystemTable               = NULL;
STATIC UINT8                mOpalSecurityEnabled         = 0;
STATIC OPAL_STORAGE_PROTOCOL *mStorageProtocol          = NULL;
STATIC OPAL_STORAGE_PROTOCOL *mChildProtocol            = NULL;

//
// Forward declarations
//
STATIC
UINTN
OpalReadCmosDebugLevel (
  VOID
  );

STATIC
EFI_STATUS
OpalGetHobList (
  VOID
  );

//------------------------------------------------------------------------------
// Module Entry Point
//------------------------------------------------------------------------------

EFI_STATUS
EFIAPI
OpalSecurityDriverInit (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_BOOT_SERVICES    *BootServices;
  EFI_RUNTIME_SERVICES *RuntimeServices;
  UINT64               Status;

  //
  // Cache UEFI service table pointers locally
  //
  if (mSystemTable == NULL) {
    mSystemTable   = SystemTable;
    BootServices   = SystemTable->BootServices;
    mBootServices  = BootServices;
    RuntimeServices = SystemTable->RuntimeServices;
    mRuntimeServices = RuntimeServices;
  }

  //
  // Allocate a protocol instance structure
  //
  Status = mBootServices->AllocatePool (
                            EfiBootServicesData,
                            sizeof (OPAL_STORAGE_PROTOCOL),
                            (VOID **)&mStorageProtocol
                            );
  if (EFI_ERROR (Status)) {
    goto EXIT;
  }

  //
  // Populate the protocol dispatch table with binding Start/Stop
  //
  mStorageProtocol->Send = (OPAL_STORAGE_SEND)OpalSecurityBindingStart;
  mStorageProtocol->Recv = (OPAL_STORAGE_RECV)OpalSecurityBindingStop;

  //
  // Install the Opal Security Protocol onto the image handle
  //
  {
    EFI_GUID OpalProtocolGuid = OPAL_SECURITY_PROTOCOL_GUID;
    Status = BootServices->InstallMultipleProtocolInterfaces (
                             &OpalProtocolGuid,
                             &OpalProtocolGuid,
                             NULL
                             );
  }

  if (EFI_ERROR (Status)) {
    OPAL_ASSERT (!EFI_ERROR (Status));
    goto EXIT;
  }

  //
  // Set the MemoryOverwriteRequestControl variable per UEFI spec
  //
  {
    EFI_GUID MorGuid = MEMORY_OVERWRITE_REQUEST_CONTROL_GUID;
    UINT64   MorAttributes = 1;
    UINT8    MorValue = 0;

    RuntimeServices->SetVariable (
                      L"MemoryOverwriteRequestControl",
                      &MorGuid,
                      0,
                      &MorAttributes,
                      &MorValue
                      );
  }

EXIT:
  return Status;
}

//------------------------------------------------------------------------------
// Driver Binding Start
//------------------------------------------------------------------------------

EFI_STATUS
EFIAPI
OpalSecurityBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
  )
{
  EFI_STATUS  Status;
  UINT8       Buffer[510];
  UINT64      StorageIoGuid;

  //
  // Zero the buffer used for TCG command data
  //
  OpalMemset (Buffer, 0, sizeof (Buffer));
  StorageIoGuid = 0;

  //
  // Check if the controller supports TCG Storage IO (type == 1)
  //
  if (StorageIoType == 1)
  {
    //
    // Copy the device context from the controller handle
    //
    CopyMem (Buffer, (VOID *)((UINTN)ControllerHandle + 35), 4 * sizeof (UINT128));
    StorageIoGuid = *((UINT64 *)This);
  }

  //
  // Verify TCG SSC feature bit in Level 0 discovery data (bit 94)
  //
  if ((Buffer[94] & 1) == 0) {
    return OPAL_STATUS_NOT_READY;
  }

  //
  // Check if the protocol already exists on this controller
  //
  {
    EFI_GUID StorageGuid = OPAL_STORAGE_PROTOCOL_GUID;
    Status = mBootServices->LocateProtocol (
                              &StorageGuid,
                              NULL,
                              NULL
                              );
    if (!EFI_ERROR (Status)) {
      return OPAL_STATUS_ALREADY_STARTED;
    }
  }

  //
  // Allocate the child protocol instance (32 bytes)
  //
  Status = mBootServices->AllocatePool (
                            EfiBootServicesData,
                            32,
                            (VOID **)&mChildProtocol
                            );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (StorageIoType == 1)
  {
    //
    // Initialize child protocol with TCG send/recv handlers
    //
    mChildProtocol->Send    = (OPAL_STORAGE_SEND)TcgStorageIoSend;
    mChildProtocol->Recv    = (OPAL_STORAGE_RECV)TcgStorageIoRecv;
    mChildProtocol->Context = (VOID *)ControllerHandle;

    ((OPAL_STORAGE_PROTOCOL *)ControllerHandle)->Context = mChildProtocol;
  }

  //
  // Install the child protocol
  //
  {
    EFI_GUID StorageGuid = OPAL_STORAGE_PROTOCOL_GUID;
    Status = mBootServices->InstallMultipleProtocolInterfaces (
                             &StorageGuid,
                             mChildProtocol,
                             NULL
                             );
  }

  if (EFI_ERROR (Status)) {
    OPAL_ASSERT (!EFI_ERROR (Status));
    return Status;
  }

  //
  // If Opal Security is enabled, perform initial security exchange
  //
  if ((mOpalSecurityEnabled & 1) != 0 &&
      OpalSecurityAllocBuffer () >= EFI_SUCCESS)
  {
    OpalSecurityReceiveResponse (
      mChildProtocol,
      This,
      StorageIoType
      );
  }

  return Status;
}

//------------------------------------------------------------------------------
// Driver Binding Stop
//------------------------------------------------------------------------------

EFI_STATUS
EFIAPI
OpalSecurityBindingStop (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN UINTN                        NumberOfChildren,
  IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
  )
{
  EFI_STATUS  Status;
  UINT64      StorageIoGuid;
  VOID        *ChildProtocol;

  StorageIoGuid = 0;
  ChildProtocol = NULL;

  if (StorageIoType == 1)
  {
    StorageIoGuid = *((UINT64 *)This);
    ChildProtocol = ((OPAL_STORAGE_PROTOCOL *)ControllerHandle)->Context;
  }

  Status = mBootServices->UninstallMultipleProtocolInterfaces (
                            ControllerHandle,
                            &ChildProtocol,
                            NULL
                            );

  if (Status == EFI_SUCCESS && ChildProtocol != NULL)
  {
    mBootServices->FreePool (ChildProtocol);
  }

  return Status;
}

//------------------------------------------------------------------------------
// Buffer Allocation for TCG Security Protocol
//------------------------------------------------------------------------------

EFI_STATUS
OpalSecurityAllocBuffer (
  VOID
  )
{
  EFI_STATUS              Status;
  OPAL_STORAGE_PROTOCOL  *Protocol;
  VOID                   *Buffer;
  UINT64                  BufferSize;

  Protocol = mChildProtocol;
  if (Protocol == NULL) {
    return OPAL_STATUS_NOT_READY;
  }

  Buffer     = NULL;
  BufferSize = 512;

  Status = mBootServices->AllocatePool (
                            EfiBootServicesData,
                            512,
                            &Buffer
                            );
  if (EFI_ERROR (Status)) {
    return OPAL_STATUS_DEVICE_ERROR;
  }

  //
  // Issue IF-RECV (Level 0 Discovery) to read TCG capabilities
  //
  Protocol->Send (
    Protocol,
    0,
    0,
    0,
    0,
    512,
    Buffer
    );

  Protocol->SecurityProtocolBuffer = Buffer;

  return EFI_SUCCESS;
}

//------------------------------------------------------------------------------
// Process TCG Security Response (IF-RECV data parsing)
//------------------------------------------------------------------------------

EFI_STATUS
OpalSecurityReceiveResponse (
  IN  OPAL_STORAGE_PROTOCOL      *Protocol,
  IN  EFI_DRIVER_BINDING_PROTOCOL *Binding,
  IN  UINT32                      StorageIoType
  )
{
  EFI_STATUS   Status;
  UINT8        Buffer[510];
  UINT8        *DiscoveryBuffer;
  UINT16       NumDescriptors;
  UINT16       Index;
  UINT64       TmpBuffer;

  DiscoveryBuffer = (UINT8 *)Protocol->SecurityProtocolBuffer;

  OpalMemset (Buffer, 0, sizeof (Buffer));

  if (StorageIoType == 1)
  {
    CopyMem (Buffer, (VOID *)((UINTN)Binding + 35), 4 * sizeof (UINT128));
  }

  //
  // Read descriptor count from Level 0 Discovery response
  //
  NumDescriptors = _byteswap_ushort (*(UINT16 *)(DiscoveryBuffer + 6));
  if (NumDescriptors == 0) {
    return OPAL_STATUS_NOT_READY;
  }

  //
  // Parse TCG Level 0 Discovery descriptors
  //
  for (Index = 0; Index < NumDescriptors; Index++)
  {
    UINT8 FeatureCode = *(UINT8 *)(DiscoveryBuffer + 8 + Index);

    if (FeatureCode == 0x02)
    {
      //
      // TCG Storage SSC feature found -- send IF-SEND command
      //
      TmpBuffer = 0;
      Status = mBootServices->AllocatePool (
                                EfiBootServicesData,
                                512,
                                &TmpBuffer
                                );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      mBootServices->SetMem ((VOID *)TmpBuffer, 512, 0);
      Protocol->Send (
        Protocol,
        0,
        0,
        2,
        0x0400,
        512,
        TmpBuffer
        );

      mBootServices->FreePool ((VOID *)TmpBuffer);
      return EFI_SUCCESS;
    }

    if (FeatureCode == 0xEE && (Buffer[0x8A] & 0x80) == 0)
    {
      //
      // Opal SSC v2 (Pyrite) feature -- issue IF-RECV
      //
      Status = OpalSecuritySendCommand (Protocol);
      if (EFI_ERROR (Status)) {
        OPAL_ASSERT (!EFI_ERROR (Status));
      }
      return EFI_SUCCESS;
    }
  }

  return EFI_SUCCESS;
}

//------------------------------------------------------------------------------
// TCG Storage IF-SEND Command
//------------------------------------------------------------------------------

EFI_STATUS
OpalSecuritySendCommand (
  IN OPAL_STORAGE_PROTOCOL *Protocol
  )
{
  EFI_STATUS   Status;
  VOID         *CmdResponseBuffer;
  VOID         *SmallBuffer;
  UINT64       ParameterLength;
  UINT16       CommandIteration;

  CmdResponseBuffer = NULL;
  CmdParamBuffer    = NULL;
  ParameterLength   = 4;

  Status = mBootServices->AllocatePool (
                            EfiBootServicesData,
                            4,
                            &CmdResponseBuffer
                            );
  if (EFI_ERROR (Status)) {
    return OPAL_STATUS_DEVICE_ERROR;
  }

  //
  // IF-RECV with Protocol = 0xEE, ComId = 256
  //
  CommandIteration = 256;
  Status = ((OPAL_STORAGE_RECV_PTR)Protocol->Context)->Recv (
    Protocol,
    0,
    0,
    0xEE,
    CommandIteration,
    512,
    CmdResponseBuffer
    );

  if (EFI_ERROR (Status)) {
    goto CLEANUP;
  }

  //
  // Verify the COM ID iteration matches
  //
  while (CommandIteration != _byteswap_ushort (*(UINT16 *)(CmdResponseBuffer + 2)))
  {
    CommandIteration++;
    if (CommandIteration >= 0x200) {
      goto CLEANUP;
    }
  }

  //
  // Final IF-RECV with Level 1 discovery ProtocolId
  //
  SmallBuffer = NULL;
  Status = mBootServices->AllocatePool (
                            EfiBootServicesData,
                            4,
                            &SmallBuffer
                            );
  if (EFI_ERROR (Status)) {
    return OPAL_STATUS_DEVICE_ERROR;
  }

  Status = ((OPAL_STORAGE_RECV_PTR)Protocol->Context)->Recv (
    Protocol,
    0,
    0,
    0xEE,
    0x0500,
    512,
    SmallBuffer
    );

  mBootServices->FreePool (SmallBuffer);

CLEANUP:
  mBootServices->FreePool (CmdResponseBuffer);
  return Status;
}

//------------------------------------------------------------------------------
// TCG IF-RECV (receive security data without transfer length)
//------------------------------------------------------------------------------

EFI_STATUS
EFIAPI
TcgStorageIoRecv (
  IN  OPAL_STORAGE_PROTOCOL  *This,
  IN  UINT32                 StorageIoType,
  IN  UINT64                 Timeout,
  IN  UINT8                  Command,
  IN  UINT16                 ProtocolId,
  IN  UINT64                 BufferLength,
  IN  VOID                   *Buffer
  )
{
  OPAL_STORAGE_PROTOCOL   *Parent;
  UINT64                  BlockIo;
  UINT32                  *TcgParams;
  UINT64                  Lba;
  UINT8                   TcgPacket[49];

  Parent    = (OPAL_STORAGE_PROTOCOL *)This->Context;
  BlockIo   = *(UINT64 *)((UINTN)Parent + 848);
  TcgParams = *(UINT32 **)(BlockIo + 864);

  if (!TcgParams || !BlockIo) {
    return OPAL_STATUS_NOT_READY;
  }

  if (*TcgParams != StorageIoType) {
    return OPAL_STATUS_INVALID_PARAMETER;
  }

  Lba = (BufferLength / TcgParams[3]) >> 8;

  OpalMemset (TcgPacket, 0, sizeof (TcgPacket));

  //
  // Build TCG IF-RECV packet
  //
  TcgPacket[12] = Command;
  TcgPacket[18] = HIBYTE (ProtocolId);
  TcgPacket[20] = ProtocolId;

  if (BufferLength)
  {
    TcgPacket[16] = (UINT8)Lba;
    TcgPacket[23] = 0x5E;                        // IF-RECV opcode

    if (Timeout) {
      TcgPacket[25] = (UINT8)(Timeout / 0x2710);
    } else {
      *(UINT64 *)&TcgPacket[17] = -1;
    }

    *(UINT64 *)&TcgPacket[0] = (UINT64)Buffer;
    *(UINT32 *)&TcgPacket[4] = (UINT32)BufferLength;

    if (Buffer) {
      return ((UINT64 (*)(VOID *, VOID *, UINT8))BlockIo)(
               Parent,
               TcgPacket,
               1
               );
    }
  }
  else
  {
    TcgPacket[23] = 0x5B;                        // IF-RECV (no data)

    if (Timeout) {
      TcgPacket[25] = (UINT8)(Timeout / 0x2710);
    } else {
      *(UINT64 *)&TcgPacket[17] = -1;
    }

    *(UINT32 *)&TcgPacket[4] = 0;
    *(UINT64 *)&TcgPacket[0] = (UINT64)Buffer;

    return ((UINT64 (*)(VOID *, VOID *))BlockIo)(
             Parent,
             TcgPacket
             );
  }

  return OPAL_STATUS_INVALID_PARAMETER;
}

//------------------------------------------------------------------------------
// TCG IF-SEND (send security data with transfer length)
//------------------------------------------------------------------------------

EFI_STATUS
EFIAPI
TcgStorageIoSend (
  IN  OPAL_STORAGE_PROTOCOL  *This,
  IN  UINT32                 StorageIoType,
  IN  UINT64                 Timeout,
  IN  UINT8                  Command,
  IN  UINT16                 ProtocolId,
  IN  UINT64                 BufferLength,
  IN  VOID                   *Buffer,
  OUT UINT64                 *TransferLength OPTIONAL
  )
{
  OPAL_STORAGE_PROTOCOL   *Parent;
  UINT64                  BlockIo;
  UINT32                  *TcgParams;
  UINT64                  Lba;
  UINT64                  AlignedLba;
  UINT8                   TcgPacket[49];
  EFI_STATUS              Status;

  Parent    = (OPAL_STORAGE_PROTOCOL *)This->Context;
  BlockIo   = *(UINT64 *)((UINTN)Parent + 864);
  TcgParams = *(UINT32 **)(BlockIo + 8);

  if (!BlockIo || !TcgParams) {
    return OPAL_STATUS_NOT_READY;
  }

  if (*TcgParams != StorageIoType) {
    return OPAL_STATUS_INVALID_PARAMETER;
  }

  Lba        = (BufferLength / TcgParams[3]) >> 8;
  AlignedLba = BufferLength / TcgParams[3];

  OpalMemset (TcgPacket, 0, sizeof (TcgPacket));

  if (BufferLength)
  {
    if (!Buffer || !TransferLength) {
      return OPAL_STATUS_INVALID_PARAMETER;
    }

    TcgPacket[14] = (UINT8)AlignedLba;
    TcgPacket[16] = (UINT8)Lba;
    TcgPacket[18] = HIBYTE (ProtocolId);
    TcgPacket[20] = ProtocolId;
    TcgPacket[23] = 0x5C;                        // IF-SEND opcode
    TcgPacket[12] = Command;

    if (Timeout) {
      TcgPacket[25] = (UINT8)(Timeout / 0x2710);
    } else {
      *(UINT64 *)&TcgPacket[17] = -1;
    }

    *(UINT64 *)&TcgPacket[0] = (UINT64)Buffer;
    *(UINT32 *)&TcgPacket[4] = (UINT32)BufferLength;

    Status = ((UINT64 (*)(VOID *, VOID *, UINT64))BlockIo)(
               Parent,
               TcgPacket,
               0
               );
  }
  else
  {
    TcgPacket[18] = HIBYTE (ProtocolId);
    TcgPacket[20] = ProtocolId;
    TcgPacket[17] = 1;
    TcgPacket[23] = 0x5B;                        // IF-SEND (no data)
    TcgPacket[12] = Command;

    if (Timeout) {
      TcgPacket[25] = (UINT8)(Timeout / 0x2710);
    } else {
      *(UINT64 *)&TcgPacket[17] = -1;
    }

    *(UINT32 *)&TcgPacket[4] = 0;
    *(UINT64 *)&TcgPacket[0] = (UINT64)Buffer;

    Status = ((UINT64 (*)(VOID *, VOID *))BlockIo)(
               Parent,
               TcgPacket
               );
  }

  if (EFI_ERROR (Status))
  {
    if (TransferLength != NULL) {
      *TransferLength = 0;
    }
  }
  else
  {
    if (TransferLength != NULL) {
      *TransferLength = *(UINT32 *)&TcgPacket[4];
    }
  }

  return Status;
}

//------------------------------------------------------------------------------
// Debug Support Functions
//------------------------------------------------------------------------------

STATIC
VOID *
OpalGetDebugContext (
  VOID
  )
{
  STATIC VOID *mDebugContext = NULL;

  if (mDebugContext == NULL)
  {
    UINTN  RngValue;

    RngValue = gBS->GetTimerValue (31);
    gBS->Stall (RngValue);

    if (RngValue <= 0x10)
    {
      EFI_STATUS  Status;
      EFI_GUID    Guid = OPAL_STORAGE_PROTOCOL_GUID;

      Status = gBS->LocateHandleBuffer (
                      ByProtocol,
                      &Guid,
                      NULL,
                      &mDebugContext
                      );
      if (EFI_ERROR (Status)) {
        mDebugContext = NULL;
      }
    }
  }

  return mDebugContext;
}

STATIC
VOID
OpalDebugAssertPrint (
  IN EFI_STATUS  Status,
  IN CHAR8       *Format,
  ...
  )
{
  VOID    *DebugContext;
  VA_LIST Args;

  VA_START (Args, Format);
  DebugContext = OpalGetDebugContext ();

  if (DebugContext != NULL)
  {
    UINTN DebugLevel;

    DebugLevel = OpalReadCmosDebugLevel ();
    if ((DebugLevel & Status) != 0)
    {
      ((VOID (*)(EFI_STATUS, CHAR8 *, VA_LIST))DebugContext)(
        Status,
        Format,
        Args
        );
    }
  }
  VA_END (Args);
}

STATIC
VOID
OpalAssertHandler (
  IN CHAR8  *File,
  IN UINTN  Line,
  IN CHAR8  *Condition
  )
{
  VOID *DebugContext;

  DebugContext = OpalGetDebugContext ();
  if (DebugContext != NULL)
  {
    ((VOID (*)(CHAR8 *, UINTN, CHAR8 *))DebugContext)(
      File,
      Line,
      Condition
      );
  }
}

//------------------------------------------------------------------------------
// HOB List Retrieval
//------------------------------------------------------------------------------

STATIC
VOID *
OpalGetHobList (
  VOID
  )
{
  STATIC VOID *mHobList = NULL;

  if (mHobList == NULL)
  {
    EFI_CONFIGURATION_TABLE *ConfigTable;
    UINTN                    TableIndex;
    EFI_GUID                 HobListGuid = gEfiHobListGuid;

    ConfigTable = (EFI_CONFIGURATION_TABLE *)gST->ConfigurationTable;
    mHobList    = NULL;

    if (gST->NumberOfTableEntries > 0)
    {
      for (TableIndex = 0; TableIndex < gST->NumberOfTableEntries; TableIndex++)
      {
        if (OpalCompareGuid (
              &HobListGuid,
              &ConfigTable[TableIndex].VendorGuid
              ))
        {
          mHobList = ConfigTable[TableIndex].VendorTable;
          break;
        }
      }
    }

    if (mHobList == NULL)
    {
      OpalDebugAssertPrint (
        OPAL_STATUS_NOT_FOUND,
        "\nASSERT_EFI_ERROR (Status = %r)\n",
        OPAL_STATUS_NOT_FOUND
        );
      OpalAssertHandler (
        "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
        54,
        "!EFI_ERROR (Status)"
        );
    }
  }

  if (mHobList == NULL)
  {
    OpalAssertHandler (
      "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
      55,
      "mHobList != ((void *) 0)"
      );
  }

  return mHobList;
}

//------------------------------------------------------------------------------
// Utility Functions
//------------------------------------------------------------------------------

STATIC
UINTN
OpalReadCmosDebugLevel (
  VOID
  )
{
  UINT8   CmosValue;
  STATIC UINT8  sCachedValue = 0;

  __outbyte (0x70, (__inbyte (0x70) & 0x80) | RTC_CMOS_DEBUG_LEVEL_REGISTER);
  CmosValue = __inbyte (0x71);

  sCachedValue = CmosValue;

  if (CmosValue > 3)
  {
    if (CmosValue == 0)
    {
      sCachedValue = (*(UINT8 *)0xFDAF0490 & 2) | 1;
    }
  }

  if (sCachedValue - 1 > 0xFD)
  {
    return 0;
  }

  if (sCachedValue == 1)
  {
    return OPAL_STATUS_NOT_READY;
  }

  return OPAL_STATUS_NOT_FOUND;
}

STATIC
BOOLEAN
OpalCompareGuid (
  IN EFI_GUID  *Guid1,
  IN EFI_GUID  *Guid2
  )
{
  EFI_GUID  CandidateGuid = *Guid2;

  return (OpalReadUnaligned64 (&Guid1->Data1) == OpalReadUnaligned64 (&CandidateGuid.Data1) &&
          OpalReadUnaligned64 (&Guid1->Data4) == OpalReadUnaligned64 (&Guid2->Data4));
}

STATIC
UINT64
OpalReadUnaligned64 (
  IN CONST VOID  *Buffer
  )
{
  if (Buffer == NULL) {
    OpalAssertHandler (
      "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
      192,
      "Buffer != ((void *) 0)"
      );
  }

  return *(UINT64 *)Buffer;
}

STATIC
VOID *
OpalMemset (
  OUT VOID    *Buffer,
  IN  INT32   Value,
  IN  UINTN   Length
  )
{
  return memset (Buffer, Value, Length);
}

STATIC
VOID *
OpalMemmove (
  OUT VOID        *Destination,
  IN  CONST VOID  *Source,
  IN  UINTN       Length
  )
{
  return memmove (Destination, Source, Length);
}