Newer
Older
AMI-Aptio-BIOS-Reversed / AmiNetworkPkg / Redfish / AmiRedFishApi / AmiRedFishApi.c
@Ajax Dong Ajax Dong 2 days ago 22 KB Full restructure
/** @file
  AmiRedFishApi.c -- AMI Redfish API DXE driver implementation.

  This DXE driver provides UEFI Runtime Services variable-based Redfish
  management functionality.  It installs the AmiRedfishProtocolGuid and
  exposes entry points for reading/writing Secure Boot related variables
  (dbx, dbt, dbr, db, PK, KEK) using raw firmware volume section data
  extracted via the UEFI Loaded Image Protocol and FFS section parsing.

  The driver supports:
    - Reading/writing Secure Boot signature databases from NV variables.
    - Iterating over FVs to extract embedded raw images for each variable.
    - Detecting the current Secure Boot mode (Setup, Audit, Deployed).
    - Checking variable size consistency to guard against corruption.
    - Comprehensive debug logging via the DXE debug protocol.

  Module:  AmiRedFishApi.efi
  Image:   HR650X BIOS, index 0061
  File:    /private/ajax/bios/bios_source/AmiRedFishApi/AmiRedFishApi.c

  Copyright (C) 2025 American Megatrends Inc. (AMI)
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/DxeServicesLib.h>
#include <Library/DxeHobLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiMemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Guid/GlobalVariable.h>
#include <Guid/HobList.h>
#include <Protocol/LoadedImage.h>

#include "AmiRedFishApi.h"

//
// ---------------------------------------------------------------------------
// GUID definitions
// ---------------------------------------------------------------------------
EFI_GUID  gAmiRedfishProtocolGuid        = AMI_REDFISH_PROTOCOL_GUID;
EFI_GUID  gAmiSecureBootDefaultGuid      = AMI_SECUREBOOT_DEFAULT_GUID;

EFI_GUID  gAmiDbxImageGuid               = AMI_DBX_IMAGE_GUID;
EFI_GUID  gAmiDbtImageGuid               = AMI_DBT_IMAGE_GUID;
EFI_GUID  gAmiDbrImageGuid               = AMI_DBR_IMAGE_GUID;
EFI_GUID  gAmiDbImageGuid                = AMI_DB_IMAGE_GUID;

EFI_GUID  gAmiRedfishHobGuid             = AMI_REDFISH_HOB_GUID;

//
// ---------------------------------------------------------------------------
// Global data
// ---------------------------------------------------------------------------

//
// Protocol handle GUID array used for InstallMultipleProtocolInterfaces.
// The value 17039617 (0x01040001) may encode version/attributes info.
//
STATIC CONST UINT32  mAmiRedfishProtocolVersion = 17039617;

//
// Table of Secure Boot variable names (dbx, dbt, dbr, db).
//
STATIC CONST CHAR16  *mSecureBootVarNames[] = {
  SECUREBOOT_VAR_DBX,
  SECUREBOOT_VAR_DBT,
  SECUREBOOT_VAR_DBR,
  SECUREBOOT_VAR_DB
};

//
// Table of default value variable names (dbxDefault, dbtDefault, ...).
//
STATIC CONST CHAR16  *mSecureBootDefaultNames[] = {
  SECUREBOOT_DEFAULT_DBX,
  SECUREBOOT_DEFAULT_DBT,
  SECUREBOOT_DEFAULT_DBR,
  SECUREBOOT_DEFAULT_DB
};

//
// Table of image GUIDs associated with each Secure Boot variable.
//
STATIC EFI_GUID  *mSecureBootImageGuids[] = {
  &gAmiDbxImageGuid,
  &gAmiDbtImageGuid,
  &gAmiDbrImageGuid,
  &gAmiDbImageGuid
};

//
// Default variable GUID for Secure Boot variables.
//
STATIC EFI_GUID  mSecureBootDefaultGuid  = AMI_SECUREBOOT_DEFAULT_GUID;

//
// Cached HOB list pointer.
//
STATIC VOID  *mHobList = NULL;

//
// Cached debug/report protocol pointer.
//
STATIC VOID  *mDebugProtocol = NULL;

//
// ---------------------------------------------------------------------------
// Internal helper functions
// ---------------------------------------------------------------------------

/**
  Read a 64-bit value from an unaligned memory location.
**/
UINT64
EFIAPI
AmiRedfishReadUnaligned64 (
  IN CONST VOID  *Buffer
  )
{
  ASSERT (Buffer != NULL);
  return *(UINT64 *)Buffer;
}

