CorebootModulePkg: Fix memmap issue

Some reserved memory (e.g. CSE reserved memory) might be in the
middle of usable physical memory. The current memory map caculation
could not handle this case. This patch fixed this issue.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: gdong1 <guo.dong@intel.com>
Reviewed-by: Maurice Ma <maurice.ma@intel.com>
This commit is contained in:
gdong1
2016-10-26 16:48:40 -07:00
committed by Maurice Ma
parent c46bf81d2d
commit 2d90b74d02
4 changed files with 135 additions and 111 deletions

View File

@ -140,6 +140,72 @@ CbPeiReportRemainedFvs (
} }
} }
/**
Based on memory base, size and type, build resource descripter HOB.
@param Base Memory base address.
@param Size Memory size.
@param Type Memory type.
@param Param A pointer to CB_MEM_INFO.
@retval EFI_SUCCESS if it completed successfully.
**/
EFI_STATUS
CbMemInfoCallback (
UINT64 Base,
UINT64 Size,
UINT32 Type,
VOID *Param
)
{
CB_MEM_INFO *MemInfo;
UINTN Attribue;
Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
EFI_RESOURCE_ATTRIBUTE_TESTED |
EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;
MemInfo = (CB_MEM_INFO *)Param;
if (Base >= 0x100000) {
if (Type == CB_MEM_RAM) {
if (Base < 0x100000000ULL) {
MemInfo->UsableLowMemTop = (UINT32)(Base + Size);
} else {
Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED;
}
BuildResourceDescriptorHob (
EFI_RESOURCE_SYSTEM_MEMORY,
Attribue,
(EFI_PHYSICAL_ADDRESS)Base,
Size
);
} else if (Type == CB_MEM_TABLE) {
BuildResourceDescriptorHob (
EFI_RESOURCE_MEMORY_RESERVED,
Attribue,
(EFI_PHYSICAL_ADDRESS)Base,
Size
);
MemInfo->SystemLowMemTop = ((UINT32)(Base + Size) + 0x0FFFFFFF) & 0xF0000000;
} else if (Type == CB_MEM_RESERVED) {
if ((MemInfo->SystemLowMemTop == 0) || (Base < MemInfo->SystemLowMemTop)) {
BuildResourceDescriptorHob (
EFI_RESOURCE_MEMORY_RESERVED,
Attribue,
(EFI_PHYSICAL_ADDRESS)Base,
Size
);
}
}
}
return EFI_SUCCESS;
}
/** /**
This is the entrypoint of PEIM This is the entrypoint of PEIM
@ -155,9 +221,9 @@ CbPeiEntryPoint (
IN CONST EFI_PEI_SERVICES **PeiServices IN CONST EFI_PEI_SERVICES **PeiServices
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINT64 LowMemorySize, HighMemorySize; UINT64 LowMemorySize;
UINT64 PeiMemSize = SIZE_64MB; // 64 MB UINT64 PeiMemSize = SIZE_64MB; // 64 MB
EFI_PHYSICAL_ADDRESS PeiMemBase = 0; EFI_PHYSICAL_ADDRESS PeiMemBase = 0;
UINT32 RegEax; UINT32 RegEax;
UINT8 PhysicalAddressBits; UINT8 PhysicalAddressBits;
@ -173,23 +239,12 @@ CbPeiEntryPoint (
UINTN PmCtrlRegBase, PmTimerRegBase, ResetRegAddress, ResetValue; UINTN PmCtrlRegBase, PmTimerRegBase, ResetRegAddress, ResetValue;
UINTN PmEvtBase; UINTN PmEvtBase;
UINTN PmGpeEnBase; UINTN PmGpeEnBase;
CB_MEM_INFO CbMemInfo;
LowMemorySize = 0;
HighMemorySize = 0;
Status = CbParseMemoryInfo (&LowMemorySize, &HighMemorySize);
if (EFI_ERROR(Status))
return Status;
DEBUG((EFI_D_ERROR, "LowMemorySize: 0x%lx.\n", LowMemorySize));
DEBUG((EFI_D_ERROR, "HighMemorySize: 0x%lx.\n", HighMemorySize));
ASSERT (LowMemorySize > 0);
// //
// Report lower 640KB of RAM. Attribute EFI_RESOURCE_ATTRIBUTE_TESTED // Report lower 640KB of RAM. Attribute EFI_RESOURCE_ATTRIBUTE_TESTED
// is intentionally omitted to prevent erasing of the coreboot header // is intentionally omitted to prevent erasing of the coreboot header
// record before it is processed by CbParseMemoryInfo. // record before it is processed by CbParseMemoryInfo.
// //
BuildResourceDescriptorHob ( BuildResourceDescriptorHob (
EFI_RESOURCE_SYSTEM_MEMORY, EFI_RESOURCE_SYSTEM_MEMORY,
@ -221,37 +276,16 @@ CbPeiEntryPoint (
(UINT64)(0x60000) (UINT64)(0x60000)
); );
BuildResourceDescriptorHob ( ZeroMem (&CbMemInfo, sizeof(CbMemInfo));
EFI_RESOURCE_SYSTEM_MEMORY, Status = CbParseMemoryInfo (CbMemInfoCallback, (VOID *)&CbMemInfo);
( if (EFI_ERROR(Status)) {
EFI_RESOURCE_ATTRIBUTE_PRESENT | return Status;
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
EFI_RESOURCE_ATTRIBUTE_TESTED |
EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
),
(EFI_PHYSICAL_ADDRESS)(0x100000),
(UINT64) (LowMemorySize - 0x100000)
);
if (HighMemorySize > 0) {
BuildResourceDescriptorHob (
EFI_RESOURCE_SYSTEM_MEMORY,
(
EFI_RESOURCE_ATTRIBUTE_PRESENT |
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
),
(EFI_PHYSICAL_ADDRESS)(0x100000000ULL),
HighMemorySize
);
} }
LowMemorySize = CbMemInfo.UsableLowMemTop;
DEBUG ((EFI_D_INFO, "Low memory 0x%lx\n", LowMemorySize));
DEBUG ((EFI_D_INFO, "SystemLowMemTop 0x%x\n", CbMemInfo.SystemLowMemTop));
// //
// Should be 64k aligned // Should be 64k aligned
// //

View File

@ -38,5 +38,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Guid/AcpiBoardInfoGuid.h> #include <Guid/AcpiBoardInfoGuid.h>
#include <Ppi/MasterBootMode.h> #include <Ppi/MasterBootMode.h>
#include "Coreboot.h"
typedef struct {
UINT32 UsableLowMemTop;
UINT32 SystemLowMemTop;
} CB_MEM_INFO;
#endif #endif

View File

@ -14,21 +14,23 @@
**/ **/
#include <Guid/FrameBufferInfoGuid.h> #include <Guid/FrameBufferInfoGuid.h>
typedef RETURN_STATUS \
(*CB_MEM_INFO_CALLBACK) (UINT64 Base, UINT64 Size, UINT32 Type, VOID *Param);
/** /**
Acquire the memory information from the coreboot table in memory. Acquire the memory information from the coreboot table in memory.
@param pLowMemorySize Pointer to the variable of low memory size @param MemInfoCallback The callback routine
@param pHighMemorySize Pointer to the variable of high memory size @param pParam Pointer to the callback routine parameter
@retval RETURN_SUCCESS Successfully find out the memory information. @retval RETURN_SUCCESS Successfully find out the memory information.
@retval RETURN_INVALID_PARAMETER Invalid input parameters.
@retval RETURN_NOT_FOUND Failed to find the memory information. @retval RETURN_NOT_FOUND Failed to find the memory information.
**/ **/
RETURN_STATUS RETURN_STATUS
CbParseMemoryInfo ( CbParseMemoryInfo (
IN UINT64* pLowMemorySize, IN CB_MEM_INFO_CALLBACK MemInfoCallback,
IN UINT64* pHighMemorySize IN VOID *pParam
); );
/** /**

View File

@ -2,7 +2,7 @@
This library will parse the coreboot table in memory and extract those required This library will parse the coreboot table in memory and extract those required
information. information.
Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -33,7 +33,7 @@
@return the UNIT64 value after convertion. @return the UNIT64 value after convertion.
**/ **/
UINT64 UINT64
cb_unpack64 ( cb_unpack64 (
IN struct cbuint64 val IN struct cbuint64 val
) )
@ -216,8 +216,8 @@ FindCbMemTable (
*pMemTableSize = Entries[Idx].size; *pMemTableSize = Entries[Idx].size;
} }
DEBUG ((EFI_D_INFO, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n", DEBUG ((EFI_D_INFO, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n",
TableId, *pMemTable, Entries[Idx].size)); TableId, *pMemTable, Entries[Idx].size));
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }
} }
@ -229,18 +229,17 @@ FindCbMemTable (
/** /**
Acquire the memory information from the coreboot table in memory. Acquire the memory information from the coreboot table in memory.
@param pLowMemorySize Pointer to the variable of low memory size @param MemInfoCallback The callback routine
@param pHighMemorySize Pointer to the variable of high memory size @param pParam Pointer to the callback routine parameter
@retval RETURN_SUCCESS Successfully find out the memory information. @retval RETURN_SUCCESS Successfully find out the memory information.
@retval RETURN_INVALID_PARAMETER Invalid input parameters.
@retval RETURN_NOT_FOUND Failed to find the memory information. @retval RETURN_NOT_FOUND Failed to find the memory information.
**/ **/
RETURN_STATUS RETURN_STATUS
CbParseMemoryInfo ( CbParseMemoryInfo (
OUT UINT64 *pLowMemorySize, IN CB_MEM_INFO_CALLBACK MemInfoCallback,
OUT UINT64 *pHighMemorySize IN VOID *pParam
) )
{ {
struct cb_memory *rec; struct cb_memory *rec;
@ -249,10 +248,6 @@ CbParseMemoryInfo (
UINT64 Size; UINT64 Size;
UINTN Index; UINTN Index;
if ((pLowMemorySize == NULL) || (pHighMemorySize == NULL)) {
return RETURN_INVALID_PARAMETER;
}
// //
// Get the coreboot memory table // Get the coreboot memory table
// //
@ -265,9 +260,6 @@ CbParseMemoryInfo (
return RETURN_NOT_FOUND; return RETURN_NOT_FOUND;
} }
*pLowMemorySize = 0;
*pHighMemorySize = 0;
for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) { for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) {
Range = MEM_RANGE_PTR(rec, Index); Range = MEM_RANGE_PTR(rec, Index);
Start = cb_unpack64(Range->start); Start = cb_unpack64(Range->start);
@ -275,19 +267,9 @@ CbParseMemoryInfo (
DEBUG ((EFI_D_INFO, "%d. %016lx - %016lx [%02x]\n", DEBUG ((EFI_D_INFO, "%d. %016lx - %016lx [%02x]\n",
Index, Start, Start + Size - 1, Range->type)); Index, Start, Start + Size - 1, Range->type));
if (Range->type != CB_MEM_RAM) { MemInfoCallback (Start, Size, Range->type, pParam);
continue;
}
if (Start + Size < 0x100000000ULL) {
*pLowMemorySize = Start + Size;
} else {
*pHighMemorySize = Start + Size - 0x100000000ULL;
}
} }
DEBUG ((EFI_D_INFO, "Low memory 0x%lx, High Memory 0x%lx\n", *pLowMemorySize, *pHighMemorySize));
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }
@ -469,25 +451,25 @@ CbParseFadtInfo (
} }
DEBUG ((EFI_D_INFO, "Reset Value 0x%x\n", Fadt->ResetValue)); DEBUG ((EFI_D_INFO, "Reset Value 0x%x\n", Fadt->ResetValue));
if (pPmEvtReg != NULL) { if (pPmEvtReg != NULL) {
*pPmEvtReg = Fadt->Pm1aEvtBlk; *pPmEvtReg = Fadt->Pm1aEvtBlk;
DEBUG ((EFI_D_INFO, "PmEvt Reg 0x%x\n", Fadt->Pm1aEvtBlk)); DEBUG ((EFI_D_INFO, "PmEvt Reg 0x%x\n", Fadt->Pm1aEvtBlk));
} }
if (pPmGpeEnReg != NULL) { if (pPmGpeEnReg != NULL) {
*pPmGpeEnReg = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2; *pPmGpeEnReg = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2;
DEBUG ((EFI_D_INFO, "PmGpeEn Reg 0x%x\n", *pPmGpeEnReg)); DEBUG ((EFI_D_INFO, "PmGpeEn Reg 0x%x\n", *pPmGpeEnReg));
} }
// //
// Verify values for proper operation // Verify values for proper operation
// //
ASSERT(Fadt->Pm1aCntBlk != 0); ASSERT(Fadt->Pm1aCntBlk != 0);
ASSERT(Fadt->PmTmrBlk != 0); ASSERT(Fadt->PmTmrBlk != 0);
ASSERT(Fadt->ResetReg.Address != 0); ASSERT(Fadt->ResetReg.Address != 0);
ASSERT(Fadt->Pm1aEvtBlk != 0); ASSERT(Fadt->Pm1aEvtBlk != 0);
ASSERT(Fadt->Gpe0Blk != 0); ASSERT(Fadt->Gpe0Blk != 0);
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }
} }
@ -519,15 +501,15 @@ CbParseFadtInfo (
*pResetValue = Fadt->ResetValue; *pResetValue = Fadt->ResetValue;
DEBUG ((EFI_D_ERROR, "Reset Value 0x%x\n", Fadt->ResetValue)); DEBUG ((EFI_D_ERROR, "Reset Value 0x%x\n", Fadt->ResetValue));
if (pPmEvtReg != NULL) { if (pPmEvtReg != NULL) {
*pPmEvtReg = Fadt->Pm1aEvtBlk; *pPmEvtReg = Fadt->Pm1aEvtBlk;
DEBUG ((EFI_D_INFO, "PmEvt Reg 0x%x\n", Fadt->Pm1aEvtBlk)); DEBUG ((EFI_D_INFO, "PmEvt Reg 0x%x\n", Fadt->Pm1aEvtBlk));
} }
if (pPmGpeEnReg != NULL) { if (pPmGpeEnReg != NULL) {
*pPmGpeEnReg = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2; *pPmGpeEnReg = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2;
DEBUG ((EFI_D_INFO, "PmGpeEn Reg 0x%x\n", *pPmGpeEnReg)); DEBUG ((EFI_D_INFO, "PmGpeEn Reg 0x%x\n", *pPmGpeEnReg));
} }
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }
} }
@ -541,10 +523,10 @@ CbParseFadtInfo (
@param pRegBase Pointer to the base address of serial port registers @param pRegBase Pointer to the base address of serial port registers
@param pRegAccessType Pointer to the access type of serial port registers @param pRegAccessType Pointer to the access type of serial port registers
@param pRegWidth Pointer to the register width in bytes @param pRegWidth Pointer to the register width in bytes
@param pBaudrate Pointer to the serial port baudrate @param pBaudrate Pointer to the serial port baudrate
@param pInputHertz Pointer to the input clock frequency @param pInputHertz Pointer to the input clock frequency
@param pUartPciAddr Pointer to the UART PCI bus, dev and func address @param pUartPciAddr Pointer to the UART PCI bus, dev and func address
@retval RETURN_SUCCESS Successfully find the serial port information. @retval RETURN_SUCCESS Successfully find the serial port information.
@retval RETURN_NOT_FOUND Failed to find the serial port information . @retval RETURN_NOT_FOUND Failed to find the serial port information .
@ -554,10 +536,10 @@ RETURN_STATUS
CbParseSerialInfo ( CbParseSerialInfo (
OUT UINT32 *pRegBase, OUT UINT32 *pRegBase,
OUT UINT32 *pRegAccessType, OUT UINT32 *pRegAccessType,
OUT UINT32 *pRegWidth, OUT UINT32 *pRegWidth,
OUT UINT32 *pBaudrate, OUT UINT32 *pBaudrate,
OUT UINT32 *pInputHertz, OUT UINT32 *pInputHertz,
OUT UINT32 *pUartPciAddr OUT UINT32 *pUartPciAddr
) )
{ {
struct cb_serial *CbSerial; struct cb_serial *CbSerial;
@ -575,10 +557,10 @@ CbParseSerialInfo (
*pRegBase = CbSerial->baseaddr; *pRegBase = CbSerial->baseaddr;
} }
if (pRegWidth != NULL) { if (pRegWidth != NULL) {
*pRegWidth = CbSerial->regwidth; *pRegWidth = CbSerial->regwidth;
} }
if (pRegAccessType != NULL) { if (pRegAccessType != NULL) {
*pRegAccessType = CbSerial->type; *pRegAccessType = CbSerial->type;
} }
@ -587,14 +569,14 @@ CbParseSerialInfo (
*pBaudrate = CbSerial->baud; *pBaudrate = CbSerial->baud;
} }
if (pInputHertz != NULL) { if (pInputHertz != NULL) {
*pInputHertz = CbSerial->input_hertz; *pInputHertz = CbSerial->input_hertz;
} }
if (pUartPciAddr != NULL) { if (pUartPciAddr != NULL) {
*pUartPciAddr = CbSerial->uart_pci_addr; *pUartPciAddr = CbSerial->uart_pci_addr;
} }
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }