Step to UEFI (121)EFI_SMM_ACCESS2_PROTOCOL 的使用

有时候我们需要得知当前系统中SMRAM的分配情况,这时候需可以使用 EFI_SMM_ACCESS2_PROTOCOL。关于这个 PROTOCOL,可以在PI Spec Vol4 找到。这个 PROTOCOL 接口如下:
sm1
其中我们需要关注的是 GetCapabilities。
sm2
首先通过 SmramMapSize,获得下面的 EFI_SMRAM_DESCRIPTOR的数量,之后一个个进行枚举即可。
代码中用到的一些结构体定义可以在下面这个文件中找到:
\EdkCompatibilityPkg\Foundation\Framework\Guid\SmramMemoryReserve\SmramMemoryReserve.h
例如:

//
// *******************************************************
//  EFI_SMRAM_DESCRIPTOR
// *******************************************************
//
typedef struct {
  EFI_PHYSICAL_ADDRESS  PhysicalStart;  // Phsyical location in DRAM
  EFI_PHYSICAL_ADDRESS  CpuStart;       // Address CPU uses to access the SMI handler
  // May or may not match PhysicalStart
  //
  UINT64                PhysicalSize;
  UINT64                RegionState;
} EFI_SMRAM_DESCRIPTOR;

//
// *******************************************************
//  EFI_SMRAM_STATE
// *******************************************************
//
#define EFI_SMRAM_OPEN                0x00000001
#define EFI_SMRAM_CLOSED              0x00000002
#define EFI_SMRAM_LOCKED              0x00000004
#define EFI_CACHEABLE                 0x00000008
#define EFI_ALLOCATED                 0x00000010
#define EFI_NEEDS_TESTING             0x00000020
#define EFI_NEEDS_ECC_INITIALIZATION  0x00000040
源代码如下:
/** @file
  Dump Capsule image information.

  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
  This program and the accompanying materials
  are licensed and made available under the terms and conditions of the BSD License
  which accompanies this distribution.  The full text of the license may be found at
  http://opensource.org/licenses/bsd-license.php

  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

 

根据上面的资料,编写代码如下:

#include <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/Shell.h>
#include <Protocol/ShellParameters.h>
#include <Protocol/SmmAccess2.h>

EFI_SMRAM_DESCRIPTOR  *mSmramRanges;
UINTN                 mSmramRangeCount;
  
/**
  Print APP usage.
**/
VOID
PrintUsage (
  VOID
  )
{
  Print(L"FVBDemo:  usage\n");
  Print(L"  FVBDemo <FileName>\n");
}
/**
  @param[in]  ImageHandle     The image handle.
  @param[in]  SystemTable     The system table.

  @retval EFI_SUCCESS            Command completed successfully.
  @retval EFI_INVALID_PARAMETER  Command usage error.
  @retval EFI_NOT_FOUND          The input file can't be found.
**/
EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                Status=EFI_SUCCESS;
  EFI_SMM_ACCESS2_PROTOCOL  *SmmAccess;
  UINTN                     Size;
  UINTN                     Index;  
  
  //
  // Locate SMM Access2 Protocol
  //
  Status = gBS->LocateProtocol (
                  &gEfiSmmAccess2ProtocolGuid, 
                  NULL, 
                  (VOID **)&SmmAccess
                  );
  if (EFI_ERROR(Status)) {
        Print(L"Can't find SmmAccess2Protocol\n");
  };

  //
  // Get SMRAM range information
  //
  Size = 0;
  Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);

  mSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);
  if (mSmramRanges == NULL) {
          Print(L"Allocate Memory Error!\n");
          return EFI_SUCCESS;
  }

  Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);
  if (EFI_ERROR(Status)) {
          Print(L"GetCapabilities Error!\n");
          return EFI_SUCCESS;
  }

  mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);

        Print(L"Index PhysicalStart CpuStart PhysicalSize RegionState\n");  
  for (Index = 0; Index < mSmramRangeCount; Index ++) {
        Print(L"[%d]   %8X      %8X %8X     %8X\n",
                Index,
                mSmramRanges[Index].PhysicalStart,
                mSmramRanges[Index].CpuStart,
                mSmramRanges[Index].PhysicalSize,
                mSmramRanges[Index].RegionState);
    }   //for 
    
  FreePool (mSmramRanges);  
  
  return Status;
}

 

最终运行结果如下(测试平台是 KBL-R HDK):
sm3
完整的代码下载
SMMAccess

《Step to UEFI (121)EFI_SMM_ACCESS2_PROTOCOL 的使用》有2个想法

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注