UEFI向SRAT 表中添加memory信息

从inf文件可以看到这是一个DXE_DRIVER,其入口函数是AcpiPlatformEntryPoint
[Defines]
  INF_VERSION                    = 0x00010005
  BASE_NAME                      = AcpiPlatform
  MODULE_UNI_FILE                = AcpiPlatform.uni
  FILE_GUID                      = cb933912-df8f-4305-b1f9-7b44fa11395c
  MODULE_TYPE                    = DXE_DRIVER
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = AcpiPlatformEntryPoint

在其入口函数AcpiPlatformEntryPoint中会调用PlatformUpdateTables 来更新APCI的SRAT表
EFI_STATUS
PlatformUpdateTables (
  IN OUT EFI_ACPI_COMMON_HEADER       **Table
  )
{
  EFI_STATUS                              Status;
  EFI_ACPI_DESCRIPTION_HEADER             *TableHeader;

  Status = EFI_SUCCESS;
//强转指针后,调用UpdateAcpiTable来更新SRAT
  TableHeader = (EFI_ACPI_DESCRIPTION_HEADER*) (*Table);

  UpdateAcpiTable(TableHeader, &Status);

  return Status;
}
VOID
UpdateAcpiTable (
  IN OUT EFI_ACPI_DESCRIPTION_HEADER      *TableHeader,
  IN OUT EFI_STATUS                       *CommonCodeReturnStatus
)
{
  switch ((TableHeader)->Signature) {

  case EFI_ACPI_6_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE:
    *CommonCodeReturnStatus = UpdateSrat (TableHeader);
    break;

  case EFI_ACPI_6_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
    *CommonCodeReturnStatus = UpdateSlit (TableHeader);
    break;
  }
  return;
}
根据Signature 来决定更新是srat还是slit。这里以srat为例

STATIC
EFI_STATUS
UpdateSrat (
  IN OUT EFI_ACPI_DESCRIPTION_HEADER  *Table
  )
{
  UINT8               Skt = 0;
  UINT8               Ch = 0;
  VOID*               HobList;
  GBL_DATA           *Gbl_Data;
  UINTN               Base;
  UINTN               Size;
  UINT8               NodeId;
  UINT32              DieInterleaveEn;
  UINT8               i;

  DEBUG(( EFI_D_ERROR, "\nSRAT: Updating SRAT memory information!\n" ));
// 原来这里也是从HOB中拿到memory的信息,也就说在SEC 阶段就已经建立好memory的HOB信息,后续所以关于硬件的信息其实都是从HOB中的到的.
  HobList = GetHobList();
  Gbl_Data = (GBL_DATA*)GetNextGuidHob(&gHisiEfiMemoryMapGuid, HobList);
  Gbl_Data = GET_GUID_HOB_DATA(Gbl_Data);
  for(Skt = 0; Skt < MAX_SOCKET; Skt++){
      for(Ch = 0; Ch < MAX_NUM_PER_TYPE; Ch++){
          NodeId = Gbl_Data->NumaInfo[Skt][Ch].NodeId;
          Base = Gbl_Data->NumaInfo[Skt][Ch].Base;
          Size = Gbl_Data->NumaInfo[Skt][Ch].Length;
          DieInterleaveEn = Gbl_Data->NumaInfo[Skt][Ch].DieInterleaveEn;
          DEBUG((EFI_D_INFO,"Skt %d Ch: %d NodeId = %d, Base = 0x%lx, Size = 0x%lx, DieInterLeaveEn = %d\n",Skt,Ch,NodeId,Base,Size,DieInterleaveEn));
          if (Size > 0)
          {
              ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].ProximityDomain = NodeId;
              ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].AddressBaseLow = Base;
              ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].AddressBaseHigh = Base >> 32;
              ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].LengthLow = Size;
              ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].LengthHigh = Size >> 32;
              MemoryNode = MemoryNode + 1;
          }
      }
  }

  //update gicc structure
  if(DieInterleaveEn != 0)
  {
      DEBUG(( EFI_D_ERROR, "\nSRAT: Updating SRAT Gicc information!\n" ));
      for (i = 0; i < 32; i ++)
          ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Gicc[i].ProximityDomain = 0;
      for (i = 32; i < 64; i ++)
          ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Gicc[i].ProximityDomain = 2;
  }

  //remove invalid memory node
  (VOID)RemoveInvalidMemoryNode (Table, MemoryNode);

  return EFI_SUCCESS;

}

这样在kernel初始化阶段就可以看到从SRAT表中得到memory信息

[    0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x00000000-0x3fffffff]
[    0.000000] NUMA: Adding memblock [0x2000000000 - 0x2fffffffff] on node 1
[    0.000000] ACPI: SRAT: Node 1 PXM 1 [mem 0x2000000000-0x2fffffffff]
[    0.000000] NUMA: Adding memblock [0x1000000000 - 0x1fffffffff] on node 0
[    0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x1000000000-0x1fffffffff]
[    0.000000] NUMA: Adding memblock [0x40000000000 - 0x4003fffffff] on node 2
[    0.000000] ACPI: SRAT: Node 2 PXM 2 [mem 0x40000000000-0x4003fffffff]
[    0.000000] NUMA: Adding memblock [0x42000000000 - 0x42fffffffff] on node 3
[    0.000000] ACPI: SRAT: Node 3 PXM 3 [mem 0x42000000000-0x42fffffffff]
[    0.000000] NUMA: Adding memblock [0x41000000000 - 0x41fffffffff] on node 2
[    0.000000] ACPI: SRAT: Node 2 PXM 2 [mem 0x41000000000-0x41fffffffff]


你可能感兴趣的:(uefi)