mirror of https://github.com/acidanthera/audk.git
350 lines
9.3 KiB
C
350 lines
9.3 KiB
C
/** @file
|
|
|
|
Copyright (c) 2006 - 2010, Intel Corporation
|
|
All rights reserved. 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.
|
|
|
|
Module Name:
|
|
LegacyTable.c
|
|
|
|
Abstract:
|
|
|
|
Revision History:
|
|
|
|
**/
|
|
|
|
#include "DxeIpl.h"
|
|
#include "HobGeneration.h"
|
|
#include "Debug.h"
|
|
|
|
#define MPS_PTR SIGNATURE_32('_','M','P','_')
|
|
#define SMBIOS_PTR SIGNATURE_32('_','S','M','_')
|
|
|
|
#define EBDA_BASE_ADDRESS 0x40E
|
|
|
|
VOID *
|
|
FindAcpiRsdPtr (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN Address;
|
|
UINTN Index;
|
|
|
|
//
|
|
// First Seach 0x0e0000 - 0x0fffff for RSD Ptr
|
|
//
|
|
for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) {
|
|
if (*(UINT64 *)(Address) == EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {
|
|
return (VOID *)Address;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Search EBDA
|
|
//
|
|
|
|
Address = (*(UINT16 *)(UINTN)(EBDA_BASE_ADDRESS)) << 4;
|
|
for (Index = 0; Index < 0x400 ; Index += 16) {
|
|
if (*(UINT64 *)(Address + Index) == EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {
|
|
return (VOID *)Address;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
VOID *
|
|
FindSMBIOSPtr (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN Address;
|
|
|
|
//
|
|
// First Seach 0x0f0000 - 0x0fffff for SMBIOS Ptr
|
|
//
|
|
for (Address = 0xf0000; Address < 0xfffff; Address += 0x10) {
|
|
if (*(UINT32 *)(Address) == SMBIOS_PTR) {
|
|
return (VOID *)Address;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
VOID *
|
|
FindMPSPtr (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN Address;
|
|
UINTN Index;
|
|
|
|
//
|
|
// First Seach 0x0e0000 - 0x0fffff for MPS Ptr
|
|
//
|
|
for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) {
|
|
if (*(UINT32 *)(Address) == MPS_PTR) {
|
|
return (VOID *)Address;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Search EBDA
|
|
//
|
|
|
|
Address = (*(UINT16 *)(UINTN)(EBDA_BASE_ADDRESS)) << 4;
|
|
for (Index = 0; Index < 0x400 ; Index += 16) {
|
|
if (*(UINT32 *)(Address + Index) == MPS_PTR) {
|
|
return (VOID *)Address;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#pragma pack(1)
|
|
|
|
typedef struct {
|
|
EFI_ACPI_DESCRIPTION_HEADER Header;
|
|
UINT32 Entry;
|
|
} RSDT_TABLE;
|
|
|
|
typedef struct {
|
|
EFI_ACPI_DESCRIPTION_HEADER Header;
|
|
UINT64 Entry;
|
|
} XSDT_TABLE;
|
|
|
|
#pragma pack()
|
|
|
|
VOID
|
|
ScanTableInRSDT (
|
|
RSDT_TABLE *Rsdt,
|
|
UINT32 Signature,
|
|
EFI_ACPI_DESCRIPTION_HEADER **FoundTable
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT32 EntryCount;
|
|
UINT32 *EntryPtr;
|
|
EFI_ACPI_DESCRIPTION_HEADER *Table;
|
|
|
|
*FoundTable = NULL;
|
|
|
|
EntryCount = (Rsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32);
|
|
|
|
EntryPtr = &Rsdt->Entry;
|
|
for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) {
|
|
Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(*EntryPtr));
|
|
if (Table->Signature == Signature) {
|
|
*FoundTable = Table;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
ScanTableInXSDT (
|
|
XSDT_TABLE *Xsdt,
|
|
UINT32 Signature,
|
|
EFI_ACPI_DESCRIPTION_HEADER **FoundTable
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT32 EntryCount;
|
|
UINT64 EntryPtr;
|
|
UINTN BasePtr;
|
|
EFI_ACPI_DESCRIPTION_HEADER *Table;
|
|
|
|
*FoundTable = NULL;
|
|
|
|
EntryCount = (Xsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);
|
|
|
|
BasePtr = (UINTN)(&(Xsdt->Entry));
|
|
for (Index = 0; Index < EntryCount; Index ++) {
|
|
CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64));
|
|
Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(EntryPtr));
|
|
if (Table->Signature == Signature) {
|
|
*FoundTable = Table;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID *
|
|
FindAcpiPtr (
|
|
IN HOB_TEMPLATE *Hob,
|
|
UINT32 Signature
|
|
)
|
|
{
|
|
EFI_ACPI_DESCRIPTION_HEADER *AcpiTable;
|
|
EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
|
|
RSDT_TABLE *Rsdt;
|
|
XSDT_TABLE *Xsdt;
|
|
|
|
AcpiTable = NULL;
|
|
|
|
//
|
|
// Check ACPI2.0 table
|
|
//
|
|
if ((int)Hob->Acpi20.Table != -1) {
|
|
Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)Hob->Acpi20.Table;
|
|
Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress;
|
|
Xsdt = NULL;
|
|
if ((Rsdp->Revision >= 2) && (Rsdp->XsdtAddress < (UINT64)(UINTN)-1)) {
|
|
Xsdt = (XSDT_TABLE *)(UINTN)Rsdp->XsdtAddress;
|
|
}
|
|
//
|
|
// Check Xsdt
|
|
//
|
|
if (Xsdt != NULL) {
|
|
ScanTableInXSDT (Xsdt, Signature, &AcpiTable);
|
|
}
|
|
//
|
|
// Check Rsdt
|
|
//
|
|
if ((AcpiTable == NULL) && (Rsdt != NULL)) {
|
|
ScanTableInRSDT (Rsdt, Signature, &AcpiTable);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check ACPI1.0 table
|
|
//
|
|
if ((AcpiTable == NULL) && ((int)Hob->Acpi.Table != -1)) {
|
|
Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)Hob->Acpi.Table;
|
|
Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress;
|
|
//
|
|
// Check Rsdt
|
|
//
|
|
if (Rsdt != NULL) {
|
|
ScanTableInRSDT (Rsdt, Signature, &AcpiTable);
|
|
}
|
|
}
|
|
|
|
return AcpiTable;
|
|
}
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UINT64 BaseAddress;
|
|
UINT16 PciSegmentGroupNumber;
|
|
UINT8 StartBusNumber;
|
|
UINT8 EndBusNumber;
|
|
UINT32 Reserved;
|
|
} MCFG_STRUCTURE;
|
|
#pragma pack()
|
|
|
|
VOID
|
|
PrepareMcfgTable (
|
|
IN HOB_TEMPLATE *Hob
|
|
)
|
|
{
|
|
EFI_ACPI_DESCRIPTION_HEADER *McfgTable;
|
|
MCFG_STRUCTURE *Mcfg;
|
|
UINTN McfgCount;
|
|
UINTN Index;
|
|
|
|
McfgTable = FindAcpiPtr (Hob, EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE);
|
|
if (McfgTable == NULL) {
|
|
return ;
|
|
}
|
|
|
|
Mcfg = (MCFG_STRUCTURE *)((UINTN)McfgTable + sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64));
|
|
McfgCount = (McfgTable->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER) - sizeof(UINT64)) / sizeof(MCFG_STRUCTURE);
|
|
|
|
//
|
|
// Fill PciExpress info on Hob
|
|
// Note: Only for 1st segment
|
|
//
|
|
for (Index = 0; Index < McfgCount; Index++) {
|
|
if (Mcfg[Index].PciSegmentGroupNumber == 0) {
|
|
Hob->PciExpress.PciExpressBaseAddressInfo.PciExpressBaseAddress = Mcfg[Index].BaseAddress;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
VOID
|
|
PrepareFadtTable (
|
|
IN HOB_TEMPLATE *Hob
|
|
)
|
|
{
|
|
EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
|
|
EFI_ACPI_DESCRIPTION *AcpiDescription;
|
|
|
|
Fadt = FindAcpiPtr (Hob, EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);
|
|
if (Fadt == NULL) {
|
|
return ;
|
|
}
|
|
|
|
AcpiDescription = &Hob->AcpiInfo.AcpiDescription;
|
|
//
|
|
// Fill AcpiDescription according to FADT
|
|
// Currently, only for PM_TMR
|
|
//
|
|
AcpiDescription->PM_TMR_LEN = Fadt->PmTmrLen;
|
|
AcpiDescription->TMR_VAL_EXT = (UINT8)((Fadt->Flags & 0x100) != 0);
|
|
|
|
//
|
|
// For fields not included in ACPI 1.0 spec, we get the value based on table length
|
|
//
|
|
if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, XPmTmrBlk) + sizeof (Fadt->XPmTmrBlk)) {
|
|
CopyMem (
|
|
&AcpiDescription->PM_TMR_BLK,
|
|
&Fadt->XPmTmrBlk,
|
|
sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE)
|
|
);
|
|
}
|
|
if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, ResetValue) + sizeof (Fadt->ResetValue)) {
|
|
CopyMem (
|
|
&AcpiDescription->RESET_REG,
|
|
&Fadt->ResetReg,
|
|
sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE)
|
|
);
|
|
AcpiDescription->RESET_VALUE = Fadt->ResetValue;
|
|
}
|
|
|
|
if (AcpiDescription->PM_TMR_BLK.Address == 0) {
|
|
AcpiDescription->PM_TMR_BLK.Address = Fadt->PmTmrBlk;
|
|
AcpiDescription->PM_TMR_BLK.AddressSpaceId = EFI_ACPI_3_0_SYSTEM_IO;
|
|
AcpiDescription->PM_TMR_BLK.RegisterBitWidth = (UINT8) ((AcpiDescription->TMR_VAL_EXT == 0) ? 24 : 32);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
VOID
|
|
PrepareHobLegacyTable (
|
|
IN HOB_TEMPLATE *Hob
|
|
)
|
|
{
|
|
CHAR8 PrintBuffer[256];
|
|
|
|
Hob->Acpi.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiRsdPtr ();
|
|
AsciiSPrint (PrintBuffer, 256, "\nAcpiTable=0x%x ", (UINT32)(UINTN)Hob->Acpi.Table);
|
|
PrintString (PrintBuffer);
|
|
Hob->Acpi20.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiRsdPtr ();
|
|
Hob->Smbios.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindSMBIOSPtr ();
|
|
AsciiSPrint (PrintBuffer, 256, "SMBIOS Table=0x%x ", (UINT32)(UINTN)Hob->Smbios.Table);
|
|
PrintString (PrintBuffer);
|
|
Hob->Mps.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindMPSPtr ();
|
|
AsciiSPrint (PrintBuffer, 256, "MPS Table=0x%x\n", (UINT32)(UINTN)Hob->Mps.Table);
|
|
PrintString (PrintBuffer);
|
|
|
|
PrepareMcfgTable (Hob);
|
|
|
|
PrepareFadtTable (Hob);
|
|
|
|
return ;
|
|
}
|
|
|