/** @file | |
Copyright (c) 2006 - 2010, 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. | |
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; | |
} | |
// | |
// It's possible that the PM_TMR_BLK.RegisterBitWidth is always 32, | |
// we need to set the correct RegisterBitWidth value according to the TMR_VAL_EXT | |
// A zero indicates TMR_VAL is implemented as a 24-bit value. | |
// A one indicates TMR_VAL is implemented as a 32-bit value | |
// | |
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 ; | |
} | |