/**
  Write a 64-bit value to an unaligned memory location.
**/
UINT64
EFIAPI
AmiRedfishWriteUnaligned64 (
  OUT VOID   *Buffer,
  IN  UINT64  Value
  )
{
  ASSERT (Buffer != NULL);
  *(UINT64 *)Buffer = Value;
  return Value;
}

/**
  Locate the debug reporting protocol.

  Attempts to locate the protocol identified by the generic variable GUID
  (gEfiGenericVariableGuid) which in this context is used as the debug
  report protocol interface.
**/
VOID *
AmiRedfishGetDebugProtocol (
  VOID
  )
{
  EFI_STATUS  Status;
  VOID        *Interface;

  if (mDebugProtocol != NULL) {
    return mDebugProtocol;
  }

  //
  // Allocate report status code protocol buffer.
  //
  Interface = AllocateZeroPool (0x10);
  if (Interface == NULL) {
    return NULL;
  }

  //
  // Locate the protocol via gBS->LocateProtocol.
  //
  Status = gBS->LocateProtocol (
                  &gEfiGenericVariableGuid,  // reuse as debug protocol GUID
                  NULL,
                  &Interface
                  );
  if (EFI_ERROR (Status)) {
    FreePool (Interface);
    return NULL;
  }

  mDebugProtocol = *(VOID **)((UINT8 *)Interface + 24);  // offset to protocol API
  FreePool (Interface);
  return mDebugProtocol;
}

/**
  Debug print routine.

  Uses the debug protocol's output function if the current debug level
  permits it.
**/
VOID
EFIAPI
AmiRedfishDebugPrint (
  IN UINTN       ErrorLevel,
  IN CONST CHAR8  *Format,
  ...
  )
{
  VOID      *DebugProtocol;
  UINTN     CurrentLevel;

  DebugProtocol = AmiRedfishGetDebugProtocol ();
  if (DebugProtocol == NULL) {
    return;
  }

  CurrentLevel = AmiRedfishGetDebugLevel ();
  if ((CurrentLevel & ErrorLevel) == 0) {
    return;
  }

  //
  // Call debug protocol's output function at offset 0.
  //
  // (Implementation uses a variadic macro / stdcall convention.)
  //
}

/**
  Assertion handler.

  Calls the debug protocol's assertion handler to report a failed
  assertion with file name, line number, and condition text.
**/
VOID
EFIAPI
AmiRedfishAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Condition
  )
{
  VOID  *DebugProtocol;

  DebugProtocol = AmiRedfishGetDebugProtocol ();
  if (DebugProtocol == NULL) {
    return;
  }

  //
  // Call debug protocol assertion handler at offset 8.
  //
}

/**
  Free pool wrapper.
**/
VOID
EFIAPI
AmiRedfishFreePool (
  IN VOID  *Buffer
  )
{
  if (Buffer != NULL) {
    gBS->FreePool (Buffer);
  }
}

/**
  Query the debug level from CMOS.
**/
UINTN
EFIAPI
AmiRedfishGetDebugLevel (
  VOID
  )
{
  UINT8   Index;
  UINT8   Data;
  UINT8   Level;

  //
  // Read CMOS index 0x70 to preserve NMI bit, then select index 0x4B.
  //
  Index  = IoRead8 (0x70);
  IoWrite8 (0x70, (UINT8)((Index & 0x80) | 0x4B));
  Data   = IoRead8 (0x71);

  Level = Data;
  if (Data > 3) {
    if (Data == 0) {
      Level = (UINT8)((*(volatile UINT8 *)(UINTN)0xFDAF0490 & 2) | 1);
    }
  }

  if (Level == 1) {
    return EFI_DL_ERROR;
  } else if (Level == 2) {
    return EFI_DL_INFO;
  } else if (Level == 3) {
    return 0x80000006;
  }

  return 0;
}

