diff --git a/CorebootModulePkg/CbSupportDxe/CbSupportDxe.c b/CorebootModulePkg/CbSupportDxe/CbSupportDxe.c new file mode 100644 index 0000000000..1b3e74a525 --- /dev/null +++ b/CorebootModulePkg/CbSupportDxe/CbSupportDxe.c @@ -0,0 +1,199 @@ +/** @file + This driver will report some MMIO/IO resources to dxe core, extract smbios and acpi + tables from coreboot and install. + + Copyright (c) 2014, 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. + +**/ +#include "CbSupportDxe.h" + +UINTN mPmCtrlReg = 0; +/** + Reserve MMIO/IO resource in GCD + + @param IsMMIO Flag of whether it is mmio resource or io resource. + @param GcdType Type of the space. + @param BaseAddress Base address of the space. + @param Length Length of the space. + @param Alignment Align with 2^Alignment + @param ImageHandle Handle for the image of this driver. + + @retval EFI_SUCCESS Reserve successful +**/ +EFI_STATUS +CbReserveResourceInGcd ( + IN BOOLEAN IsMMIO, + IN UINTN GcdType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINTN Alignment, + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + if (IsMMIO) { + Status = gDS->AddMemorySpace ( + GcdType, + BaseAddress, + Length, + EFI_MEMORY_UC + ); + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_ERROR, + "Failed to add memory space :0x%x 0x%x\n", + BaseAddress, + Length + )); + } + ASSERT_EFI_ERROR (Status); + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + GcdType, + Alignment, + Length, + &BaseAddress, + ImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else { + Status = gDS->AddIoSpace ( + GcdType, + BaseAddress, + Length + ); + ASSERT_EFI_ERROR (Status); + Status = gDS->AllocateIoSpace ( + EfiGcdAllocateAddress, + GcdType, + Alignment, + Length, + &BaseAddress, + ImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + return Status; +} + +/** + Notification function of EVT_GROUP_READY_TO_BOOT event group. + + This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group. + When the Boot Manager is about to load and execute a boot option, it reclaims variable + storage if free size is below the threshold. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context. + +**/ +VOID +OnReadyToBoot ( + EFI_EVENT Event, + VOID *Context + ) +{ + // + // Enable SCI + // + IoOr16 (mPmCtrlReg, BIT0); + + DEBUG ((EFI_D_ERROR, "Enable SCI bit at 0x%x before boot\n", mPmCtrlReg)); +} + +/** + Main entry for the Coreboot Support DXE module. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +CbDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT ReadyToBootEvent; + EFI_HOB_GUID_TYPE *GuidHob; + SYSTEM_TABLE_INFO *pSystemTableInfo; + ACPI_BOARD_INFO *pAcpiBoardInfo; + + Status = EFI_SUCCESS; + // + // Report MMIO/IO Resources + // + Status = CbReserveResourceInGcd (TRUE, EfiGcdMemoryTypeMemoryMappedIo, 0xFEE00000, SIZE_1MB, 0, SystemTable); // LAPIC + ASSERT_EFI_ERROR (Status); + + Status = CbReserveResourceInGcd (TRUE, EfiGcdMemoryTypeMemoryMappedIo, 0xFEC00000, SIZE_4KB, 0, SystemTable); // IOAPIC + ASSERT_EFI_ERROR (Status); + + Status = CbReserveResourceInGcd (TRUE, EfiGcdMemoryTypeMemoryMappedIo, 0xFED00000, SIZE_1KB, 0, SystemTable); // HPET + ASSERT_EFI_ERROR (Status); + + // + // Find the system table information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiSystemTableInfoGuid); + ASSERT (GuidHob != NULL); + pSystemTableInfo = (SYSTEM_TABLE_INFO *)GET_GUID_HOB_DATA (GuidHob); + + // + // Install Acpi Table + // + if (pSystemTableInfo->AcpiTableBase != 0 && pSystemTableInfo->AcpiTableSize != 0) { + DEBUG ((EFI_D_ERROR, "Install Acpi Table at 0x%x, length 0x%x\n", (UINTN)pSystemTableInfo->AcpiTableBase, pSystemTableInfo->AcpiTableSize)); + Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, (VOID *)(UINTN)pSystemTableInfo->AcpiTableBase); + ASSERT_EFI_ERROR (Status); + } + + // + // Install Smbios Table + // + if (pSystemTableInfo->SmbiosTableBase != 0 && pSystemTableInfo->SmbiosTableSize != 0) { + DEBUG ((EFI_D_ERROR, "Install Smbios Table at 0x%x, length 0x%x\n", (UINTN)pSystemTableInfo->SmbiosTableBase, pSystemTableInfo->SmbiosTableSize)); + Status = gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, (VOID *)(UINTN)pSystemTableInfo->SmbiosTableBase); + ASSERT_EFI_ERROR (Status); + } + + // + // Find the acpi board information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + ASSERT (GuidHob != NULL); + pAcpiBoardInfo = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob); + + mPmCtrlReg = (UINTN)pAcpiBoardInfo->PmCtrlRegBase; + DEBUG ((EFI_D_ERROR, "PmCtrlReg at 0x%x\n", mPmCtrlReg)); + + // + // Register callback on the ready to boot event + // in order to enable SCI + // + ReadyToBootEvent = NULL; + Status = EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + OnReadyToBoot, + NULL, + &ReadyToBootEvent + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + diff --git a/CorebootModulePkg/CbSupportDxe/CbSupportDxe.h b/CorebootModulePkg/CbSupportDxe/CbSupportDxe.h new file mode 100644 index 0000000000..bace2728e6 --- /dev/null +++ b/CorebootModulePkg/CbSupportDxe/CbSupportDxe.h @@ -0,0 +1,35 @@ +/** @file + The header file of Coreboot Support DXE. + +Copyright (c) 2014, 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. + +**/ +#ifndef __DXE_COREBOOT_SUPPORT_H__ +#define __DXE_COREBOOT_SUPPORT_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#endif diff --git a/CorebootModulePkg/CbSupportDxe/CbSupportDxe.inf b/CorebootModulePkg/CbSupportDxe/CbSupportDxe.inf new file mode 100644 index 0000000000..c92db8ded4 --- /dev/null +++ b/CorebootModulePkg/CbSupportDxe/CbSupportDxe.inf @@ -0,0 +1,59 @@ +## @file +# Coreboot Support DXE Module +# +# Report some MMIO/IO resources to dxe core, extract smbios and acpi tables from coreboot and install. +# +# Copyright (c) 2014, 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CbSupportDxe + FILE_GUID = C68DAA4E-7AB5-41e8-A91D-5954421053F3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = CbDxeEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + CbSupportDxe.c + CbSupportDxe.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + CorebootModulePkg/CorebootModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DxeServicesTableLib + DebugLib + BaseMemoryLib + UefiLib + IoLib + HobLib + +[Guids] + gEfiAcpiTableGuid + gEfiSmbiosTableGuid + gUefiSystemTableInfoGuid + gUefiAcpiBoardInfoGuid + +[Depex] + TRUE diff --git a/CorebootModulePkg/CbSupportPei/CbSupportPei.c b/CorebootModulePkg/CbSupportPei/CbSupportPei.c new file mode 100644 index 0000000000..d51553dbc6 --- /dev/null +++ b/CorebootModulePkg/CbSupportPei/CbSupportPei.c @@ -0,0 +1,380 @@ +/** @file + This PEIM will parse coreboot table in memory and report resource information into pei core. + This file contains the main entrypoint of the PEIM. + +Copyright (c) 2014, 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. + +**/ +#include "CbSupportPei.h" + +EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { + { EfiACPIReclaimMemory, 0x008 }, + { EfiACPIMemoryNVS, 0x004 }, + { EfiReservedMemoryType, 0x004 }, + { EfiRuntimeServicesData, 0x080 }, + { EfiRuntimeServicesCode, 0x080 }, + { EfiMaxMemoryType, 0 } +}; + +EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiMasterBootModePpiGuid, + NULL + } +}; + +/** + Create memory mapped io resource hob. + + @param MmioBase Base address of the memory mapped io range + @param MmioSize Length of the memory mapped io range + +**/ +VOID +BuildMemoryMappedIoRangeHob ( + EFI_PHYSICAL_ADDRESS MmioBase, + UINT64 MmioSize + ) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED), + MmioBase, + MmioSize + ); + + BuildMemoryAllocationHob ( + MmioBase, + MmioSize, + EfiMemoryMappedIO + ); +} + +/** + Check the integrity of firmware volume header + + @param[in] FwVolHeader A pointer to a firmware volume header + + @retval TRUE The firmware volume is consistent + @retval FALSE The firmware volume has corrupted. + +**/ +STATIC +BOOLEAN +IsFvHeaderValid ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +{ + UINT16 Checksum; + + // Skip nv storage fv + if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) { + return FALSE; + } + + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) || + (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength == ((UINTN) -1)) || + ((FwVolHeader->HeaderLength & 0x01 ) !=0) ) { + return FALSE; + } + + Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength); + if (Checksum != 0) { + DEBUG (( DEBUG_ERROR, + "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n", + FwVolHeader->Checksum, + (UINT16)( Checksum + FwVolHeader->Checksum ))); + return FALSE; + } + + return TRUE; +} + +/** + Install FvInfo PPI and create fv hobs for remained fvs + +**/ +VOID +CbPeiReportRemainedFvs ( + VOID + ) +{ + UINT8* TempPtr; + UINT8* EndPtr; + + TempPtr = (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase); + EndPtr = (UINT8* )(UINTN) (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize)); + + for (;TempPtr < EndPtr;) { + if (IsFvHeaderValid ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)) { + if (TempPtr != (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase)) { + // Skip the PEI FV + DEBUG((EFI_D_ERROR, "Found one valid fv : 0x%x.\n", TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength)); + + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) (UINTN) TempPtr, + (UINT32) (UINTN) ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength, + NULL, + NULL + ); + BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN) TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength); + } + } + TempPtr += ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength; + } +} + +/** + This is the entrypoint of PEIM + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS if it completed successfully. +**/ +EFI_STATUS +EFIAPI +CbPeiEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UINT64 LowMemorySize, HighMemorySize; + UINT64 PeiMemSize = SIZE_64MB; // 64 MB + EFI_PHYSICAL_ADDRESS PeiMemBase = 0; + UINT32 RegEax; + UINT8 PhysicalAddressBits; + VOID* pCbHeader; + VOID* pAcpiTable; + UINT32 AcpiTableSize; + VOID* pSmbiosTable; + UINT32 SmbiosTableSize; + SYSTEM_TABLE_INFO* pSystemTableInfo; + FRAME_BUFFER_INFO FbInfo; + FRAME_BUFFER_INFO* pFbInfo; + ACPI_BOARD_INFO* pAcpiBoardInfo; + UINTN PmCtrlRegBase, PmTimerRegBase, ResetRegAddress, ResetValue; + + LowMemorySize = 0; + HighMemorySize = 0; + + Status = CbParseMemoryInfo (&LowMemorySize, &HighMemorySize); + if (EFI_ERROR(Status)) + return Status; + + DEBUG((EFI_D_ERROR, "LowMemorySize: 0x%x.\n", LowMemorySize)); + DEBUG((EFI_D_ERROR, "HighMemorySize: 0x%x.\n", HighMemorySize)); + + ASSERT (LowMemorySize > 0); + + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + 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 + ), + (EFI_PHYSICAL_ADDRESS)(0), + (UINT64)(0xA0000) + ); + + + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_RESERVED, + ( + 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 + ), + (EFI_PHYSICAL_ADDRESS)(0xA0000), + (UINT64)(0x60000) + ); + + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + 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 + ), + (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)(0x100000000), + HighMemorySize + ); + } + + // + // Should be 64k aligned + // + PeiMemBase = (LowMemorySize - PeiMemSize) & (~(BASE_64KB - 1)); + + DEBUG((EFI_D_ERROR, "PeiMemBase: 0x%x.\n", PeiMemBase)); + DEBUG((EFI_D_ERROR, "PeiMemSize: 0x%x.\n", PeiMemSize)); + + Status = PeiServicesInstallPeiMemory ( + PeiMemBase, + PeiMemSize + ); + ASSERT_EFI_ERROR (Status); + + // + // Set cache on the physical memory + // + MtrrSetMemoryAttribute (BASE_1MB, LowMemorySize - BASE_1MB, CacheWriteBack); + MtrrSetMemoryAttribute (0, 0xA0000, CacheWriteBack); + + // + // Create Memory Type Information HOB + // + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + mDefaultMemoryTypeInformation, + sizeof(mDefaultMemoryTypeInformation) + ); + + // + // Create Fv hob + // + CbPeiReportRemainedFvs (); + + BuildMemoryAllocationHob ( + PcdGet32 (PcdPayloadFdMemBase), + PcdGet32 (PcdPayloadFdMemSize), + EfiBootServicesData + ); + + // + // Build CPU memory space and IO space hob + // + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits = (UINT8) RegEax; + } else { + PhysicalAddressBits = 36; + } + // + // Create a CPU hand-off information + // + BuildCpuHob (PhysicalAddressBits, 16); + + // + // Report Local APIC range + // + BuildMemoryMappedIoRangeHob (0xFEC80000, SIZE_512KB); + + // + // Boot mode + // + Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION); + ASSERT_EFI_ERROR (Status); + + Status = PeiServicesInstallPpi (mPpiBootMode); + ASSERT_EFI_ERROR (Status); + + // + // Set pcd to save the upper coreboot header in case the dxecore will + // erase 0~4k memory + // + pCbHeader = NULL; + if ((CbParseGetCbHeader (1, &pCbHeader) == RETURN_SUCCESS) + && ((UINTN)pCbHeader > BASE_4KB)) { + DEBUG((EFI_D_ERROR, "Actual Coreboot header: 0x%x.\n", (UINTN)pCbHeader)); + PcdSet32 (PcdCbHeaderPointer, (UINT32)(UINTN)pCbHeader); + } + + // + // Create guid hob for system tables like acpi table and smbios table + // + pAcpiTable = NULL; + AcpiTableSize = 0; + pSmbiosTable = NULL; + SmbiosTableSize = 0; + Status = CbParseAcpiTable (&pAcpiTable, &AcpiTableSize); + if (EFI_ERROR (Status)) { + // ACPI table is oblidgible + DEBUG ((EFI_D_ERROR, "Failed to find the required acpi table\n")); + ASSERT (FALSE); + } + CbParseSmbiosTable (&pSmbiosTable, &SmbiosTableSize); + + pSystemTableInfo = NULL; + pSystemTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO)); + ASSERT (pSystemTableInfo != NULL); + pSystemTableInfo->AcpiTableBase = (UINT64) (UINTN)pAcpiTable; + pSystemTableInfo->AcpiTableSize = AcpiTableSize; + pSystemTableInfo->SmbiosTableBase = (UINT64) (UINTN)pSmbiosTable; + pSystemTableInfo->SmbiosTableSize = SmbiosTableSize; + DEBUG ((EFI_D_ERROR, "Detected Acpi Table at 0x%x, length 0x%x\n", (UINTN)pSystemTableInfo->AcpiTableBase, pSystemTableInfo->AcpiTableSize)); + DEBUG ((EFI_D_ERROR, "Detected Smbios Table at 0x%x, length 0x%x\n", (UINTN)pSystemTableInfo->SmbiosTableBase, pSystemTableInfo->SmbiosTableSize)); + DEBUG ((EFI_D_ERROR, "Create system table info guid hob\n")); + + // + // Create guid hob for acpi board information + // + Status = CbParseFadtInfo (&PmCtrlRegBase, &PmTimerRegBase, &ResetRegAddress, &ResetValue); + ASSERT_EFI_ERROR (Status); + pAcpiBoardInfo = NULL; + pAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO)); + ASSERT (pAcpiBoardInfo != NULL); + pAcpiBoardInfo->PmCtrlRegBase = (UINT64)PmCtrlRegBase; + pAcpiBoardInfo->PmTimerRegBase = (UINT64)PmTimerRegBase; + pAcpiBoardInfo->ResetRegAddress = (UINT64)ResetRegAddress; + pAcpiBoardInfo->ResetValue = (UINT8)ResetValue; + DEBUG ((EFI_D_ERROR, "Create acpi board info guid hob\n")); + + // + // Create guid hob for frame buffer information + // + ZeroMem (&FbInfo, sizeof (FRAME_BUFFER_INFO)); + Status = CbParseFbInfo (&FbInfo); + if (!EFI_ERROR (Status)) { + pFbInfo = BuildGuidHob (&gUefiFrameBufferInfoGuid, sizeof (FRAME_BUFFER_INFO)); + ASSERT (pSystemTableInfo != NULL); + CopyMem (pFbInfo, &FbInfo, sizeof (FRAME_BUFFER_INFO)); + DEBUG ((EFI_D_ERROR, "Create frame buffer info guid hob\n")); + } + + return EFI_SUCCESS; +} + diff --git a/CorebootModulePkg/CbSupportPei/CbSupportPei.h b/CorebootModulePkg/CbSupportPei/CbSupportPei.h new file mode 100644 index 0000000000..544838523b --- /dev/null +++ b/CorebootModulePkg/CbSupportPei/CbSupportPei.h @@ -0,0 +1,40 @@ +/** @file + The header file of Coreboot Support PEIM. + +Copyright (c) 2014, 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. + +**/ + + +#ifndef __PEI_COREBOOT_SUPPORT_H__ +#define __PEI_COREBOOT_SUPPORT_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#endif diff --git a/CorebootModulePkg/CbSupportPei/CbSupportPei.inf b/CorebootModulePkg/CbSupportPei/CbSupportPei.inf new file mode 100644 index 0000000000..9328151554 --- /dev/null +++ b/CorebootModulePkg/CbSupportPei/CbSupportPei.inf @@ -0,0 +1,72 @@ +## @file +# Coreboot Support PEI Module +# +# Parses coreboot table in memory and report resource information into pei core. It will install +# the memory as required. +# +# Copyright (c) 2014, 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CbSupportPeim + FILE_GUID = 352C6AF8-315B-4bd6-B04F-31D4ED1EBE57 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = CbPeiEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + CbSupportPei.c + CbSupportPei.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + CorebootModulePkg/CorebootModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + PeimEntryPoint + PeiServicesLib + BaseLib + BaseMemoryLib + DebugLib + HobLib + PcdLib + CbParseLib + MtrrLib + +[Guids] + gEfiSmmPeiSmramMemoryReserveGuid + gEfiMemoryTypeInformationGuid + gEfiFirmwareFileSystem2Guid + gUefiSystemTableInfoGuid + gUefiFrameBufferInfoGuid + gUefiAcpiBoardInfoGuid + +[Ppis] + gEfiPeiMasterBootModePpiGuid + +[Pcd] + gUefiCorebootModulePkgTokenSpaceGuid.PcdPayloadFdMemBase + gUefiCorebootModulePkgTokenSpaceGuid.PcdPayloadFdMemSize + gUefiCorebootModulePkgTokenSpaceGuid.PcdCbHeaderPointer + +[Depex] + TRUE \ No newline at end of file diff --git a/CorebootModulePkg/CorebootModulePkg.dec b/CorebootModulePkg/CorebootModulePkg.dec new file mode 100644 index 0000000000..4b97f9f249 --- /dev/null +++ b/CorebootModulePkg/CorebootModulePkg.dec @@ -0,0 +1,59 @@ +## @file +# Coreboot Support Package +# +# Provides drivers and definitions to support coreboot in EDKII bios. +# +# Copyright (c) 2014, 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 that 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. +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = CorebootModulePkg + PACKAGE_GUID = DE1750CE-FEE7-4dd1-8E9C-B7B8BAEBCF4F + PACKAGE_VERSION = 0.1 + +[Includes] + Include + +[LibraryClasses] + CbParseLib|Include/Library/CbParseLib.h + +[Guids] + # + ## Defines the token space for the Coreboot Module Package PCDs. + # + gUefiCorebootModulePkgTokenSpaceGuid = {0xe6ff49a0, 0x15df, 0x48fd, {0x9a, 0xcf, 0xd7, 0xdc, 0x27, 0x1b, 0x39, 0xd5}} + gUefiSystemTableInfoGuid = {0x16c8a6d0, 0xfe8a, 0x4082, {0xa2, 0x8, 0xcf, 0x89, 0xc4, 0x29, 0x4, 0x33}} + gUefiFrameBufferInfoGuid = {0xdc2cd8bd, 0x402c, 0x4dc4, {0x9b, 0xe0, 0xc, 0x43, 0x2b, 0x7, 0xfa, 0x34}} + gUefiAcpiBoardInfoGuid = {0xad3d31b, 0xb3d8, 0x4506, {0xae, 0x71, 0x2e, 0xf1, 0x10, 0x6, 0xd9, 0xf}} + + +[Ppis] + +[Protocols] + + +################################################################################ +# +# PCD Declarations section - list of all PCDs Declared by this Package +# Only this package should be providing the +# declaration, other packages should not. +# +################################################################################ +[PcdsFixedAtBuild, PcdsPatchableInModule] +## Indicates the base address of the payload binary in memory +gUefiCorebootModulePkgTokenSpaceGuid.PcdPayloadFdMemBase|0|UINT32|0x10000001 +## Provides the size of the payload binary in memory +gUefiCorebootModulePkgTokenSpaceGuid.PcdPayloadFdMemSize|0|UINT32|0x10000002 + +[PcdsDynamicEx] +gUefiCorebootModulePkgTokenSpaceGuid.PcdCbHeaderPointer|0|UINT32|0x10000003 + diff --git a/CorebootModulePkg/Include/Coreboot.h b/CorebootModulePkg/Include/Coreboot.h new file mode 100644 index 0000000000..7bec1f3d6f --- /dev/null +++ b/CorebootModulePkg/Include/Coreboot.h @@ -0,0 +1,219 @@ +/** @file + Coreboot PEI module include file. + + Copyright (c) 2014, 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. + +**/ + +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _COREBOOT_PEI_H_INCLUDED_ +#define _COREBOOT_PEI_H_INCLUDED_ + +#pragma warning( disable : 4200 ) + +#define DYN_CBMEM_ALIGN_SIZE (4096) + +struct cbmem_entry { + UINT32 magic; + UINT32 start; + UINT32 size; + UINT32 id; +}; + +struct cbmem_root { + UINT32 max_entries; + UINT32 num_entries; + UINT32 locked; + UINT32 size; + struct cbmem_entry entries[0]; +}; + +struct cbuint64 { + UINT32 lo; + UINT32 hi; +}; + +#define CB_HEADER_SIGNATURE 0x4F49424C + +struct cb_header { + UINT32 signature; + UINT32 header_bytes; + UINT32 header_checksum; + UINT32 table_bytes; + UINT32 table_checksum; + UINT32 table_entries; +}; + +struct cb_record { + UINT32 tag; + UINT32 size; +}; + +#define CB_TAG_UNUSED 0x0000 +#define CB_TAG_MEMORY 0x0001 + +struct cb_memory_range { + struct cbuint64 start; + struct cbuint64 size; + UINT32 type; +}; + +#define CB_MEM_RAM 1 +#define CB_MEM_RESERVED 2 +#define CB_MEM_ACPI 3 +#define CB_MEM_NVS 4 +#define CB_MEM_UNUSABLE 5 +#define CB_MEM_VENDOR_RSVD 6 +#define CB_MEM_TABLE 16 + +struct cb_memory { + UINT32 tag; + UINT32 size; + struct cb_memory_range map[0]; +}; + +#define CB_TAG_MAINBOARD 0x0003 + +struct cb_mainboard { + UINT32 tag; + UINT32 size; + UINT8 vendor_idx; + UINT8 part_number_idx; + UINT8 strings[0]; +}; +#define CB_TAG_VERSION 0x0004 +#define CB_TAG_EXTRA_VERSION 0x0005 +#define CB_TAG_BUILD 0x0006 +#define CB_TAG_COMPILE_TIME 0x0007 +#define CB_TAG_COMPILE_BY 0x0008 +#define CB_TAG_COMPILE_HOST 0x0009 +#define CB_TAG_COMPILE_DOMAIN 0x000a +#define CB_TAG_COMPILER 0x000b +#define CB_TAG_LINKER 0x000c +#define CB_TAG_ASSEMBLER 0x000d + +struct cb_string { + UINT32 tag; + UINT32 size; + UINT8 string[0]; +}; + +#define CB_TAG_SERIAL 0x000f + +struct cb_serial { + UINT32 tag; + UINT32 size; +#define CB_SERIAL_TYPE_IO_MAPPED 1 +#define CB_SERIAL_TYPE_MEMORY_MAPPED 2 + UINT32 type; + UINT32 baseaddr; + UINT32 baud; +}; + +#define CB_TAG_CONSOLE 0x00010 + +struct cb_console { + UINT32 tag; + UINT32 size; + UINT16 type; +}; + +#define CB_TAG_CONSOLE_SERIAL8250 0 +#define CB_TAG_CONSOLE_VGA 1 // OBSOLETE +#define CB_TAG_CONSOLE_BTEXT 2 // OBSOLETE +#define CB_TAG_CONSOLE_LOGBUF 3 +#define CB_TAG_CONSOLE_SROM 4 // OBSOLETE +#define CB_TAG_CONSOLE_EHCI 5 + +#define CB_TAG_FORWARD 0x00011 + +struct cb_forward { + UINT32 tag; + UINT32 size; + UINT64 forward; +}; + +#define CB_TAG_FRAMEBUFFER 0x0012 +struct cb_framebuffer { + UINT32 tag; + UINT32 size; + + UINT64 physical_address; + UINT32 x_resolution; + UINT32 y_resolution; + UINT32 bytes_per_line; + UINT8 bits_per_pixel; + UINT8 red_mask_pos; + UINT8 red_mask_size; + UINT8 green_mask_pos; + UINT8 green_mask_size; + UINT8 blue_mask_pos; + UINT8 blue_mask_size; + UINT8 reserved_mask_pos; + UINT8 reserved_mask_size; +}; + +#define CB_TAG_VDAT 0x0015 +struct cb_vdat { + UINT32 tag; + UINT32 size; /* size of the entire entry */ + UINT64 vdat_addr; + UINT32 vdat_size; +}; + +#define CB_TAG_TIMESTAMPS 0x0016 +#define CB_TAG_CBMEM_CONSOLE 0x0017 +#define CB_TAG_MRC_CACHE 0x0018 +struct cb_cbmem_tab { + UINT32 tag; + UINT32 size; + UINT64 cbmem_tab; +}; + +/* Helpful macros */ + +#define MEM_RANGE_COUNT(_rec) \ + (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0])) + +#define MEM_RANGE_PTR(_rec, _idx) \ + (void *)(((UINT8 *) (_rec)) + sizeof(*(_rec)) \ + + (sizeof((_rec)->map[0]) * (_idx))) + + +#endif // _COREBOOT_PEI_H_INCLUDED_ diff --git a/CorebootModulePkg/Include/Guid/AcpiBoardInfoGuid.h b/CorebootModulePkg/Include/Guid/AcpiBoardInfoGuid.h new file mode 100644 index 0000000000..66ebffef2d --- /dev/null +++ b/CorebootModulePkg/Include/Guid/AcpiBoardInfoGuid.h @@ -0,0 +1,30 @@ +/** @file + This file defines the hob structure for board related information from acpi table + + Copyright (c) 2014, 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. + +**/ + +#ifndef __ACPI_BOARD_INFO_GUID_H__ +#define __ACPI_BOARD_INFO_GUID_H__ + +/// +/// Board information GUID +/// +extern EFI_GUID gUefiAcpiBoardInfoGuid; + +typedef struct { + UINT64 PmCtrlRegBase; + UINT64 PmTimerRegBase; + UINT64 ResetRegAddress; + UINT8 ResetValue; +} ACPI_BOARD_INFO; + +#endif diff --git a/CorebootModulePkg/Include/Guid/FrameBufferInfoGuid.h b/CorebootModulePkg/Include/Guid/FrameBufferInfoGuid.h new file mode 100644 index 0000000000..be5ca49abc --- /dev/null +++ b/CorebootModulePkg/Include/Guid/FrameBufferInfoGuid.h @@ -0,0 +1,40 @@ +/** @file + This file defines the hob structure for frame buffer device. + + Copyright (c) 2014, 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. + +**/ + +#ifndef __FRAME_BUFFER_INFO_GUID_H__ +#define __FRAME_BUFFER_INFO_GUID_H__ + +/// +/// Frame Buffer Information GUID +/// +extern EFI_GUID gUefiFrameBufferInfoGuid; + +typedef struct { + UINT8 Position; // Position of the color + UINT8 Mask; // The number of bits expressed as a mask +} COLOR_PLACEMENT; + +typedef struct { + UINT64 LinearFrameBuffer; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 BitsPerPixel; + UINT16 BytesPerScanLine; + COLOR_PLACEMENT Red; + COLOR_PLACEMENT Green; + COLOR_PLACEMENT Blue; + COLOR_PLACEMENT Reserved; +} FRAME_BUFFER_INFO; + +#endif diff --git a/CorebootModulePkg/Include/Guid/SystemTableInfoGuid.h b/CorebootModulePkg/Include/Guid/SystemTableInfoGuid.h new file mode 100644 index 0000000000..5147645911 --- /dev/null +++ b/CorebootModulePkg/Include/Guid/SystemTableInfoGuid.h @@ -0,0 +1,30 @@ +/** @file + This file defines the hob structure for system tables like ACPI, SMBIOS tables. + + Copyright (c) 2014, 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. + +**/ + +#ifndef __SYSTEM_TABLE_INFO_GUID_H__ +#define __SYSTEM_TABLE_INFO_GUID_H__ + +/// +/// System Table Information GUID +/// +extern EFI_GUID gUefiSystemTableInfoGuid; + +typedef struct { + UINT64 AcpiTableBase; + UINT32 AcpiTableSize; + UINT64 SmbiosTableBase; + UINT32 SmbiosTableSize; +} SYSTEM_TABLE_INFO; + +#endif diff --git a/CorebootModulePkg/Include/Library/CbParseLib.h b/CorebootModulePkg/Include/Library/CbParseLib.h new file mode 100644 index 0000000000..36727d3f58 --- /dev/null +++ b/CorebootModulePkg/Include/Library/CbParseLib.h @@ -0,0 +1,154 @@ +/** @file + This library will parse the coreboot table in memory and extract those required + information. + + Copyright (c) 2014, 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. + +**/ +#include + +/** + Acquire the memory information from the coreboot table in memory. + + @param pLowMemorySize Pointer to the variable of low memory size + @param pHighMemorySize Pointer to the variable of high memory size + + @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. + +**/ +RETURN_STATUS +CbParseMemoryInfo ( + IN UINT64* pLowMemorySize, + IN UINT64* pHighMemorySize + ); + +/** + Acquire the coreboot memory table with the given table id + + @param TableId Table id to be searched + @param pMemTable Pointer to the base address of the memory table + @param pMemTableSize Pointer to the size of the memory table + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +CbParseCbMemTable ( + IN UINT32 TableId, + IN VOID** pMemTable, + IN UINT32* pMemTableSize + ); + +/** + Acquire the acpi table from coreboot + + @param pMemTable Pointer to the base address of the memory table + @param pMemTableSize Pointer to the size of the memory table + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +CbParseAcpiTable ( + IN VOID** pMemTable, + IN UINT32* pMemTableSize + ); + +/** + Acquire the smbios table from coreboot + + @param pMemTable Pointer to the base address of the memory table + @param pMemTableSize Pointer to the size of the memory table + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +CbParseSmbiosTable ( + IN VOID** pMemTable, + IN UINT32* pMemTableSize + ); + +/** + Find the required fadt information + + @param pPmCtrlReg Pointer to the address of power management control register + @param pPmTimerReg Pointer to the address of power management timer register + @param pResetReg Pointer to the address of system reset register + @param pResetValue Pointer to the value to be writen to the system reset register + + @retval RETURN_SUCCESS Successfully find out all the required fadt information. + @retval RETURN_NOT_FOUND Failed to find the fadt table. + +**/ +RETURN_STATUS +CbParseFadtInfo ( + IN UINTN* pPmCtrlReg, + IN UINTN* pPmTimerReg, + IN UINTN* pResetReg, + IN UINTN* pResetValue + ); + +/** + Find the serial port information + + @param pRegBase Pointer to the base address of serial port registers + @param pRegAccessType Pointer to the access type of serial port registers + @param pBaudrate Pointer to the serial port baudrate + + @retval RETURN_SUCCESS Successfully find the serial port information. + @retval RETURN_NOT_FOUND Failed to find the serial port information . + +**/ +RETURN_STATUS +CbParseSerialInfo ( + IN UINT32* pRegBase, + IN UINT32* pRegAccessType, + IN UINT32* pBaudrate + ); + +/** + Search for the coreboot table header + + @param Level Level of the search depth + @param HeaderPtr Pointer to the pointer of coreboot table header + + @retval RETURN_SUCCESS Successfully find the coreboot table header . + @retval RETURN_NOT_FOUND Failed to find the coreboot table header . + +**/ +RETURN_STATUS +CbParseGetCbHeader ( + IN UINTN Level, + IN VOID** HeaderPtr + ); + +/** + Find the video frame buffer information + + @param pFbInfo Pointer to the FRAME_BUFFER_INFO structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +CbParseFbInfo ( + IN FRAME_BUFFER_INFO* pFbInfo + ); + diff --git a/CorebootModulePkg/Library/CbParseLib/CbParseLib.c b/CorebootModulePkg/Library/CbParseLib/CbParseLib.c new file mode 100644 index 0000000000..5535fdcdd5 --- /dev/null +++ b/CorebootModulePkg/Library/CbParseLib/CbParseLib.c @@ -0,0 +1,567 @@ +/** @file + This library will parse the coreboot table in memory and extract those required + information. + + Copyright (c) 2014, 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. + +**/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "Coreboot.h" + +/* Helpful inlines */ + +static UINT64 cb_unpack64(struct cbuint64 val) +{ + return (((UINT64) val.hi) << 32) | val.lo; +} + +static const char *cb_mb_vendor_string(const struct cb_mainboard *cbm) +{ + return (char *)(cbm->strings + cbm->vendor_idx); +} + +static const char *cb_mb_part_string(const struct cb_mainboard *cbm) +{ + return (char *)(cbm->strings + cbm->part_number_idx); +} + +UINT16 +CbCheckSum16 ( + IN UINT16 *Buffer, + IN UINTN Length + ) +{ + UINT32 Sum, TmpValue; + UINTN Idx; + UINT8 *TmpPtr; + + Sum = 0; + TmpPtr = (UINT8 *)Buffer; + for(Idx = 0; Idx < Length; Idx++) { + TmpValue = TmpPtr[Idx]; + if (Idx % 2 == 1) { + TmpValue <<= 8; + } + + Sum += TmpValue; + + // Wrap + if (Sum >= 0x10000) { + Sum = (Sum + (Sum >> 16)) & 0xFFFF; + } + } + + return (UINT16)((~Sum) & 0xFFFF); +} + +VOID * +FindCbTag ( + IN VOID *Start, + IN UINT32 Tag + ) +{ + struct cb_header *Header; + struct cb_record *Record; + UINT8 *TmpPtr; + UINT8 *TagPtr; + UINTN Idx; + UINT16 CheckSum; + + Header = NULL; + TmpPtr = (UINT8 *)Start; + for (Idx = 0; Idx < 4096; Idx += 16, TmpPtr += 16) { + Header = (struct cb_header *)TmpPtr; + if (Header->signature == CB_HEADER_SIGNATURE) { + break; + } + } + + if (Idx >= 4096) + return NULL; + + if (Header == NULL || !Header->table_bytes) + return NULL; + + // + // Check the checksum of the coreboot table header + // + CheckSum = CbCheckSum16 ((UINT16 *)Header, sizeof (*Header)); + if (CheckSum != 0) { + DEBUG ((EFI_D_ERROR, "Invalid coreboot table header checksum\n")); + return NULL; + } + + CheckSum = CbCheckSum16 ((UINT16 *)(TmpPtr + sizeof (*Header)), Header->table_bytes); + if (CheckSum != Header->table_checksum) { + DEBUG ((EFI_D_ERROR, "Incorrect checksum of all the coreboot table entries\n")); + return NULL; + } + + TagPtr = NULL; + TmpPtr += Header->header_bytes; + for (Idx = 0; Idx < Header->table_entries; Idx++) { + Record = (struct cb_record *)TmpPtr; + if (Record->tag == CB_TAG_FORWARD) { + TmpPtr = (VOID *)(UINTN)((struct cb_forward *)(UINTN)Record)->forward; + if (Tag == CB_TAG_FORWARD) + return TmpPtr; + else + return FindCbTag (TmpPtr, Tag); + } + if (Record->tag == Tag) { + TagPtr = TmpPtr; + break; + } + TmpPtr += Record->size; + } + + return TagPtr; +} + +RETURN_STATUS +FindCbMemTable ( + struct cbmem_root *root, + IN UINT32 TableId, + IN VOID** pMemTable, + IN UINT32* pMemTableSize +) +{ + UINTN Idx; + + if ((!root) || (!pMemTable)) + return RETURN_INVALID_PARAMETER; + + for (Idx = 0; Idx < root->num_entries; Idx++) { + if (root->entries[Idx].id == TableId) { + *pMemTable = (VOID *) (UINTN)root->entries[Idx].start; + if (pMemTableSize) + *pMemTableSize = root->entries[Idx].size; + + DEBUG ((EFI_D_ERROR, "Find CbMemTable Id 0x%x, base 0x%x, size 0x%x\n", TableId, *pMemTable, *pMemTableSize)); + return RETURN_SUCCESS; + } + } + + return RETURN_NOT_FOUND; +} + + +/** + Acquire the memory information from the coreboot table in memory. + + @param pLowMemorySize Pointer to the variable of low memory size + @param pHighMemorySize Pointer to the variable of high memory size + + @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. + +**/ +RETURN_STATUS +CbParseMemoryInfo ( + IN UINT64* pLowMemorySize, + IN UINT64* pHighMemorySize + ) +{ + struct cb_memory* rec; + struct cb_memory_range* Range; + UINT64 Start; + UINT64 Size; + UINTN Index; + + if ((!pLowMemorySize) || (!pHighMemorySize)) + return RETURN_INVALID_PARAMETER; + + // + // Get the coreboot memory table + // + rec = (struct cb_memory *)FindCbTag (0, CB_TAG_MEMORY); + if (!rec) + rec = (struct cb_memory *)FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_MEMORY); + + if (!rec) + return RETURN_NOT_FOUND; + + *pLowMemorySize = 0; + *pHighMemorySize = 0; + + for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) { + Range = MEM_RANGE_PTR(rec, Index); + Start = cb_unpack64(Range->start); + Size = cb_unpack64(Range->size); + DEBUG ((EFI_D_ERROR, "%d. %016lx - %016lx [%02x]\n", + Index, Start, Start + Size - 1, Range->type)); + + if (Range->type != CB_MEM_RAM) { + continue; + } + + if (Start + Size < 0x100000000ULL) { + *pLowMemorySize = Start + Size; + } else { + *pHighMemorySize = Start + Size - 0x100000000ULL; + } + } + + DEBUG ((EFI_D_ERROR, "Low memory 0x%x, High Memory 0x%x\n", *pLowMemorySize, *pHighMemorySize)); + + return RETURN_SUCCESS; +} + + +/** + Acquire the coreboot memory table with the given table id + + @param TableId Table id to be searched + @param pMemTable Pointer to the base address of the memory table + @param pMemTableSize Pointer to the size of the memory table + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +CbParseCbMemTable ( + IN UINT32 TableId, + IN VOID** pMemTable, + IN UINT32* pMemTableSize + ) +{ + struct cb_memory* rec; + struct cb_memory_range* Range; + UINT64 Start; + UINT64 Size; + UINTN Index; + + if (!pMemTable) + return RETURN_INVALID_PARAMETER; + + *pMemTable = NULL; + + // + // Get the coreboot memory table + // + rec = (struct cb_memory *)FindCbTag (0, CB_TAG_MEMORY); + if (!rec) + rec = (struct cb_memory *)FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_MEMORY); + + if (!rec) + return RETURN_NOT_FOUND; + + for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) { + Range = MEM_RANGE_PTR(rec, Index); + Start = cb_unpack64(Range->start); + Size = cb_unpack64(Range->size); + + if ((Range->type == CB_MEM_TABLE) && (Start > 0x1000)) { + if (FindCbMemTable ((struct cbmem_root *)(UINTN)(Start + Size - DYN_CBMEM_ALIGN_SIZE), TableId, pMemTable, pMemTableSize) == RETURN_SUCCESS) + return RETURN_SUCCESS; + } + } + + return RETURN_NOT_FOUND; +} + + +/** + Acquire the acpi table from coreboot + + @param pMemTable Pointer to the base address of the memory table + @param pMemTableSize Pointer to the size of the memory table + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +CbParseAcpiTable ( + IN VOID** pMemTable, + IN UINT32* pMemTableSize + ) +{ + return CbParseCbMemTable (SIGNATURE_32 ('I', 'P', 'C', 'A'), pMemTable, pMemTableSize); +} + +/** + Acquire the smbios table from coreboot + + @param pMemTable Pointer to the base address of the memory table + @param pMemTableSize Pointer to the size of the memory table + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +CbParseSmbiosTable ( + IN VOID** pMemTable, + IN UINT32* pMemTableSize + ) +{ + return CbParseCbMemTable (SIGNATURE_32 ('T', 'B', 'M', 'S'), pMemTable, pMemTableSize); +} + +/** + Find the required fadt information + + @param pPmCtrlReg Pointer to the address of power management control register + @param pPmTimerReg Pointer to the address of power management timer register + @param pResetReg Pointer to the address of system reset register + @param pResetValue Pointer to the value to be writen to the system reset register + + @retval RETURN_SUCCESS Successfully find out all the required fadt information. + @retval RETURN_NOT_FOUND Failed to find the fadt table. + +**/ +RETURN_STATUS +CbParseFadtInfo ( + IN UINTN* pPmCtrlReg, + IN UINTN* pPmTimerReg, + IN UINTN* pResetReg, + IN UINTN* pResetValue + ) +{ + EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER* Rsdp; + EFI_ACPI_DESCRIPTION_HEADER* Rsdt; + UINT32* Entry32; + UINTN Entry32Num; + EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE* Fadt; + EFI_ACPI_DESCRIPTION_HEADER* Xsdt; + UINT64* Entry64; + UINTN Entry64Num; + UINTN Idx; + RETURN_STATUS Status; + + Rsdp = NULL; + Status = RETURN_SUCCESS; + + Status = CbParseAcpiTable (&Rsdp, NULL); + if (RETURN_ERROR(Status)) + return Status; + + if (!Rsdp) + return RETURN_NOT_FOUND; + + DEBUG ((EFI_D_ERROR, "Find Rsdp at 0x%x\n", Rsdp)); + DEBUG ((EFI_D_ERROR, "Find Rsdt 0x%x, Xsdt 0x%x\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress)); + + // + // Search Rsdt First + // + Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress); + if (Rsdt != NULL) { + Entry32 = (UINT32 *)(Rsdt + 1); + Entry32Num = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 2; + for (Idx = 0; Idx < Entry32Num; Idx++) { + if (*(UINT32 *)(UINTN)(Entry32[Idx]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { + Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)(Entry32[Idx]); + if (pPmCtrlReg) + *pPmCtrlReg = Fadt->Pm1aCntBlk; + DEBUG ((EFI_D_ERROR, "PmCtrl Reg 0x%x\n", Fadt->Pm1aCntBlk)); + + if (pPmTimerReg) + *pPmTimerReg = Fadt->PmTmrBlk; + DEBUG ((EFI_D_ERROR, "PmTimer Reg 0x%x\n", Fadt->PmTmrBlk)); + + if (pResetReg) + *pResetReg = (UINTN)Fadt->ResetReg.Address; + DEBUG ((EFI_D_ERROR, "Reset Reg 0x%x\n", Fadt->ResetReg.Address)); + + if (pResetValue) + *pResetValue = Fadt->ResetValue; + DEBUG ((EFI_D_ERROR, "Reset Value 0x%x\n", Fadt->ResetValue)); + + return RETURN_SUCCESS; + } + } + } + + // + // Search Xsdt Second + // + Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress); + if (Xsdt != NULL) { + Entry64 = (UINT64 *)(Xsdt + 1); + Entry64Num = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 3; + for (Idx = 0; Idx < Entry64Num; Idx++) { + if (*(UINT32 *)(UINTN)(Entry64[Idx]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { + Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)(Entry64[Idx]); + if (pPmCtrlReg) + *pPmCtrlReg = Fadt->Pm1aCntBlk; + DEBUG ((EFI_D_ERROR, "PmCtrl Reg 0x%x\n", Fadt->Pm1aCntBlk)); + + if (pPmTimerReg) + *pPmTimerReg = Fadt->PmTmrBlk; + DEBUG ((EFI_D_ERROR, "PmTimer Reg 0x%x\n", Fadt->PmTmrBlk)); + + if (pResetReg) + *pResetReg = (UINTN)Fadt->ResetReg.Address; + DEBUG ((EFI_D_ERROR, "Reset Reg 0x%x\n", Fadt->ResetReg.Address)); + + if (pResetValue) + *pResetValue = Fadt->ResetValue; + DEBUG ((EFI_D_ERROR, "Reset Value 0x%x\n", Fadt->ResetValue)); + + return RETURN_SUCCESS; + } + } + } + + return RETURN_NOT_FOUND; +} + +/** + Find the serial port information + + @param pRegBase Pointer to the base address of serial port registers + @param pRegAccessType Pointer to the access type of serial port registers + @param pBaudrate Pointer to the serial port baudrate + + @retval RETURN_SUCCESS Successfully find the serial port information. + @retval RETURN_NOT_FOUND Failed to find the serial port information . + +**/ +RETURN_STATUS +CbParseSerialInfo ( + IN UINT32* pRegBase, + IN UINT32* pRegAccessType, + IN UINT32* pBaudrate + ) +{ + struct cb_serial* CbSerial; + + CbSerial = FindCbTag (0, CB_TAG_SERIAL); + if (!CbSerial) + CbSerial = FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_SERIAL); + + if (!CbSerial) + return RETURN_NOT_FOUND; + + if (pRegBase) + *pRegBase = CbSerial->baseaddr; + + if (pRegAccessType) + *pRegAccessType = CbSerial->type; + + if (pBaudrate) + *pBaudrate = CbSerial->baud; + + return RETURN_SUCCESS; +} + +/** + Search for the coreboot table header + + @param Level Level of the search depth + @param HeaderPtr Pointer to the pointer of coreboot table header + + @retval RETURN_SUCCESS Successfully find the coreboot table header . + @retval RETURN_NOT_FOUND Failed to find the coreboot table header . + +**/ +RETURN_STATUS +CbParseGetCbHeader ( + IN UINTN Level, + IN VOID** HeaderPtr + ) +{ + UINTN Index; + VOID* TempPtr; + + if (!HeaderPtr) + return RETURN_NOT_FOUND; + + TempPtr = NULL; + for (Index = 0; Index < Level; Index++) { + TempPtr = FindCbTag (TempPtr, CB_TAG_FORWARD); + if (!TempPtr) + break; + } + + if ((Index >= Level) && (TempPtr != NULL)) { + *HeaderPtr = TempPtr; + return RETURN_SUCCESS; + } + + return RETURN_NOT_FOUND; +} + +/** + Find the video frame buffer information + + @param pFbInfo Pointer to the FRAME_BUFFER_INFO structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +CbParseFbInfo ( + IN FRAME_BUFFER_INFO* pFbInfo + ) +{ + struct cb_framebuffer* CbFbRec; + + if (!pFbInfo) + return RETURN_INVALID_PARAMETER; + + CbFbRec = FindCbTag (0, CB_TAG_FRAMEBUFFER); + if (!CbFbRec) + CbFbRec = FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_FRAMEBUFFER); + + if (!CbFbRec) + return RETURN_NOT_FOUND; + + DEBUG ((EFI_D_ERROR, "Found coreboot video frame buffer information\n")); + DEBUG ((EFI_D_ERROR, "physical_address: 0x%x\n", CbFbRec->physical_address)); + DEBUG ((EFI_D_ERROR, "x_resolution: 0x%x\n", CbFbRec->x_resolution)); + DEBUG ((EFI_D_ERROR, "y_resolution: 0x%x\n", CbFbRec->y_resolution)); + DEBUG ((EFI_D_ERROR, "bits_per_pixel: 0x%x\n", CbFbRec->bits_per_pixel)); + DEBUG ((EFI_D_ERROR, "bytes_per_line: 0x%x\n", CbFbRec->bytes_per_line)); + + DEBUG ((EFI_D_ERROR, "red_mask_size: 0x%x\n", CbFbRec->red_mask_size)); + DEBUG ((EFI_D_ERROR, "red_mask_pos: 0x%x\n", CbFbRec->red_mask_pos)); + DEBUG ((EFI_D_ERROR, "green_mask_size: 0x%x\n", CbFbRec->green_mask_size)); + DEBUG ((EFI_D_ERROR, "green_mask_pos: 0x%x\n", CbFbRec->green_mask_pos)); + DEBUG ((EFI_D_ERROR, "blue_mask_size: 0x%x\n", CbFbRec->blue_mask_size)); + DEBUG ((EFI_D_ERROR, "blue_mask_pos: 0x%x\n", CbFbRec->blue_mask_pos)); + DEBUG ((EFI_D_ERROR, "reserved_mask_size: 0x%x\n", CbFbRec->reserved_mask_size)); + DEBUG ((EFI_D_ERROR, "reserved_mask_pos: 0x%x\n", CbFbRec->reserved_mask_pos)); + + pFbInfo->LinearFrameBuffer = CbFbRec->physical_address; + pFbInfo->HorizontalResolution = CbFbRec->x_resolution; + pFbInfo->VerticalResolution = CbFbRec->y_resolution; + pFbInfo->BitsPerPixel = CbFbRec->bits_per_pixel; + pFbInfo->BytesPerScanLine = (UINT16)CbFbRec->bytes_per_line; + pFbInfo->Red.Mask = (1 << CbFbRec->red_mask_size) - 1; + pFbInfo->Red.Position = CbFbRec->red_mask_pos; + pFbInfo->Green.Mask = (1 << CbFbRec->green_mask_size) - 1; + pFbInfo->Green.Position = CbFbRec->green_mask_pos; + pFbInfo->Blue.Mask = (1 << CbFbRec->blue_mask_size) - 1; + pFbInfo->Blue.Position = CbFbRec->blue_mask_pos; + pFbInfo->Reserved.Mask = (1 << CbFbRec->reserved_mask_size) - 1; + pFbInfo->Reserved.Position = CbFbRec->reserved_mask_pos; + + return RETURN_SUCCESS; +} + + diff --git a/CorebootModulePkg/Library/CbParseLib/CbParseLib.inf b/CorebootModulePkg/Library/CbParseLib/CbParseLib.inf new file mode 100644 index 0000000000..d7146a415b --- /dev/null +++ b/CorebootModulePkg/Library/CbParseLib/CbParseLib.inf @@ -0,0 +1,44 @@ +## @file +# Coreboot Table Parse Library. +# +# Copyright (c) 2014, 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CbParseLib + FILE_GUID = 49EDFC9E-5945-4386-9C0B-C9B60CD45BB1 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CbParseLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + CbParseLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CorebootModulePkg/CorebootModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + PcdLib + +[Pcd] + gUefiCorebootModulePkgTokenSpaceGuid.PcdCbHeaderPointer \ No newline at end of file diff --git a/CorebootModulePkg/SecCore/FindPeiCore.c b/CorebootModulePkg/SecCore/FindPeiCore.c new file mode 100644 index 0000000000..4ce032e72d --- /dev/null +++ b/CorebootModulePkg/SecCore/FindPeiCore.c @@ -0,0 +1,199 @@ +/** @file + Locate the entry point for the PEI Core + +Copyright (c) 2013, 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. + +**/ + +#include +#include +#include + +#include "SecMain.h" + +/** + Find core image base. + + @param BootFirmwareVolumePtr Point to the boot firmware volume. + @param SecCoreImageBase The base address of the SEC core image. + @param PeiCoreImageBase The base address of the PEI core image. + +**/ +EFI_STATUS +EFIAPI +FindImageBase ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + *SecCoreImageBase = 0; + *PeiCoreImageBase = 0; + + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr; + EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) { + + CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL; + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; + if (IS_FFS_FILE2 (File)) { + Size = FFS_FILE2_SIZE (File); + if (Size <= 0x00FFFFFF) { + return EFI_NOT_FOUND; + } + } else { + Size = FFS_FILE_SIZE (File); + if (Size < sizeof (EFI_FFS_FILE_HEADER)) { + return EFI_NOT_FOUND; + } + } + + EndOfFile = CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + // + // Look for SEC Core / PEI Core files + // + if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE && + File->Type != EFI_FV_FILETYPE_PEI_CORE) { + continue; + } + + // + // Loop through the FFS file sections within the FFS file + // + if (IS_FFS_FILE2 (File)) { + EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER2)); + } else { + EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER)); + } + for (;;) { + CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL; + Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + + if (IS_SECTION2 (Section)) { + Size = SECTION2_SIZE (Section); + if (Size <= 0x00FFFFFF) { + return EFI_NOT_FOUND; + } + } else { + Size = SECTION_SIZE (Section); + if (Size < sizeof (EFI_COMMON_SECTION_HEADER)) { + return EFI_NOT_FOUND; + } + } + + EndOfSection = CurrentAddress + Size; + if (EndOfSection > EndOfFile) { + return EFI_NOT_FOUND; + } + + // + // Look for executable sections + // + if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) { + if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) { + if (IS_SECTION2 (Section)) { + *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2)); + } else { + *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER)); + } + } else { + if (IS_SECTION2 (Section)) { + *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2)); + } else { + *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER)); + } + } + break; + } + } + + // + // Both SEC Core and PEI Core images found + // + if (*SecCoreImageBase != 0 && *PeiCoreImageBase != 0) { + return EFI_SUCCESS; + } + } +} + +/** + Find and return Pei Core entry point. + + It also find SEC and PEI Core file debug inforamtion. It will report them if + remote debug is enabled. + + @param BootFirmwareVolumePtr Point to the boot firmware volume. + @param PeiCoreEntryPoint The entry point of the PEI core. + +**/ +VOID +EFIAPI +FindAndReportEntryPoints ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS SecCoreImageBase; + EFI_PHYSICAL_ADDRESS PeiCoreImageBase; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + // + // Find SEC Core and PEI Core image base + // + Status = FindImageBase (BootFirmwareVolumePtr, &SecCoreImageBase, &PeiCoreImageBase); + ASSERT_EFI_ERROR (Status); + + ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + // + // Report SEC Core debug information when remote debug is enabled + // + ImageContext.ImageAddress = SecCoreImageBase; + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Report PEI Core debug information when remote debug is enabled + // + ImageContext.ImageAddress = PeiCoreImageBase; + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Find PEI Core entry point + // + Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint); + if (EFI_ERROR (Status)) { + *PeiCoreEntryPoint = 0; + } + + return; +} + diff --git a/CorebootModulePkg/SecCore/Ia32/SecEntry.S b/CorebootModulePkg/SecCore/Ia32/SecEntry.S new file mode 100644 index 0000000000..7133a9edb7 --- /dev/null +++ b/CorebootModulePkg/SecCore/Ia32/SecEntry.S @@ -0,0 +1,74 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2013, 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: +# +# SecEntry.S +# +# Abstract: +# +# This is the code that begins in protected mode. +# It will transfer the control to pei core. +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(SecStartup) + +# Pcds +ASM_GLOBAL ASM_PFX(PcdGet32 (PcdPayloadFdMemBase)) + +# +# SecCore Entry Point +# +# Processor is in flat protected mode +# +# @param[in] EAX Initial value of the EAX register (BIST: Built-in Self Test) +# @param[in] DI 'BP': boot-strap processor, or 'AP': application processor +# @param[in] EBP Pointer to the start of the Boot Firmware Volume +# +# @return None This routine does not return +# +ASM_GLOBAL ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + # + # Disable all the interrupts + # + cli + + # + # Construct the temporary memory at 0x80000, length 0x10000 + # + movl ($BASE_512KB + $SIZE_64KB), %esp + + # + # Pass BFV into the PEI Core + # + pushl ASM_PFX(PcdGet32 (PcdPayloadFdMemBase)) + + # + # Pass stack base into the PEI Core + # + pushl $BASE_512KB + + # + # Pass stack size into the PEI Core + # + pushl $SIZE_64KB + + # + # Pass Control into the PEI Core + # + call SecStartup + + # + # Never return to here + # + jmp . diff --git a/CorebootModulePkg/SecCore/Ia32/SecEntry.asm b/CorebootModulePkg/SecCore/Ia32/SecEntry.asm new file mode 100644 index 0000000000..e3c2eac852 --- /dev/null +++ b/CorebootModulePkg/SecCore/Ia32/SecEntry.asm @@ -0,0 +1,78 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2013, 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: +; +; SecEntry.asm +; +; Abstract: +; +; This is the code that begins in protected mode. +; It will transfer the control to pei core. +; +;------------------------------------------------------------------------------ +#include + +.686p +.xmm +.model small, c + +EXTRN SecStartup:NEAR + +; Pcds +EXTRN PcdGet32 (PcdPayloadFdMemBase):DWORD + + .code + +; +; SecCore Entry Point +; +; Processor is in flat protected mode +; +; @param[in] EAX Initial value of the EAX register (BIST: Built-in Self Test) +; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor +; @param[in] EBP Pointer to the start of the Boot Firmware Volume +; +; @return None This routine does not return +; + +_ModuleEntryPoint PROC PUBLIC + ; + ; Disable all the interrupts + ; + cli + ; + ; Construct the temporary memory at 0x80000, length 0x10000 + ; + mov esp, (BASE_512KB + SIZE_64KB) + + ; + ; Pass BFV into the PEI Core + ; + push PcdGet32 (PcdPayloadFdMemBase) + + ; + ; Pass stack base into the PEI Core + ; + push BASE_512KB + + ; + ; Pass stack size into the PEI Core + ; + push SIZE_64KB + + ; + ; Pass Control into the PEI Core + ; + call SecStartup +_ModuleEntryPoint ENDP + +END diff --git a/CorebootModulePkg/SecCore/Ia32/Stack.S b/CorebootModulePkg/SecCore/Ia32/Stack.S new file mode 100644 index 0000000000..cd492404a0 --- /dev/null +++ b/CorebootModulePkg/SecCore/Ia32/Stack.S @@ -0,0 +1,78 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2013, 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. +# +# Abstract: +# +# Switch the stack from temporary memory to permenent memory. +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# SecSwitchStack ( +# UINT32 TemporaryMemoryBase, +# UINT32 PermenentMemoryBase +# )# +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX (SecSwitchStack) +ASM_PFX(SecSwitchStack): + # + # Save standard registers so they can be used to change stack + # + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + + # + # !!CAUTION!! this function address's is pushed into stack after + # migration of whole temporary memory, so need save it to permenent + # memory at first! + # + movl 20(%esp), %ebx # Save the first parameter + movl 24(%esp), %ecx # Save the second parameter + + # + # Save this function's return address into permenent memory at first. + # Then, Fixup the esp point to permenent memory + # + movl %esp, %eax + subl %ebx, %eax + addl %ecx, %eax + movl 0(%esp), %edx # copy pushed register's value to permenent memory + movl %edx, 0(%eax) + movl 4(%esp), %edx + movl %edx, 4(%eax) + movl 8(%esp), %edx + movl %edx, 8(%eax) + movl 12(%esp), %edx + movl %edx, 12(%eax) + movl 16(%esp), %edx # Update this function's return address into permenent memory + movl %edx, 16(%eax) + movl %eax, %esp # From now, esp is pointed to permenent memory + + # + # Fixup the ebp point to permenent memory + # + movl %ebp, %eax + subl %ebx, %eax + addl %ecx, %eax + movl %eax, %ebp # From now, ebp is pointed to permenent memory + + popl %edx + popl %ecx + popl %ebx + popl %eax + ret + + diff --git a/CorebootModulePkg/SecCore/Ia32/Stack.asm b/CorebootModulePkg/SecCore/Ia32/Stack.asm new file mode 100644 index 0000000000..9d1ed153e1 --- /dev/null +++ b/CorebootModulePkg/SecCore/Ia32/Stack.asm @@ -0,0 +1,82 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2013, 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. +; +; Abstract: +; +; Switch the stack from temporary memory to permenent memory. +; +;------------------------------------------------------------------------------ + + .586p + .model flat,C + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; SecSwitchStack ( +; UINT32 TemporaryMemoryBase, +; UINT32 PermenentMemoryBase +; ); +;------------------------------------------------------------------------------ +SecSwitchStack PROC + ; + ; Save three register: eax, ebx, ecx + ; + push eax + push ebx + push ecx + push edx + + ; + ; !!CAUTION!! this function address's is pushed into stack after + ; migration of whole temporary memory, so need save it to permenent + ; memory at first! + ; + + mov ebx, [esp + 20] ; Save the first parameter + mov ecx, [esp + 24] ; Save the second parameter + + ; + ; Save this function's return address into permenent memory at first. + ; Then, Fixup the esp point to permenent memory + ; + mov eax, esp + sub eax, ebx + add eax, ecx + mov edx, dword ptr [esp] ; copy pushed register's value to permenent memory + mov dword ptr [eax], edx + mov edx, dword ptr [esp + 4] + mov dword ptr [eax + 4], edx + mov edx, dword ptr [esp + 8] + mov dword ptr [eax + 8], edx + mov edx, dword ptr [esp + 12] + mov dword ptr [eax + 12], edx + mov edx, dword ptr [esp + 16] ; Update this function's return address into permenent memory + mov dword ptr [eax + 16], edx + mov esp, eax ; From now, esp is pointed to permenent memory + + ; + ; Fixup the ebp point to permenent memory + ; + mov eax, ebp + sub eax, ebx + add eax, ecx + mov ebp, eax ; From now, ebp is pointed to permenent memory + + pop edx + pop ecx + pop ebx + pop eax + ret +SecSwitchStack ENDP + + END diff --git a/CorebootModulePkg/SecCore/SecCore.inf b/CorebootModulePkg/SecCore/SecCore.inf new file mode 100644 index 0000000000..f8468f4c24 --- /dev/null +++ b/CorebootModulePkg/SecCore/SecCore.inf @@ -0,0 +1,64 @@ +## @file +# This is the first module taking control from the coreboot. +# +# Copyright (c) 2013, 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. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SecCore + FILE_GUID = BA7BE337-6CFB-4dbb-B26C-21EC2FC16073 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + SecMain.c + SecMain.h + FindPeiCore.c + +[Sources.IA32] + Ia32/Stack.asm | MSFT + Ia32/Stack.S | GCC + Ia32/SecEntry.asm | MSFT + Ia32/SecEntry.S | GCC + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + CorebootModulePkg/CorebootModulePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + PcdLib + DebugAgentLib + UefiCpuLib + PeCoffGetEntryPointLib + PeCoffExtraActionLib + +[Ppis] + gEfiSecPlatformInformationPpiGuid # PPI ALWAYS_PRODUCED + gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED + +[Pcd] + gUefiCorebootModulePkgTokenSpaceGuid.PcdPayloadFdMemBase + gUefiCorebootModulePkgTokenSpaceGuid.PcdPayloadFdMemSize + diff --git a/CorebootModulePkg/SecCore/SecMain.c b/CorebootModulePkg/SecCore/SecMain.c new file mode 100644 index 0000000000..7ce0463d98 --- /dev/null +++ b/CorebootModulePkg/SecCore/SecMain.c @@ -0,0 +1,291 @@ +/** @file + C funtions in SEC + +Copyright (c) 2013, 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. + +**/ + + +#include "SecMain.h" + +EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = { + SecTemporaryRamSupport +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTemporaryRamSupportPpiGuid, + &gSecTemporaryRamSupportPpi + } +}; + +// +// These are IDT entries pointing to 10:FFFFFFE4h. +// +UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL; + +/** + Caller provided function to be invoked at the end of InitializeDebugAgent(). + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param[in] Context The first input parameter of InitializeDebugAgent(). + +**/ +VOID +EFIAPI +SecStartupPhase2( + IN VOID *Context + ); + + +/** + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + + @param SizeOfRam Size of the temporary memory available for use. + @param TempRamBase Base address of tempory ram + @param BootFirmwareVolume Base address of the Boot Firmware Volume. +**/ +VOID +EFIAPI +SecStartup ( + IN UINT32 SizeOfRam, + IN UINT32 TempRamBase, + IN VOID *BootFirmwareVolume + ) +{ + EFI_SEC_PEI_HAND_OFF SecCoreData; + IA32_DESCRIPTOR IdtDescriptor; + SEC_IDT_TABLE IdtTableInStack; + UINT32 Index; + UINT32 PeiStackSize; + + PeiStackSize = (SizeOfRam >> 1); + + ASSERT (PeiStackSize < SizeOfRam); + + // + // Process all libraries constructor function linked to SecCore. + // + ProcessLibraryConstructorList (); + + // + // Initialize floating point operating environment + // to be compliant with UEFI spec. + // + InitializeFloatingPointUnits (); + + + // |-------------------|----> + // |Idt Table | + // |-------------------| + // |PeiService Pointer | PeiStackSize + // |-------------------| + // | | + // | Stack | + // |-------------------|----> + // | | + // | | + // | Heap | PeiTemporayRamSize + // | | + // | | + // |-------------------|----> TempRamBase + + IdtTableInStack.PeiService = 0; + for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { + CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64)); + } + + IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable; + IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); + + AsmWriteIdtr (&IdtDescriptor); + + // + // Update the base address and length of Pei temporary memory + // + SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF); + SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume; + SecCoreData.BootFirmwareVolumeSize = (UINTN)(0x100000000ULL - (UINTN) BootFirmwareVolume); + SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase; + SecCoreData.TemporaryRamSize = SizeOfRam; + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize; + SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize); + SecCoreData.StackSize = PeiStackSize; + + // + // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready. + // + InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2); + +} + +/** + Caller provided function to be invoked at the end of InitializeDebugAgent(). + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param[in] Context The first input parameter of InitializeDebugAgent(). + +**/ +VOID +EFIAPI +SecStartupPhase2( + IN VOID *Context + ) +{ + EFI_SEC_PEI_HAND_OFF *SecCoreData; + EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; + + SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context; + // + // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug + // is enabled. + // + FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint); + if (PeiCoreEntryPoint == NULL) + { + CpuDeadLoop (); + } + + // + // Transfer the control to the PEI core + // + ASSERT (PeiCoreEntryPoint != NULL); + (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPeiSecPlatformInformationPpi); + + // + // Should not come here. + // + return ; +} + +/** + This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into + permanent memory. + + @param PeiServices Pointer to the PEI Services Table. + @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the + Temporary RAM contents. + @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the + Temporary RAM contents. + @param CopySize Amount of memory to migrate from temporary to permanent memory. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when + TemporaryMemoryBase > PermanentMemoryBase. + +**/ +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ) +{ + IA32_DESCRIPTOR IdtDescriptor; + VOID* OldHeap; + VOID* NewHeap; + VOID* OldStack; + VOID* NewStack; + DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext; + BOOLEAN OldStatus; + UINTN PeiStackSize; + + PeiStackSize = (CopySize >> 1); + + ASSERT (PeiStackSize < CopySize); + + // + // |-------------------|----> + // | Stack | PeiStackSize + // |-------------------|----> + // | Heap | PeiTemporayRamSize + // |-------------------|----> TempRamBase + // + // |-------------------|----> + // | Heap | PeiTemporayRamSize + // |-------------------|----> + // | Stack | PeiStackSize + // |-------------------|----> PermanentMemoryBase + // + + OldHeap = (VOID*)(UINTN)TemporaryMemoryBase; + NewHeap = (VOID*)((UINTN)PermanentMemoryBase + PeiStackSize); + + OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize - PeiStackSize); + NewStack = (VOID*)(UINTN)PermanentMemoryBase; + + DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap; + DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack; + + OldStatus = SaveAndSetDebugTimerInterrupt (FALSE); + // + // Initialize Debug Agent to support source level debug in PEI phase after memory ready. + // It will build HOB and fix up the pointer in IDT table. + // + InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL); + + // + // Migrate Heap + // + CopyMem (NewHeap, OldHeap, CopySize - PeiStackSize); + + // + // Migrate Stack + // + CopyMem (NewStack, OldStack, PeiStackSize); + + + // + // We need *not* fix the return address because currently, + // The PeiCore is executed in flash. + // + + // + // Rebase IDT table in permanent memory + // + AsmReadIdtr (&IdtDescriptor); + IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack; + + AsmWriteIdtr (&IdtDescriptor); + + + // + // Program MTRR + // + + // + // SecSwitchStack function must be invoked after the memory migration + // immediatly, also we need fixup the stack change caused by new call into + // permenent memory. + // + SecSwitchStack ( + (UINT32) (UINTN) OldStack, + (UINT32) (UINTN) NewStack + ); + + SaveAndSetDebugTimerInterrupt (OldStatus); + + return EFI_SUCCESS; +} + diff --git a/CorebootModulePkg/SecCore/SecMain.h b/CorebootModulePkg/SecCore/SecMain.h new file mode 100644 index 0000000000..7bc991ab5f --- /dev/null +++ b/CorebootModulePkg/SecCore/SecMain.h @@ -0,0 +1,134 @@ +/** @file + Master header file for SecCore. + +Copyright (c) 2013, 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. + +**/ + +#ifndef _SEC_CORE_H_ +#define _SEC_CORE_H_ + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SEC_IDT_ENTRY_COUNT 34 + +typedef struct _SEC_IDT_TABLE { + // + // Reserved 8 bytes preceding IDT to store EFI_PEI_SERVICES**, since IDT base + // address should be 8-byte alignment. + // Note: For IA32, only the 4 bytes immediately preceding IDT is used to store + // EFI_PEI_SERVICES** + // + UINT64 PeiService; + UINT64 IdtTable[SEC_IDT_ENTRY_COUNT]; +} SEC_IDT_TABLE; + +/** + Switch the stack in the temporary memory to the one in the permanent memory. + + This function must be invoked after the memory migration immediately. The relative + position of the stack in the temporary and permanent memory is same. + + @param TemporaryMemoryBase Base address of the temporary memory. + @param PermenentMemoryBase Base address of the permanent memory. +**/ +VOID +EFIAPI +SecSwitchStack ( + UINT32 TemporaryMemoryBase, + UINT32 PermenentMemoryBase + ); + +/** + This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into + permanent memory. + + @param PeiServices Pointer to the PEI Services Table. + @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the + Temporary RAM contents. + @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the + Temporary RAM contents. + @param CopySize Amount of memory to migrate from temporary to permanent memory. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when + TemporaryMemoryBase > PermanentMemoryBase. + +**/ +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ); + +/** + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param SizeOfRam Size of the temporary memory available for use. + @param TempRamBase Base address of tempory ram + @param BootFirmwareVolume Base address of the Boot Firmware Volume. +**/ +VOID +EFIAPI +SecStartup ( + IN UINT32 SizeOfRam, + IN UINT32 TempRamBase, + IN VOID *BootFirmwareVolume + ); + +/** + Find and return Pei Core entry point. + + It also find SEC and PEI Core file debug inforamtion. It will report them if + remote debug is enabled. + + @param BootFirmwareVolumePtr Point to the boot firmware volume. + @param PeiCoreEntryPoint Point to the PEI core entry point. + +**/ +VOID +EFIAPI +FindAndReportEntryPoints ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint + ); + +/** + Autogenerated function that calls the library constructors for all of the module's + dependent libraries. This function must be called by the SEC Core once a stack has + been established. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + VOID + ); + +#endif