diff options
author | jljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-01-04 16:17:59 +0000 |
---|---|---|
committer | jljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-01-04 16:17:59 +0000 |
commit | c1c2669c6bb3ed4e23c06a93e60450a4fc3eccf2 (patch) | |
tree | 844feddcd621f20d1d6e27eb3efc0bc437367112 /OvmfPkg/Sec | |
parent | 8cf01cae78c1e7b823587aac1b672a8c5adccaa9 (diff) | |
download | edk2-c1c2669c6bb3ed4e23c06a93e60450a4fc3eccf2.tar.gz |
OVMF: Update OVMF FD/FV build to minimize ROM size
* Only SEC is uncompressed now
* The MAIN FV with PEI & DXE can easily shrink and grow as needed
* The final output will now be OVMF.Fv rather than OVMF.fd
* The final output size will be a multiple of 64kb
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9672 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'OvmfPkg/Sec')
-rw-r--r-- | OvmfPkg/Sec/FindPeiCore.c | 373 | ||||
-rw-r--r-- | OvmfPkg/Sec/SecMain.c | 25 | ||||
-rw-r--r-- | OvmfPkg/Sec/SecMain.h | 4 | ||||
-rw-r--r-- | OvmfPkg/Sec/SecMain.inf | 6 |
4 files changed, 348 insertions, 60 deletions
diff --git a/OvmfPkg/Sec/FindPeiCore.c b/OvmfPkg/Sec/FindPeiCore.c index 7d13ebb4bc..01cd70f5ba 100644 --- a/OvmfPkg/Sec/FindPeiCore.c +++ b/OvmfPkg/Sec/FindPeiCore.c @@ -1,7 +1,7 @@ /** @file Locate the entry point for the PEI Core - Copyright (c) 2008 - 2009, Intel Corporation + Copyright (c) 2008 - 2010, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -15,16 +15,151 @@ #include <PiPei.h> #include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/ExtractGuidedSectionLib.h> +#include <Library/PcdLib.h> #include <Library/PeCoffGetEntryPointLib.h> #include "SecMain.h" -VOID +/** + Locates the main boot firmware volume. + + @param[in,out] BootFv On input, the base of the BootFv + On output, the decompressed main firmware volume + + @retval EFI_SUCCESS The main firmware volume was located and decompressed + @retval EFI_NOT_FOUND The main firmware volume was not found + +**/ +EFI_STATUS +FindMainFv ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *Fv; + UINTN Distance; + BOOLEAN Found; + + ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0); + + Found = FALSE; + Fv = *BootFv; + Distance = (UINTN) (*BootFv)->FvLength; + do { + Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE); + Distance += EFI_PAGE_SIZE; + if (Distance > SIZE_32MB) { + return EFI_NOT_FOUND; + } + + if (Fv->Signature != EFI_FVH_SIGNATURE) { + continue; + } + + if ((UINTN) Fv->FvLength > Distance) { + continue; + } + + *BootFv = Fv; + return EFI_SUCCESS; + + } while (TRUE); +} + + +/** + Locates a section within a series of sections + with the specified section type. + + @param[in] Sections The sections to search + @param[in] SizeOfSections Total size of all sections + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindFfsSectionInSections ( + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfSections; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + // + // Loop through the FFS file sections within the PEI Core FFS file + // + EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections; + EndOfSections = EndOfSection + SizeOfSections; + for (;;) { + if (EndOfSection == EndOfSections) { + break; + } + CurrentAddress = (EndOfSection + 3) & ~(3ULL); + if (CurrentAddress >= EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + DEBUG ((EFI_D_INFO, "Section->Type: 0x%x\n", Section->Type)); + + Size = SECTION_SIZE (Section); + if (Size < sizeof (*Section)) { + return EFI_VOLUME_CORRUPTED; + } + + EndOfSection = CurrentAddress + Size; + if (EndOfSection > EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the requested section type + // + if (Section->Type == SectionType) { + *FoundSection = Section; + return EFI_SUCCESS; + } + DEBUG ((EFI_D_INFO, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType)); + } + + return EFI_NOT_FOUND; +} + + +/** + Locates a FFS file with the specified file type and a section + within that file with the specified section type. + + @param[in] Fv The firmware volume to search + @param[in] FileType The file type to locate + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS EFIAPI -FindPeiCoreEntryPoint ( - IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, - OUT VOID **PeiCoreEntryPoint +FindFfsFileAndSection ( + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + IN EFI_FV_FILETYPE FileType, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection ) { EFI_STATUS Status; @@ -33,71 +168,219 @@ FindPeiCoreEntryPoint ( EFI_FFS_FILE_HEADER *File; UINT32 Size; EFI_PHYSICAL_ADDRESS EndOfFile; - EFI_COMMON_SECTION_HEADER *Section; - EFI_PHYSICAL_ADDRESS EndOfSection; - *PeiCoreEntryPoint = NULL; + if (Fv->Signature != EFI_FVH_SIGNATURE) { + DEBUG ((EFI_D_INFO, "FV at %p does not have FV header signature\n", Fv)); + return EFI_VOLUME_CORRUPTED; + } - CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr; - EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength; + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv; + EndOfFirmwareVolume = CurrentAddress + Fv->FvLength; // // Loop through the FFS files in the Boot Firmware Volume // - for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) { + for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) { - CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL; + CurrentAddress = (EndOfFile + 7) & ~(7ULL); if (CurrentAddress > EndOfFirmwareVolume) { - return; + return EFI_VOLUME_CORRUPTED; } File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; Size = *(UINT32*) File->Size & 0xffffff; - if (Size < (sizeof (*File) + sizeof (*Section))) { - return; + if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) { + return EFI_VOLUME_CORRUPTED; } + DEBUG ((EFI_D_INFO, "File->Type: 0x%x\n", File->Type)); EndOfFile = CurrentAddress + Size; if (EndOfFile > EndOfFirmwareVolume) { - return; + return EFI_VOLUME_CORRUPTED; } // - // Look for PEI Core files + // Look for the request file type // - if (File->Type != EFI_FV_FILETYPE_PEI_CORE) { + if (File->Type != FileType) { + DEBUG ((EFI_D_INFO, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType)); continue; } - // - // Loop through the FFS file sections within the PEI Core FFS file - // - EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1); - for (;;) { - CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL; - Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; - - Size = *(UINT32*) Section->Size & 0xffffff; - if (Size < sizeof (*Section)) { - return; - } - - EndOfSection = CurrentAddress + Size; - if (EndOfSection > EndOfFile) { - return; - } - - // - // Look for executable sections - // - if (Section->Type == EFI_SECTION_PE32) { - Status = PeCoffLoaderGetEntryPoint ((VOID*) (Section + 1), PeiCoreEntryPoint); - if (!EFI_ERROR (Status)) { - return; - } - } + Status = FindFfsSectionInSections ( + (VOID*) (File + 1), + (UINTN) EndOfFile - (UINTN) (File + 1), + SectionType, + FoundSection + ); + if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) { + return Status; } + } + + return EFI_NOT_FOUND; +} + + +/** + Locates the compressed main firmware volume and decompresses it. + + @param[in,out] Fv On input, the firmware volume to search + On output, the decompressed main FV + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +EFIAPI +DecompressGuidedFv ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv + ) +{ + EFI_STATUS Status; + EFI_GUID_DEFINED_SECTION *Section; + UINT32 OutputBufferSize; + UINT32 ScratchBufferSize; + UINT16 SectionAttribute; + UINT32 AuthenticationStatus; + VOID *OutputBuffer; + VOID *ScratchBuffer; + EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection; + EFI_FIRMWARE_VOLUME_HEADER *NewFv; + NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL; + + Status = FindFfsFileAndSection ( + *Fv, + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + EFI_SECTION_GUID_DEFINED, + (EFI_COMMON_SECTION_HEADER**) &Section + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n")); + return Status; + } + + Status = ExtractGuidedSectionGetInfo ( + Section, + &OutputBufferSize, + &ScratchBufferSize, + &SectionAttribute + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n")); + return Status; + } + + //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize) + OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB); + ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB); + Status = ExtractGuidedSectionDecode ( + Section, + &OutputBuffer, + ScratchBuffer, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n")); + return Status; + } + + Status = FindFfsSectionInSections ( + OutputBuffer, + OutputBufferSize, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + (EFI_COMMON_SECTION_HEADER**) &NewFvSection + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n")); + return Status; } + + NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase); + CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize)); + + if (NewFv->Signature != EFI_FVH_SIGNATURE) { + DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv)); + CpuDeadLoop (); + return EFI_VOLUME_CORRUPTED; + } + + *Fv = NewFv; + return EFI_SUCCESS; +} + + +/** + Locates the PEI Core entry point address + + @param[in] Fv The firmware volume to search + @param[out] PeiCoreEntryPoint The entry point of the PEI Core image + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +EFIAPI +FindPeiCoreEntryPointInFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + OUT VOID **PeiCoreEntryPoint + ) +{ + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; + + Status = FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_PE32, + &Section + ); + if (EFI_ERROR (Status)) { + Status = FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_TE, + &Section + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n")); + return Status; + } + } + + return PeCoffLoaderGetEntryPoint ((VOID*) (Section + 1), PeiCoreEntryPoint); +} + + +/** + Locates the PEI Core entry point address + + @param[in,out] Fv The firmware volume to search + @param[out] PeiCoreEntryPoint The entry point of the PEI Core image + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +VOID +EFIAPI +FindPeiCoreEntryPoint ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv, + OUT VOID **PeiCoreEntryPoint + ) +{ + *PeiCoreEntryPoint = NULL; + + FindMainFv (BootFv); + + DecompressGuidedFv (BootFv); + + FindPeiCoreEntryPointInFv (*BootFv, PeiCoreEntryPoint); } diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index 99d21f3d95..58da92b086 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -17,6 +17,7 @@ #include <Library/BaseLib.h> #include <Library/DebugLib.h> #include <Library/BaseMemoryLib.h> +#include <Library/PeimEntryPoint.h> #include <Library/PeiServicesLib.h> #include <Ppi/TemporaryRamSupport.h> #include <Library/PcdLib.h> @@ -61,7 +62,7 @@ InitializeIdtPtr ( VOID EFIAPI SecCoreStartupWithStack ( - IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, IN VOID *TopOfCurrentStack ) { @@ -72,18 +73,20 @@ SecCoreStartupWithStack ( VOID *IdtPtr; VOID *PeiCoreEntryPoint; + DEBUG ((EFI_D_INFO, + "SecCoreStartupWithStack(0x%x, 0x%x)\n", + (UINT32)(UINTN)BootFv, + (UINT32)(UINTN)TopOfCurrentStack + )); + + ProcessLibraryConstructorList (NULL, NULL); + // // Initialize floating point operating environment // to be compliant with UEFI spec. // InitializeFloatingPointUnits (); - DEBUG ((EFI_D_INFO, - "SecCoreStartupWithStack(0x%x, 0x%x)\n", - (UINT32)(UINTN)BootFirmwareVolumePtr, - (UINT32)(UINTN)TopOfCurrentStack - )); - BottomOfTempRam = (UINT8*)(UINTN) INITIAL_TOP_OF_STACK; SizeOfTempRam = (UINTN) SIZE_64KB; TopOfTempRam = BottomOfTempRam + SizeOfTempRam; @@ -104,9 +107,6 @@ SecCoreStartupWithStack ( SecCoreData = (EFI_SEC_PEI_HAND_OFF*)((UINTN) TopOfTempRam - SIZE_4KB); SecCoreData->DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); - SecCoreData->BootFirmwareVolumeBase = (VOID*)(UINTN) PcdGet32 (PcdOvmfFlashFvRecoveryBase); - SecCoreData->BootFirmwareVolumeSize = PcdGet32 (PcdOvmfFlashFvRecoverySize); - SecCoreData->TemporaryRamBase = (VOID*) BottomOfTempRam; SecCoreData->TemporaryRamSize = SizeOfTempRam; @@ -124,7 +124,10 @@ SecCoreStartupWithStack ( IdtPtr = ALIGN_POINTER(IdtPtr, 16); InitializeIdtPtr (IdtPtr); - FindPeiCoreEntryPoint (BootFirmwareVolumePtr, &PeiCoreEntryPoint); + FindPeiCoreEntryPoint (&BootFv, &PeiCoreEntryPoint); + + SecCoreData->BootFirmwareVolumeBase = BootFv; + SecCoreData->BootFirmwareVolumeSize = BootFv->FvLength; if (PeiCoreEntryPoint != NULL) { DEBUG ((EFI_D_INFO, diff --git a/OvmfPkg/Sec/SecMain.h b/OvmfPkg/Sec/SecMain.h index 4f5eaa8137..1a4ed40bf7 100644 --- a/OvmfPkg/Sec/SecMain.h +++ b/OvmfPkg/Sec/SecMain.h @@ -47,11 +47,11 @@ TemporaryRamMigration ( VOID EFIAPI FindPeiCoreEntryPoint ( - IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr, OUT VOID **PeiCoreEntryPoint ); -#define INITIAL_TOP_OF_STACK BASE_128KB +#define INITIAL_TOP_OF_STACK BASE_512KB #endif // _PLATFORM_SECMAIN_H_ diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf index 7cc1533fdc..08e26d2ac0 100644 --- a/OvmfPkg/Sec/SecMain.inf +++ b/OvmfPkg/Sec/SecMain.inf @@ -50,6 +50,8 @@ [LibraryClasses]
BaseLib
+ BaseMemoryLib
+ ExtractGuidedSectionLib
PcdLib
PeCoffGetEntryPointLib
UefiCpuLib
@@ -58,6 +60,6 @@ gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
[FixedPcd.common]
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashFvRecoveryBase
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashFvRecoverySize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfMemFvBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfMemFvSize
|