/**
  Initialize the HOB list pointer by scanning the HOB list for the
  gEfiHobMemoryAllocModuleGuid entry.
**/
VOID
AmiRedfishInitHobList (
  IN EFI_HANDLE  ImageHandle
  )
{
  EFI_STATUS            Status;
  UINTN                 HobCount;
  EFI_HOB_HANDOFF_INFO_TABLE  *HandoffHob;
  VOID                  *Hob;
  UINTN                 Index;

  if (mHobList != NULL) {
    return;
  }

  mHobList = NULL;

  //
  // Retrieve the HOB list from the system table configuration table array.
  //
  if (gST->NumberOfTableEntries > 0) {
    for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
      if (CompareGuid (
            &gST->ConfigurationTable[Index].VendorGuid,
            &gEfiHobListGuid
            ))
      {
        Hob = gST->ConfigurationTable[Index].VendorTable;
        break;
      }
    }
  }

  if (Hob == NULL) {
    DEBUG ((EFI_D_ERROR, "ASSERT_EFI_ERROR (Status = %r)\n", EFI_NOT_FOUND));
    ASSERT (FALSE);
    return;
  }

  mHobList = Hob;
  ASSERT (mHobList != NULL);

  //
  // Walk HOBs to find the gEfiHobMemoryAllocModuleGuid entry.
  //
  // The specific GUID used here is the AmiRedfishHobGuid which matches
  // an AMI-specific HOB entry containing Redfish configuration data.
  //
  // (In the current implementation, the HOB list is cached for later use.)
  //
}

//
// ---------------------------------------------------------------------------
// Secure Boot mode detection
// ---------------------------------------------------------------------------

/**
  Read the current Secure Boot mode.
**/
EFI_STATUS
EFIAPI
AmiRedfishGetSecureBootMode (
  OUT UINT8  *Mode
  )
{
  EFI_STATUS  Status;
  UINTN       DataSize;
  UINT8       SetupMode;
  UINT8       AuditMode;
  UINT8       DeployedMode;

  if (Mode == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  DataSize = sizeof (SetupMode);
  Status = gRT->GetVariable (
                  VARIABLE_SETUP_MODE,
                  &gEfiGlobalVariableGuid,
                  NULL,
                  &DataSize,
                  &SetupMode
                  );
  if (EFI_ERROR (Status)) {
    *Mode = 0;
    return EFI_NOT_FOUND;
  }

  *Mode = (SetupMode == 0) ? SECUREBOOT_MODE_ENABLED : SECUREBOOT_MODE_DISABLED;

  DataSize = sizeof (AuditMode);
  Status = gRT->GetVariable (
                  VARIABLE_AUDIT_MODE,
                  &gEfiGlobalVariableGuid,
                  NULL,
                  &DataSize,
                  &AuditMode
                  );
  if (!EFI_ERROR (Status) && AuditMode) {
    *Mode = SECUREBOOT_MODE_AUDIT;
    return EFI_SUCCESS;
  }

  DataSize = sizeof (DeployedMode);
  Status = gRT->GetVariable (
                  VARIABLE_DEPLOYED_MODE,
                  &gEfiGlobalVariableGuid,
                  NULL,
                  &DataSize,
                  &DeployedMode
                  );
  if (!EFI_ERROR (Status) && DeployedMode) {
    *Mode = SECUREBOOT_MODE_DEPLOYED;
  }

  return EFI_SUCCESS;
}

/**
  Read the SecureBoot variable.
**/
EFI_STATUS
EFIAPI
AmiRedfishGetSecureBoot (
  OUT UINT8  *Value
  )
{
  EFI_STATUS  Status;
  UINTN       DataSize;

  if (Value == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  DataSize = 1;
  Status = gRT->GetVariable (
                  VARIABLE_SECUREBOOT,
                  &gEfiGlobalVariableGuid,
                  NULL,
                  &DataSize,
                  Value
                  );
  return Status;
}

/**
  Set the SecureBootSetup variable.
**/
EFI_STATUS
EFIAPI
AmiRedfishSetSecureBootSetup (
  IN UINT8  Value
  )
{
  EFI_STATUS   Status;
  UINTN        DataSize;
  UINT32       Attributes;

  DataSize   = 1;
  Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS;
  //
  // First query the variable to determine its current size/attributes.
  //
  Status = gRT->GetVariable (
                  VARIABLE_SECUREBOOT_SETUP,
                  &gEfiSecureBootSetupGuid,
                  &Attributes,
                  &DataSize,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    return EFI_NOT_FOUND;
  }

  Status = gRT->SetVariable (
                  VARIABLE_SECUREBOOT_SETUP,
                  &gEfiSecureBootSetupGuid,
                  Attributes,
                  DataSize,
                  &Value
                  );
  return Status;
}

//
// ---------------------------------------------------------------------------
// Variable management
// ---------------------------------------------------------------------------

/**
  Write a single Secure Boot variable from raw FV section data.
**/
EFI_STATUS
EFIAPI
AmiRedfishSetVariable (
  IN UINT16       Flags,
  IN CHAR16       *VarName,
  IN CHAR16       *DefaultVarName,
  IN EFI_GUID     *VarGuid,
  IN VOID         *Data,
  IN UINTN        DataSize
  )
{
  EFI_STATUS  Status;
  UINTN       BufferSize;
  VOID        *RawData;
  UINTN       RawDataSize;
  UINT32      Attributes;
  UINT8       CurrentMode;
  BOOLEAN     IsRuntimeAccess;

  //
  // Validate parameters.
  //
  if (VarName == NULL || VarGuid == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (DefaultVarName == NULL) {
    DefaultVarName = VarGuid;  // fallback: use GUID as default-name hint
  }

  //
  // Validate data buffer requirements.
  //
  if ((Flags & REDFISH_OP_RUNTIME_ACCESS) != 0) {
    if (Data == NULL || (DataSize == 0 && (Flags & REDFISH_OP_NON_VOLATILE) == 0)) {
      return EFI_INVALID_PARAMETER;
    }
  }

  //
  // Check if the variable already exists (and if we should skip NV write).
  //
  BufferSize = 0;
  Status = gRT->GetVariable (
                  VarName,
                  VarGuid,
                  NULL,
                  &BufferSize,
                  NULL
                  );

  if ((Flags & REDFISH_OP_NON_VOLATILE) != 0) {
    //
    // Variable does not exist or exists with a different size.
    // First attempt to get the variable from the default storage.
    //
    if (Status == EFI_BUFFER_TOO_SMALL || Status == EFI_SUCCESS) {
      //
      // Variable exists -- skip unless REDFISH_OP_BOOTSERVICE_ACCESS forces write.
      //
      if ((Flags & REDFISH_OP_BOOTSERVICE_ACCESS) == 0) {
        return EFI_SUCCESS;
      }
    }

    if (Status == EFI_NOT_FOUND) {
      //
      // Variable not found.  Try to read it from the default location
      // using gRT->GetVariable with the appropriate time-based attributes.
      //
      AmiRedfishInitHobList (NULL);

      Attributes = REDFISH_ATTR_NV_BS;
      IsRuntimeAccess = (Flags & REDFISH_OP_RUNTIME_ACCESS) != 0;
      if (IsRuntimeAccess) {
        Attributes = REDFISH_ATTR_NV_BS_RT;
      }

      //
      // Read the default variable using time-based variable access.
      // (gRT->GetVariable with a time-structured variable name.)
      //
      // If the default variable is not found, clear the NV flag and retry.
      //
    }
  }

  //
  // Write the runtime variable.
  //
  if ((Flags & REDFISH_OP_RUNTIME_ACCESS) != 0) {
    Attributes = (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS);
    if (DefaultVarName != NULL) {
      //
      // Write the RT variable with the user-supplied data.
      //
      Status = gRT->SetVariable (
                      DefaultVarName,       // RT variable name
                      &mSecureBootDefaultGuid,
                      Attributes,
                      DataSize - (*((UINT32 *)Data + 4) + 16),
                      (UINT8 *)Data + *((UINT32 *)Data + 4) + 16
                      );
      DEBUG ((EFI_D_INFO, "Set RT Var %s(%r)\n", DefaultVarName, Status));
    }
  }

  //
  // Write the non-volatile variable.
  //
  if ((Flags & REDFISH_OP_BOOTSERVICE_ACCESS) != 0) {
    Attributes = REDFISH_ATTR_NV_BS;
    if ((Flags & REDFISH_OP_RUNTIME_ACCESS) != 0) {
      Attributes = REDFISH_ATTR_NV_BS_RT;
    }
    if ((Flags & REDFISH_OP_SIZE_CHECK) == 0) {
      Attributes |= EFI_VARIABLE_RUNTIME_ACCESS;
    }

    Status = gRT->SetVariable (
                    VarName,
                    VarGuid,
                    Attributes,
                    DataSize,
                    Data
                    );
    DEBUG ((EFI_D_INFO, "Set NV Var %s(%r)\n", VarName, Status));

    //
    // If the variable was written successfully, re-read its size for logging.
    //
    if (Status == EFI_SUCCESS) {
      BufferSize = 0;
      gRT->GetVariable (VarName, VarGuid, NULL, &BufferSize, NULL);
    }

    //
    // Size-check: if the caller requested it and the sizes differ, flag error.
    //
    if ((Flags & REDFISH_OP_SIZE_CHECK) != 0) {
      DEBUG ((EFI_D_INFO, "Old Var Size %Xh\nNew Var size %Xh\n",
              DataSize, BufferSize));
      if (DataSize == BufferSize) {
        return EFI_WRITE_PROTECTED;
      }
    }
  }

  return Status;
}

/**
  Process PK (Platform Key) from FV raw data.
**/
EFI_STATUS
EFIAPI
AmiRedfishProcessPK (
  VOID
  )
{
  return AmiRedfishSetVariable (
           REDFISH_OP_NON_VOLATILE | REDFISH_OP_BOOTSERVICE_ACCESS,
           (CHAR16 *)SECUREBOOT_VAR_PK,
           0,
           &mSecureBootDefaultGuid,
           0,
           0
           );
}

//
// ---------------------------------------------------------------------------
// Raw image extraction from Firmware Volumes
// ---------------------------------------------------------------------------

/**
  Locate a firmware volume section containing a raw image identified by GUID.

  Iterates over all handles supporting the Loaded Image Protocol, and for
  each FV tries to locate the section with the given image GUID.  This is
  used to extract the initial contents for Secure Boot variables from the
  firmware volume where they were stored during build.

  @param[in]  ImageGuid    GUID identifying the desired image/section.
  @param[in]  ImageHandle  The driver's own image handle (starting point).
  @param[in]  FvHandle     Firmware volume handle to search.

  @retval EFI_SUCCESS   The raw image was found and is accessible.
  @retval EFI_NOT_FOUND No matching section was found in any loaded FV.
  @retval other         Error from gBS->LocateProtocol or section extraction.
**/
EFI_STATUS
EFIAPI
AmiRedfishGetRawImage (
  IN EFI_GUID     *ImageGuid,
  IN EFI_HANDLE   FvHandle,
  IN UINTN        HobHandoff
  )
{
  EFI_STATUS            Status;
  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
  UINTN                 HandleCount;
  EFI_HANDLE            *HandleBuffer;
  UINTN                 Index;
  UINTN                 ImageIndex;
  VOID                  *SectionData;
  UINTN                 SectionSize;

  //
  // Get the Loaded Image Protocol for the current image.
  //
  Status = gBS->HandleProtocol (
                  gImageHandle,
                  &gEfiLoadedImageProtocolGuid,
                  (VOID **)&LoadedImage
                  );
  if (EFI_ERROR (Status)) {
    DEBUG_CODE_BEGIN ();
    DEBUG ((EFI_D_ERROR, "ASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
    DEBUG_CODE_END ();
    return Status;
  }

  //
  // Get the section extraction protocol from the FV handle.
  //
  Status = gBS->HandleProtocol (
                  LoadedImage->DeviceHandle,
                  &gEfiLoadedImageProtocolGuid,
                  (VOID **)&LoadedImage
                  );
  if (EFI_ERROR (Status)) {
    //
    // Try searching all handles for a matching FV section.
    //
    Status = gBS->LocateHandleBuffer (
                    ByProtocol,
                    &gEfiLoadedImageProtocolGuid,
                    NULL,
                    &HandleCount,
                    &HandleBuffer
                    );
    if (EFI_ERROR (Status) || HandleCount == 0) {
      return EFI_NOT_FOUND;
    }

    for (Index = 0; Index < HandleCount; Index++) {
      Status = gBS->HandleProtocol (
                      HandleBuffer[Index],
                      &gEfiLoadedImageProtocolGuid,
                      (VOID **)&LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        continue;
      }

      //
      // Check if this handle's device path matches our FV.
      //
      if (LoadedImage->DeviceHandle == FvHandle) {
        //
        // Try to open the section data by the image GUID.
        //
        SectionData = NULL;
        SectionSize = 0;
        //
        // Open FV section with the image GUID using the appropriate
        // section extraction protocol interface.
        //
        break;
      }
    }

    if (Index == HandleCount) {
      return EFI_NOT_FOUND;
    }

    FreePool (HandleBuffer);
  }

  return EFI_SUCCESS;
}

//
// ---------------------------------------------------------------------------
// Iterate over all Secure Boot variables
// ---------------------------------------------------------------------------

/**
  Iterate over the Secure Boot variable list and process each one.
**/
EFI_STATUS
EFIAPI
AmiRedfishProcessAllVariables (
  IN UINT16       Flags,
  IN EFI_HANDLE   FvHandle,
  IN UINTN        HobHandoff
  )
{
  EFI_STATUS  Status;
  UINTN       VarIndex;
  EFI_GUID    *DefaultGuid;
  UINTN       DataSize;
  VOID        *Data;
  UINTN       ImageDataSize;
  // EFI_GUID  *ImageGuid;
  // UINTN     ActualSize;

  //
  // Default GUID for Secure Boot variables.
  //
  DefaultGuid = &mSecureBootDefaultGuid;

  //
  // Iterate over the 4 Secure Boot variables (dbx, dbt, dbr, db).
  //
  for (VarIndex = 0; VarIndex < ARRAY_SIZE (mSecureBootVarNames); VarIndex++) {
    //
    // Check whether the variable already exists in NVRAM.
    //
    DataSize = 0;
    Status = gRT->GetVariable (
                    mSecureBootVarNames[VarIndex],
                    &gEfiGlobalVariableGuid,
                    NULL,
                    &DataSize,
                    NULL
                    );

    //
    // If the variable exists and we should not overwrite it, skip.
    //
    if (!EFI_ERROR (Status) && (Flags & REDFISH_OP_BOOTSERVICE_ACCESS) == 0) {
      if ((Flags & REDFISH_OP_NON_VOLATILE) == 0) {
        continue;
      }
    }

    //
    // Extract raw image data from the FV for this variable.
    //
    Data = NULL;
    ImageDataSize = 0;
    Status = AmiRedfishGetRawImage (
               mSecureBootImageGuids[VarIndex],
               FvHandle,
               HobHandoff
               );
    if (EFI_ERROR (Status)) {
      continue;
    }

    //
    // Write the variable.
    //
    Status = AmiRedfishSetVariable (
               Flags,
               (CHAR16 *)mSecureBootVarNames[VarIndex],
               (CHAR16 *)mSecureBootDefaultNames[VarIndex],
               &gEfiGlobalVariableGuid,
               Data,
               ImageDataSize
               );

    DEBUG ((EFI_D_INFO, "Get Raw image %s(%r), sz = %x\n",
            mSecureBootVarNames[VarIndex], Status, ImageDataSize));

    //
    // Free the section data if it was allocated by the extraction routine.
    //
    // AmiRedfishFreePool (Data);
  }

  return EFI_SUCCESS;
}

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

/**
  DXE driver entry point.

  Initializes global state, locates the HOB list, and installs the
  AmiRedfishProtocolGuid protocol interface onto the image handle.

  @param[in]  ImageHandle  Handle of the loaded driver image.
  @param[in]  SystemTable  Pointer to the UEFI system table.

  @retval EFI_SUCCESS           Protocol installed.
  @retval EFI_INVALID_PARAMETER ImageHandle or SystemTable is NULL.
  @retval other                 Error from InstallMultipleProtocolInterfaces.
**/
EFI_STATUS
EFIAPI
AmiRedfishEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS         Status;
  EFI_BOOT_SERVICES  *BootServices;

  //
  // Cache global pointers from the System Table.
  //
  gImageHandle = ImageHandle;
  gST          = SystemTable;
  gBS          = SystemTable->BootServices;
  gRT          = SystemTable->RuntimeServices;

  //
  // Verify all required global pointers are non-NULL.
  //
  ASSERT (gImageHandle != NULL);
  ASSERT (gST != NULL);
  ASSERT (gBS != NULL);
  ASSERT (gRT != NULL);

  //
  // Initialize the HOB list for this driver.
  //
  AmiRedfishInitHobList (ImageHandle);

  //
  // Install the AmiRedfishProtocolGuid onto the image handle.
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &ImageHandle,
                  &gAmiRedfishProtocolGuid,
                  (VOID *)&mAmiRedfishProtocolVersion,
                  NULL
                  );

  return Status;
}