diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/CORE_PEI/CORE_PEI_PI | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'Core/CORE_PEI/CORE_PEI_PI')
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/BootMode.c | 107 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/CORE_PEISrcPI.cif | 21 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c | 689 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/FwVol.c | 782 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/Hob.c | 191 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/Image.c | 932 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/MemoryServices.c | 392 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/PeiCore.h | 1416 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/PeiMain.c | 404 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/Ppi.c | 687 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/Reset.c | 76 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/Security.c | 192 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/StatusCode.c | 94 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/dependency.c | 265 | ||||
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/dependency.h | 38 |
15 files changed, 6286 insertions, 0 deletions
diff --git a/Core/CORE_PEI/CORE_PEI_PI/BootMode.c b/Core/CORE_PEI/CORE_PEI_PI/BootMode.c new file mode 100644 index 0000000..2c5845a --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/BootMode.c @@ -0,0 +1,107 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + BootMode.c + +Abstract: + + EFI PEI Core Boot Mode services + + + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + if (BootMode == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + *BootMode = HandOffHob->BootMode; + + + return EFI_SUCCESS; +}; + + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + HandOffHob->BootMode = BootMode; + + return EFI_SUCCESS; +}; diff --git a/Core/CORE_PEI/CORE_PEI_PI/CORE_PEISrcPI.cif b/Core/CORE_PEI/CORE_PEI_PI/CORE_PEISrcPI.cif new file mode 100644 index 0000000..62d8649 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/CORE_PEISrcPI.cif @@ -0,0 +1,21 @@ +<component> + name = "CORE_PEI Source PI (EDK)" + category = ModulePart + LocalRoot = "Core\CORE_PEI\CORE_PEI_PI" + RefName = "CORE_PEISrcPI_EDK" +[files] +"BootMode.c" +"dependency.c" +"dependency.h" +"Dispatcher.c" +"FwVol.c" +"Hob.c" +"Image.c" +"MemoryServices.c" +"PeiCore.h" +"PeiMain.c" +"Ppi.c" +"Reset.c" +"Security.c" +"StatusCode.c" +<endComponent> diff --git a/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c b/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c new file mode 100644 index 0000000..91e8821 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c @@ -0,0 +1,689 @@ +/*++ + +Copyright (c) 2004 - 2009, 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: + + Dispatcher.c + +Abstract: + + EFI PEI Core dispatch services + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) + +//*** AMI PORTING BEGIN ***// +VOID PeiCoreEntry(IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList); +//*** AMI PORTING END *****// +VOID +DiscoverPeimsAndOrderWithApriori ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FV_HANDLE VolumeHandle + ) +/*++ + +Routine Description: + + Discover all Peims and optional Apriori file in one FV. There is at most one + Apriori file in one FV. + +Arguments: + + Private - Pointer to the private data passed in from caller + VolumeHandle - Fv handle. +Returns: + + NONE + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_FV_HANDLE FileHandle; + EFI_PEI_FILE_HANDLE AprioriFileHandle; + EFI_GUID *Apriori; + UINTN Index; + UINTN Index2; + UINTN PeimIndex; + UINTN PeimCount; + EFI_GUID *Guid; + EFI_PEI_FV_HANDLE TempFileHandles[PEI_CORE_MAX_PEIM_PER_FV]; + EFI_GUID FileGuid[PEI_CORE_MAX_PEIM_PER_FV]; + + // + // Walk the FV and find all the PEIMs and the Apriori file. + // + AprioriFileHandle = NULL; + Private->CurrentFvFileHandles[0] = NULL; + Guid = NULL; + FileHandle = NULL; + + // + // If the current Fv has been scanned, directly get its cachable record. + // + if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) { + PeiCoreCopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles)); + return; + } + + // + // Go ahead to scan this Fv, and cache FileHandles within it. + // + for (PeimCount = 0; PeimCount < PEI_CORE_MAX_PEIM_PER_FV; PeimCount++) { + Status = PeiFindFileEx ( + VolumeHandle, + NULL, + PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, + &FileHandle, + &AprioriFileHandle + ); + if (Status != EFI_SUCCESS) { + break; + } + + Private->CurrentFvFileHandles[PeimCount] = FileHandle; + } + + Private->AprioriCount = 0; + if (AprioriFileHandle != NULL) { + // + // Read the Apriori file + // + Status = PeiFfsFindSectionData (&Private->PS, EFI_SECTION_RAW, AprioriFileHandle, &Apriori); + if (!EFI_ERROR (Status)) { + // + // Calculate the number of PEIMs in the A Priori list + // + Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF; + Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER); + Private->AprioriCount /= sizeof (EFI_GUID); + + PeiCoreSetMem (FileGuid, sizeof (FileGuid), 0); + for (Index = 0; Index < PeimCount; Index++) { + // + // Make an array of file name guids that matches the FileHandle array so we can convert + // quickly from file name to file handle + // + PeiCoreCopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID)); + } + + // + // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file. + // Add avalible PEIMs in Apriori file into TempFileHandles array at first. + // + Index2 = 0; + for (Index = 0; Index2 < Private->AprioriCount; Index++) { + while (Index2 < Private->AprioriCount) { + Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]); + if (Guid != NULL) { + break; + } + } + if (Guid == NULL) { + break; + } + PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID); + TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex]; + + // + // Since we have copied the file handle we can remove it from this list. + // + Private->CurrentFvFileHandles[PeimIndex] = NULL; + } + + // + // Update valid Aprioricount + // + Private->AprioriCount = Index; + + // + // Add in any PEIMs not in the Apriori file + // + for (;Index < PeimCount; Index++) { + for (Index2 = 0; Index2 < PeimCount; Index2++) { + if (Private->CurrentFvFileHandles[Index2] != NULL) { + TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2]; + Private->CurrentFvFileHandles[Index2] = NULL; + break; + } + } + } + // + //Index the end of array contains re-range Pei moudle. + // + TempFileHandles[Index] = NULL; + + // + // Private->CurrentFvFileHandles is currently in PEIM in the FV order. + // We need to update it to start with files in the A Priori list and + // then the remaining files in PEIM order. + // + PeiCoreCopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles)); + } + } + // + // Cache the current Fv File Handle. So that we don't have to scan the Fv again. + // Instead, we can retrieve the file handles within this Fv from cachable data. + // + Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE; + PeiCoreCopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles)); + +} + + +VOID +PeiDispatcher ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *Private + ) +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + Private - Pointer to the private data passed in from caller + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +{ + EFI_STATUS Status; + UINT32 Index1; + UINT32 Index2; + EFI_PEI_SERVICES **PeiServices; + VOID *PrivateInMem; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE PeiCoreFileHandle; + EFI_PEI_FILE_HANDLE PeimFileHandle; + UINTN FvCount; + UINTN PeimCount; + UINT32 AuthenticationState; + EFI_PHYSICAL_ADDRESS EntryPoint; + EFI_PEIM_ENTRY_POINT PeimEntryPoint; + VOID* PeiCoreReentryPoint; + UINTN SaveCurrentPeimCount; + UINTN SaveCurrentFvCount; + EFI_PEI_FILE_HANDLE SaveCurrentFileHandle; + + PEI_REPORT_STATUS_CODE_CODE ( + + EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + + ExtendedData.DataHeader.HeaderSize = (UINT16)sizeof (EFI_STATUS_CODE_DATA); + ExtendedData.DataHeader.Size = (UINT16)(sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - ExtendedData.DataHeader.HeaderSize); + + PeiCoreCopyMem ( + &ExtendedData.DataHeader.Type, + &gEfiStatusCodeSpecificDataGuid, + sizeof (EFI_GUID) + ); + ) + + PeiServices = &Private->PS; + PeimEntryPoint = NULL; + PeimFileHandle = NULL; + + if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + // + // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile + // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE. + // + SaveCurrentPeimCount = Private->CurrentPeimCount; + SaveCurrentFvCount = Private->CurrentPeimFvCount; + SaveCurrentFileHandle = Private->CurrentFileHandle; + + for (Index1 = 0;Index1 <= SaveCurrentFvCount; Index1++) { + for (Index2 = 0; (Index2 < PEI_CORE_MAX_PEIM_PER_FV) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) { + if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) { + PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2]; + Status = PeiLoadImage ( + &Private->PS, + PeimFileHandle, + &EntryPoint, + &AuthenticationState + ); + if (Status == EFI_SUCCESS) { + // + // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE + // + Private->Fv[Index1].PeimState[Index2]++; + Private->CurrentFileHandle = PeimFileHandle; + Private->CurrentPeimFvCount = Index1; + Private->CurrentPeimCount = Index2; + + // + // Call the PEIM entry point + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; + + PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0); + PeimEntryPoint(PeimFileHandle, &Private->PS); + PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); + } + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (&Private->PS); + } + } + } + Private->CurrentFileHandle = SaveCurrentFileHandle; + Private->CurrentPeimFvCount = SaveCurrentFvCount; + Private->CurrentPeimCount = SaveCurrentPeimCount; + } + + // + // This is the main dispatch loop. It will search known FVs for PEIMs and + // attempt to dispatch them. If any PEIM gets dispatched through a single + // pass of the dispatcher, it will start over from the Bfv again to see + // if any new PEIMs dependencies got satisfied. With a well ordered + // FV where PEIMs are found in the order their dependencies are also + // satisfied, this dipatcher should run only once. + // + do { + // + // In case that reenter PeiCore happens, the last pass record is still available. + // + if (!Private->PeimDispatcherReenter) { + Private->PeimNeedingDispatch = FALSE; + Private->PeimDispatchOnThisPass = FALSE; + } else { + Private->PeimDispatcherReenter = FALSE; + } + for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) { + Private->CurrentPeimFvCount = FvCount; + VolumeHandle = Private->Fv[FvCount].FvHeader; + + if (Private->CurrentPeimCount == 0) { + // + // When going through each FV, at first, search Apriori file to + // reorder all PEIMs to ensure the PEIMs in Apriori file to get + // dispatch at first. + // + DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle); + } + + // + // Start to dispatch all modules within the current Fv. + // + for (PeimCount = Private->CurrentPeimCount; + (PeimCount < PEI_CORE_MAX_PEIM_PER_FV) && (Private->CurrentFvFileHandles[PeimCount] != NULL); + PeimCount++) { + Private->CurrentPeimCount = PeimCount; + PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount]; + + if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) { + if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) { + Private->PeimNeedingDispatch = TRUE; + } else { + Status = PeiLoadImage ( + PeiServices, + PeimFileHandle, + &EntryPoint, + &AuthenticationState + ); + if ((Status == EFI_SUCCESS)) { + // + // The PEIM has its dependencies satisfied, and its entry point + // has been found, so invoke it. + // + PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0); + + PEI_REPORT_STATUS_CODE_CODE ( + ExtendedData.Handle = PeimFileHandle; + ) + + PEI_REPORT_STATUS_CODE_CODE ( + PeiReportStatusCode ( + PeiServices, + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN, + 0, + NULL, + (EFI_STATUS_CODE_DATA *)(&ExtendedData) + ); + ) + + Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle); + if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) { + // + // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED + // + Private->Fv[FvCount].PeimState[PeimCount]++; + + // + // Call the PEIM entry point + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; + PeimEntryPoint (PeimFileHandle, PeiServices); + Private->PeimDispatchOnThisPass = TRUE; + } + + PEI_REPORT_STATUS_CODE_CODE ( + PeiReportStatusCode ( + PeiServices, + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END, + 0, + NULL, + (EFI_STATUS_CODE_DATA *)(&ExtendedData) + ); + ) + PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); + } + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (PeiServices); + + // + // If permanent memory was discovered and installed by this + // PEIM, shadow PEI Core and switch the stacks to the new memory. + // + if (Private->SwitchStackSignal) { + + // + // Make sure we don't retry the same PEIM that added memory + // + Private->CurrentPeimCount++; + + // + // Indicate that PeiCore reenter + // + Private->PeimDispatcherReenter = TRUE; + // + // Migrate IDT from CAR into real memory, so after stack switches to + // the new memory, the caller can get memory version PeiServiceTable. + // + MigrateIdtTable (PeiServices); + // + // Since we are at dispatch level, only the Core's private data + // is preserved, nobody else should have any data on the stack. + // So we need to copy PEI core instance data to memory. + // + Status = PeiAllocatePool (PeiServices, sizeof (PEI_CORE_INSTANCE), &PrivateInMem); + ASSERT_PEI_ERROR (PeiServices, Status); + PeiCoreCopyMem (PrivateInMem, Private, sizeof (PEI_CORE_INSTANCE)); + + // + // Shadow PEI Core. When permanent memory is avaiable, shadow + // PEI Core and PEIMs to get high performance. + // + PeiCoreFileHandle = NULL; + // + // Find the PEI Core in the BFV + // + Status = PeiFindFileEx ( + (EFI_PEI_FV_HANDLE)Private->Fv[0].FvHeader, + NULL, + EFI_FV_FILETYPE_PEI_CORE, + &PeiCoreFileHandle, + NULL + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + // + // Shadow PEI Core into memory so it will run faster + // + Status = PeiLoadImage (PeiServices, PeiCoreFileHandle, &EntryPoint, &AuthenticationState); + ASSERT_PEI_ERROR (PeiServices, Status); + + // + // The 2nd time around we need to call PeiCore passing in a non + // NULL value to OldCoreData. We can not call the PE COFF entry + // point (_EntryPoint) as it had codes a NULL into OldCoreData. + // We calculate the memory (shadowed) address of PeiCore by + // figuring out the offset from _EntryPoint to PeiCore and then + // adding that value to the new memory based entry point. + // + PeiCoreReentryPoint = (VOID*)(UINTN)(EntryPoint + +//*** AMI PORTING BEGIN ***// +// (((UINT8 *)(UINTN)PeiCore) - (UINT8 *)(UINTN)PeiMain)); + (((UINT8 *)(UINTN)PeiCore) - (UINT8 *)(UINTN)PeiCoreEntry)); +//*** AMI PORTING END ***// + + + // + // Switch to memory based stack and reenter PEI Core that has been + // shadowed to memory. + // + SwitchCoreStacks ( + PeiCoreReentryPoint, + (UINTN)SecCoreData, + (UINTN)NULL, + (UINTN)PrivateInMem, + (VOID*)((UINTN)Private->StackBase + (UINTN)Private->StackSize - 0x10) + ); + } + + if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \ + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + // + // If memory is availble we shadow images by default for performance reasons. + // We call the entry point a 2nd time so the module knows it's shadowed. + // + PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0); + PeimEntryPoint (PeimFileHandle, PeiServices); + PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); + + // + // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE + // + Private->Fv[FvCount].PeimState[PeimCount]++; + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (PeiServices); + } + } + } + } + + // + // We set to NULL here to optimize the 2nd entry to this routine after + // memory is found. This reprevents rescanning of the FV. We set to + // NULL here so we start at the begining of the next FV + // + Private->CurrentFileHandle = NULL; + Private->CurrentPeimCount = 0; + // + // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL + // + PeiCoreSetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0); + } + + // + // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go + // through all the FV. + // + Private->CurrentPeimFvCount = 0; + + // + // PeimNeedingDispatch being TRUE means we found a PEIM that did not get + // dispatched. So we need to make another pass + // + // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this + // pass. If we did not dispatch a PEIM there is no point in trying again + // as it will fail the next time too (nothing has changed). + // + } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass); + +//*** AMI PORTING BEGIN ***// + // Print out a list of the PEIMs that were not dispatched + PEI_DEBUG_CODE + ( + { + UINTN i = 0; + UINTN j = 0; + + for(i = 0; i < PEI_CORE_MAX_FV_SUPPORTED; i++) + { + for(j = 0; j < PEI_CORE_MAX_PEIM_PER_FV; j++) + { + if( Private->Fv[i].FvFileHandles[j] == NULL) continue; + + if(Private->Fv[i].PeimState[j] == PEIM_STATE_NOT_DISPATCHED) + PEI_DEBUG((&Private->PS, -1, "WARNING -> PEIM Not Dispatched: %g\n", &((EFI_FFS_FILE_HEADER*)(Private->Fv[i].FvFileHandles[j]))->Name )); + } + } + } + ) +//*** AMI PORTING END *****// +} + + +VOID +InitializeDispatcherData ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + SecCoreData - Information and services provided by SEC phase. + +Returns: + + None. + +--*/ +{ + if (OldCoreData == NULL) { + PeiInitializeFv (PrivateData, SecCoreData); + } + + return; +} + + +BOOLEAN +DepexSatisfied ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + + Private - Pointer to the private data passed in from caller. + FileHandle - File handle of PEIM. + PeimCount - The PEIM sequence in one FV. + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +{ + EFI_STATUS Status; + INT8 *DepexData; + + if (PeimCount < Private->AprioriCount) { + // + // If its in the A priori file then we set Depex to TRUE + // + return TRUE; + } + + Status = PeiFfsFindSectionData (&Private->PS, EFI_SECTION_PEI_DEPEX, FileHandle, &DepexData); + if (EFI_ERROR (Status)) { + // + // If there is no DEPEX, assume the module can be executed + // + return TRUE; + } + + // + // Evaluate a given DEPEX + // + return PeimDispatchReadiness (&Private->PS, DepexData); +} + + +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + This routine enable a PEIM to register itself to shadow when PEI Foundation + discovery permanent memory. + +Arguments: + FileHandle - File handle of a PEIM. + +Returns: + EFI_NOT_FOUND - The file handle doesn't point to PEIM itself. + EFI_ALREADY_STARTED - Indicate that the PEIM has been registered itself. + EFI_SUCCESS - Successfully to register itself. + +--*/ +{ + PEI_CORE_INSTANCE *Private; + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + + if (Private->CurrentFileHandle != FileHandle) { + // + // The FileHandle must be for the current PEIM + // + return EFI_NOT_FOUND; + } + + if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) { + // + // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started + // + return EFI_ALREADY_STARTED; + } + + Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW; + + return EFI_SUCCESS; +} + + + diff --git a/Core/CORE_PEI/CORE_PEI_PI/FwVol.c b/Core/CORE_PEI/CORE_PEI_PI/FwVol.c new file mode 100644 index 0000000..2ecf88e --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/FwVol.c @@ -0,0 +1,782 @@ +/*++ + +Copyright (c) 2004 - 2009, 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: + + FwVol.c + +Abstract: + + Pei Core Firmware File System service routines. + +--*/ + +#include "Tiano.h" +#include "EfiImageFormat.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ + (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)) + + +EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiFirmwareVolumeInfoPpiGuid, + FirmwareVolmeInfoPpiNotifyCallback +}; + + + + +STATIC +EFI_FFS_FILE_STATE +GetFileState( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Returns the highest bit set of the State field + +Arguments: + + ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY + in the Attributes field. + FfsHeader - Pointer to FFS File Header. + +Returns: + Returns the highest bit in the State field + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} + +STATIC +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +/*++ + +Routine Description: + + Calculates the checksum of the header of a file. + +Arguments: + + FileHeader - Pointer to FFS File Header. + +Returns: + Checksum of the header. + + The header is zero byte checksum. + - Zero means the header is good. + - Non-zero means the header is bad. + + +Bugbug: For PEI performance reason, we comments this code at this time. +--*/ +{ + UINT8 *ptr; + UINTN Index; + UINT8 Sum; + + Sum = 0; + ptr = (UINT8 *)FileHeader; + + for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) { + Sum = (UINT8)(Sum + ptr[Index]); + Sum = (UINT8)(Sum + ptr[Index+1]); + Sum = (UINT8)(Sum + ptr[Index+2]); + Sum = (UINT8)(Sum + ptr[Index+3]); + } + + for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) { + Sum = (UINT8)(Sum + ptr[Index]); + } + + // + // State field (since this indicates the different state of file). + // + Sum = (UINT8)(Sum - FileHeader->State); + // + // Checksum field of the file is not part of the header checksum. + // + Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File); + + return Sum; +} + +STATIC +BOOLEAN +EFIAPI +PeiFileHandleToVolume ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + UINTN Index; + PEI_CORE_INSTANCE *PrivateData; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + for (Index = 0; Index < PrivateData->FvCount; Index++) { + FwVolHeader = PrivateData->Fv[Index].FvHeader; + if (((UINTN)FileHandle > (UINTN)FwVolHeader ) && \ + ((UINTN)FileHandle < ((UINTN)FwVolHeader + (UINTN)FwVolHeader->FvLength))) { + *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader; + return TRUE; + } + } + return FALSE; +} + + +EFI_STATUS +PeiFindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName, OPTIONAL + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle, + IN OUT EFI_PEI_FILE_HANDLE *AprioriFile OPTIONAL + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + Flag - Indicator for if this is for PEI Dispath search + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FFS_FILE_HEADER **FileHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle; + FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle; + + FvLength = FwVolHeader->FvLength; + if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // If FileHeader is not specified (NULL) or FileName is not NULL, + // start with the first file in the firmware volume. Otherwise, + // start from the FileHeader. + // + if ((*FileHeader == NULL) || (FileName != NULL)) { + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength); + if (FwVolHeader->ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize); + } + } else { + // + // Length is 24 bits wide so mask upper 8 bits + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize); + } + + FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader); + PEI_ASSERT (PeiServices,(FileOffset <= 0xFFFFFFFF)); + + while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, FfsFileHeader); + switch (FileState) { + + case EFI_FILE_HEADER_INVALID: + FileOffset += sizeof(EFI_FFS_FILE_HEADER); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER)); + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) != 0) { +//*** AMI PORTING BEGIN ***// +// Skip the assert to support a more sophisiticated +// FV corruption handling outside of the Core. +// PEI_ASSERT (PeiServices,FALSE); +//*** AMI PORTING END *****// + return EFI_NOT_FOUND; + } + + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8); + + if (FileName != NULL) { + if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) { + if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { + + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } else if (AprioriFile != NULL) { + if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) { + if (CompareGuid (&FfsFileHeader->Name, &gEfiPeiAprioriGuid)) { + *AprioriFile = FfsFileHeader; + } + } + } + } else if ((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + case EFI_FILE_DELETED: + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + default: + return EFI_NOT_FOUND; + + } + } + + return EFI_NOT_FOUND; +} + + +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize PeiCore Fv List. + +Arguments: + PrivateData - Pointer to PEI_CORE_INSTANCE. + SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. + +Returns: + NONE + +--*/ +{ + EFI_STATUS Status; + // + // The BFV must be the first entry. The Core FV support is stateless + // The AllFV list has a single entry per FV in PEI. + // The Fv list only includes FV that PEIMs will be dispatched from and + // its File System Format is PI 1.0 definition. + // + PrivateData->FvCount = 1; + PrivateData->Fv[0].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; + + PrivateData->AllFvCount = 1; + PrivateData->AllFv[0] = (EFI_PEI_FV_HANDLE)PrivateData->Fv[0].FvHeader; + + + // + // Post a call-back for the FvInfoPPI services to expose + // additional Fvs to PeiCore. + // + Status = (PrivateData->PS)->NotifyPpi (&PrivateData->PS, &mNotifyList); + ASSERT_PEI_ERROR (&PrivateData->PS, Status); + +} + + + +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Process Firmware Volum Information once FvInfoPPI install. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the interface could be successfully + installed + +--*/ +{ + UINT8 FvCount; + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv; + PEI_CORE_INSTANCE *PrivateData; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (PrivateData->FvCount >= PEI_CORE_MAX_FV_SUPPORTED) { + PEI_ASSERT (GetPeiServicesTablePointer(),FALSE); + } + + Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi; + + if (CompareGuid (&Fv->FvFormat, &gEfiFirmwareFileSystem2Guid)) { + for (FvCount = 0; FvCount < PrivateData->FvCount; FvCount ++) { + if ((UINTN)PrivateData->Fv[FvCount].FvHeader == (UINTN)Fv->FvInfo) { + return EFI_SUCCESS; + } + } + PrivateData->Fv[PrivateData->FvCount++].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv->FvInfo; + } + + // + // Allways add to the All list + // + PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +/*++ + +Routine Description: + + Search the next FV Volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + Instance - The Fv Volume Instance. + VolumeHandle - Pointer to the current Fv Volume to search. + +Returns: + EFI_INVALID_PARAMETER - VolumeHandle is NULL. + EFI_NOT_FOUND - No FV Volume is found. + EFI_SUCCESS - The next FV Volume is found. + +--*/ + +{ + PEI_CORE_INSTANCE *Private; + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + if (VolumeHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Instance >= Private->AllFvCount) { + VolumeHandle = NULL; + return EFI_NOT_FOUND; + } + + *VolumeHandle = Private->AllFv[Instance]; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input FvHandle, search for the next matching type file in the FV Volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only file of this type. + FvHandle - Pointer to the current FV to search. + FileHandle - Pointer to the file matching SearchType in FwVolHeader. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +{ + return PeiFindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL); +} + +EFI_STATUS +PeiFfsProcessSection ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_COMMON_SECTION_HEADER *Section, + IN UINTN SectionSize, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *Authentication + ) +/*++ + +Routine Description: + + Go through the file to search SectionType section, + when meeting an encapsuled section, search recursively. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only section of this type. + Section - From where to search. + SectionSize - The file size to search. + OutputBuffer - Pointer to the section to search. + OutputSize - The size of the section to search. + Authentication - Authenticate the section. + +Returns: + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + UINT32 SectionLength; + UINT32 ParsedLength; + EFI_GUID_DEFINED_SECTION *GuidSection; + EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi; + EFI_COMPRESSION_SECTION *CompressionSection; + EFI_PEI_DECOMPRESS_PPI *DecompressPpi; + VOID *PpiOutput; + UINTN PpiOutputSize; + + *OutputBuffer = NULL; + ParsedLength = 0; + while (ParsedLength < SectionSize) { + if (Section->Type == SectionType) { + *OutputBuffer = (VOID *)(Section + 1); + return EFI_SUCCESS; + } else if (Section->Type == EFI_SECTION_GUID_DEFINED) { + GuidSection = (EFI_GUID_DEFINED_SECTION *)Section; + GuidSectionPpi = PeiReturnPpi (PeiServices, &GuidSection->SectionDefinitionGuid); + if (GuidSectionPpi != NULL) { + Status = GuidSectionPpi->ExtractSection ( + GuidSectionPpi, + Section, + &PpiOutput, + &PpiOutputSize, + Authentication + ); + if (!EFI_ERROR (Status)) { + return PeiFfsProcessSection ( + PeiServices, + SectionType, + PpiOutput, + PpiOutputSize, + OutputBuffer, + OutputSize, + Authentication + ); + } + } + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + CompressionSection = (EFI_COMPRESSION_SECTION *)Section; + DecompressPpi = PeiReturnPpi (PeiServices, &gEfiPeiDecompressPpiGuid); + if (DecompressPpi != NULL) { + Status = DecompressPpi->Decompress ( + DecompressPpi, + CompressionSection, + &PpiOutput, + &PpiOutputSize + ); + if (!EFI_ERROR (Status)) { + return PeiFfsProcessSection ( + PeiServices, SectionType, PpiOutput, PpiOutputSize, OutputBuffer, OutputSize, Authentication + ); + } + } + } + + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; + SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + PEI_ASSERT (PeiServices, (SectionLength != 0)); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FileHandle - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINTN OutputSize; + UINT32 AuthenticationStatus; + + + FfsFileHeader = (EFI_FFS_FILE_HEADER *)FileHandle; + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1); + FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileSize -= sizeof (EFI_FFS_FILE_HEADER); + + return PeiFfsProcessSection ( + PeiServices, + SectionType, + Section, + FileSize, + SectionData, + &OutputSize, + &AuthenticationStatus + ); +} + + +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input VolumeHandle, search for the next matching name file. + +Arguments: + + FileName - File name to search. + VolumeHandle - The current FV to search. + FileHandle - Pointer to the file matching name in VolumeHandle. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + Status = PeiFindFileEx (VolumeHandle, FileName, 0, FileHandle, NULL); + if (Status == EFI_NOT_FOUND) { + *FileHandle = NULL; + } + return Status; +} + + +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +/*++ + +Routine Description: + + Collect information of given file. + +Arguments: + FileHandle - The handle to file. + FileInfo - Pointer to the file information. + +Returns: + EFI_STATUS + +--*/ +{ + UINT8 FileState; + UINT8 ErasePolarity; + EFI_FFS_FILE_HEADER *FileHeader; + EFI_PEI_FV_HANDLE VolumeHandle; + + if ((FileHandle == NULL) || (FileInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the FirmwareVolume which the file resides in. + // + if (!PeiFileHandleToVolume(FileHandle, &VolumeHandle)) { + return EFI_INVALID_PARAMETER; + } + + if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle); + + switch (FileState) { + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + break; + default: + return EFI_INVALID_PARAMETER; + } + + FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle; + CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID)); + FileInfo->FileType = FileHeader->Type; + FileInfo->FileAttributes = FileHeader->Attributes; + FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER); + FileInfo->Buffer = (FileHeader + 1); + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +/*++ + +Routine Description: + + Collect information of given Fv Volume. + +Arguments: + VolumeHandle - The handle to Fv Volume. + VolumeInfo - The pointer to volume information. + +Returns: + EFI_STATUS + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + + if (VolumeInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)VolumeHandle; + VolumeInfo->FvAttributes = FwVolHeader->Attributes; + VolumeInfo->FvStart = FwVolHeader; + VolumeInfo->FvSize = FwVolHeader->FvLength; + CopyMem (&VolumeInfo->FvFormat, &FwVolHeader->FileSystemGuid,sizeof(EFI_GUID)); + + if (FwVolHeader->ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset); + CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID)); + } + return EFI_SUCCESS; +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/Hob.c b/Core/CORE_PEI/CORE_PEI_PI/Hob.c new file mode 100644 index 0000000..30b7b3f --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Hob.c @@ -0,0 +1,191 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + Hob.c + +Abstract: + + EFI PEI Core HOB services + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +{ + // + // Only check this parameter in debug mode + // + + PEI_DEBUG_CODE ( + if (HobList == NULL) { + return EFI_INVALID_PARAMETER; + } + ) + + *HobList = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices)->HobList.Raw; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + + + Status = PeiGetHobList (PeiServices, Hob); + if (EFI_ERROR(Status)) { + return Status; + } + + HandOffHob = *Hob; + + Length = (UINT16)((Length + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - + HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < Length) { + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom)); + } + ) + return EFI_OUT_OF_RESOURCES; + } + + *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = (VOID *)(UINTN)MemoryBegin; + HobEnd = (EFI_HOB_GENERIC_HEADER*) (Hob+1); + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BootMode; + + Hob->EfiMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiMemoryBottom = MemoryBegin; + Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd+1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + return EFI_SUCCESS; +} diff --git a/Core/CORE_PEI/CORE_PEI_PI/Image.c b/Core/CORE_PEI/CORE_PEI_PI/Image.c new file mode 100644 index 0000000..a6967e0 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Image.c @@ -0,0 +1,932 @@ +/*++ + +Copyright (c) 2004 - 2009, 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: + + Image.c + +Abstract: + + Pei Core Load Image Support + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include "PeiApi.h" +#include "EfiImage.h" +#include EFI_PROTOCOL_DEFINITION (CustomizedDecompress) + +#include EFI_PPI_DEFINITION (LoadFile2) +#include EFI_GUID_DEFINITION (PeiPeCoffLoader) +#include EFI_PPI_DEFINITION (SectionExtraction) + + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + FileOffset - The offset, in bytes, into the file to read + ReadSize - The number of bytes to read from the file starting at FileOffset + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +; + +EFI_STATUS +PeiLoadImageLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for loading file image. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + The wrapper function of PeiLoadImageLoadImage(). + +Arguments: + + This - Pointer to EFI_PEI_LOAD_FILE_PPI. + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + EFI_STATUS. + +--*/ +; + + +EFI_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for get PE image entry point. + +Arguments: + + Pe32Data - Pointer to PE image. + EntryPoint - Pointer to entry point of PE image. + +Returns: + + EFI_SUCCESS. + +--*/ +; + +EFI_IMAGE_NT_HEADERS* +EFIAPI +GetPeHeader ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Pe32Data + ) +/*++ + +Routine Description: + + Routine for get PE image header. + +Arguments: + PeiServices - The PEI core services table. + Pe32Data - Pointer to PE image. + +Returns: + + Pointer to PE header. + +--*/ +; + +static EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = { + PeiLoadImageLoadImageWrapper +}; + + +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiLoadFile2PpiGuid, + &mPeiLoadImagePpi +}; + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + FileOffset - The offset, in bytes, into the file to read + ReadSize - The number of bytes to read from the file starting at FileOffset + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Support routine to return the Image Read + +Arguments: + + PeiServices - PEI Services Table + + ImageContext - The context of the image being loaded + +Returns: + + EFI_SUCCESS - If Image function location is found + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemoryBuffer; + + Status = (*PeiServices)->AllocatePages ( + PeiServices, + EfiBootServicesData, + 0x400 / EFI_PAGE_SIZE + 1, + &MemoryBuffer + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + (*PeiServices)->CopyMem ( + (VOID *) (UINTN) MemoryBuffer, + (VOID *) (UINTN) PeiImageRead, + 0x400 + ); + + ImageContext->ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; + + return Status; +} + +EFI_STATUS +PeiLoadImageLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for loading file image. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS Status; + PEI_CORE_INSTANCE *Private; + VOID *Pe32Data; + EFI_TE_IMAGE_HEADER *TEImageHeader; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeCoffLoader; + +#ifdef EFI_NT_EMULATOR + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + NT_PEI_LOAD_FILE_PPI *PeiNtService; +#else + VOID *EntryPointPtr; +#endif +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of compressed PEIMS +//and PEIMS from the firmware volumes in memory (see below). + BOOLEAN FixupRequired = FALSE; +//*** AMI PORTING END *****// + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + *EntryPoint = 0; + *AuthenticationState = 0; + ImageAddress = 0; + ImageSize = 0; + PeHdr = NULL; + + // + // Try to find a TE or PE32 section. + // + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_TE, + FileHandle, + (VOID **)&TEImageHeader + ); + Pe32Data = TEImageHeader; + if (EFI_ERROR (Status)) { + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_PE32, + FileHandle, + &Pe32Data + ); + } + + if (EFI_ERROR (Status)) { + // + // NO image types we support so exit. + // + return Status; + } + + // + // Check image header machine type. If not supported, skip it. + // + if (TEImageHeader != NULL) { + if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (TEImageHeader->Machine) && + !EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (TEImageHeader->Machine)) { + return EFI_UNSUPPORTED; + } + } else { + // + // Get PE32 Header to check machine type. + // + PeHdr = GetPeHeader(PeiServices, Pe32Data); + if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeHdr->FileHeader.Machine) && + !EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (PeHdr->FileHeader.Machine)) { + return EFI_UNSUPPORTED; + } +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of compressed PEIMS +//and PEIMS from the firmware volumes in memory. + if (PeHdr->OptionalHeader.ImageBase != (UINTN)Pe32Data) + FixupRequired = TRUE; +//*** AMI PORTING END *****// + } + + if (Private->PeiMemoryInstalled && + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || FixupRequired)) { + // + // Load, relocate, and run image in memory + // + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + if (Private->ImageReadFile == NULL) { + GetImageReadFunction (PeiServices, &ImageContext); + Private->ImageReadFile = ImageContext.ImageRead; + } else { + ImageContext.ImageRead = Private->ImageReadFile; + } + PeCoffLoader = Private->PeCoffLoader; + Status = PeCoffLoader->GetImageInfo (PeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate Memory for the image + // + Status = PeiAllocatePages ( + PeiServices, + EfiBootServicesData, + EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), + &ImageContext.ImageAddress + ); + ASSERT_PEI_ERROR (PeiServices,Status); + + if (ImageContext.IsTeImage && + TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA64) { + ImageContext.ImageAddress = ImageContext.ImageAddress + + TEImageHeader->StrippedSize - + sizeof (EFI_TE_IMAGE_HEADER); + } + + // + // Load the image to our new buffer + // + Status = PeCoffLoader->LoadImage (PeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Relocate the image in our new buffer + // + Status = PeCoffLoader->RelocateImage (PeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + ImageAddress = ImageContext.ImageAddress; + ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + } +#ifndef EFI_NT_EMULATOR + else if (TEImageHeader != NULL) { + // + // Get entry point from the TE image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)TEImageHeader; +//*** AMI PORTING BEGIN ***// +//Bug fix: the function must return a valid image size +// The original implmentation always returns NULL for XIP images. + ImageSize = FVSECTION_SIZE(TEImageHeader); +// ImageSize = 0; +//*** AMI PORTING END ***// + *EntryPoint = (EFI_PHYSICAL_ADDRESS)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + // + // Retrieve the entry point from the PE/COFF image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data; +//*** AMI PORTING BEGIN ***// +//Bug fix: the function must return a valid image size +// The original implmentation always returns NULL for XIP images. + ImageSize = PeHdr->OptionalHeader.SizeOfImage; +// ImageSize = 0; +//*** AMI PORTING END ***// + Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointPtr); + *EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPointPtr; + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } +#else + else { + if (TEImageHeader == NULL) { + PeHdr = GetPeHeader(PeiServices,Pe32Data); + } + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gNtPeiLoadFileGuid, + 0, + &PpiDescriptor, + &PeiNtService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeiNtService->PeiLoadFileService ( + Pe32Data, + &ImageAddress, + &ImageSize, + EntryPoint + ); + + if (EFI_ERROR (Status)) { + if (TEImageHeader != NULL) { + *EntryPoint = (EFI_PHYSICAL_ADDRESS)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (EFI_PHYSICAL_ADDRESS) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } + } + } +#endif + + + if (ImageAddressArg != NULL) { + *ImageAddressArg = ImageAddress; + } + + if (ImageSizeArg != NULL) { + *ImageSizeArg = ImageSize; + } + +//*** AMI PORTING BEGIN ***// +//Message is printed later. Disable this one +/* + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint)); + PEI_DEBUG_CODE ( + { + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN DirCount; + UINTN Index; + UINTN Index1; + BOOLEAN FileNameFound; + CHAR8 *AsciiString; + CHAR8 AsciiBuffer[512]; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *PeHeader; + + DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + + // + // Find the codeview info in the image and display the file name + // being loaded. + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + DebugEntry = NULL; + DirectoryEntry = NULL; + TEImageAdjust = 0; + if (TEImageHeader == NULL) { + if (PeHeader->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHeader->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress); + } + } else { + if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader + + TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + } + + if (DebugEntry != NULL && DirectoryEntry != NULL) { + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + AsciiString = NULL; + break; + } + if (AsciiString != NULL) { + FileNameFound = FALSE; + for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) { + if (AsciiString[Index] == '\\') { + Index1 = Index; + FileNameFound = TRUE; + } + } + + if (FileNameFound) { + for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) { + AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index]; + } + AsciiBuffer[Index - (Index1 + 1)] = 0; + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); + break; + } + } + } + } + } + } + } + ) + + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "\n")); +*/ +//*** AMI PORTING END ***// + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + The wrapper function of PeiLoadImageLoadImage(). + +Arguments: + + This - Pointer to EFI_PEI_LOAD_FILE_PPI. + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + EFI_STATUS. + +--*/ +{ + return PeiLoadImageLoadImage ( + GetPeiServicesTablePointer (), + FileHandle, + ImageAddressArg, + ImageSizeArg, + EntryPoint, + AuthenticationState + ); +} + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for load image file. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS PpiStatus; + EFI_STATUS Status; + UINTN Index; + EFI_PEI_LOAD_FILE_PPI *LoadFile; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + UINT16 Magic; + UINT16 Machine; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + + // + // If any instances of PEI_LOAD_FILE_PPI are installed, they are called. + // one at a time, until one reports EFI_SUCCESS. + // + Index = 0; + do { + PpiStatus = PeiLocatePpi ( + PeiServices, + &gEfiLoadFile2PpiGuid, + Index, + NULL, + (VOID **)&LoadFile + ); + if (!EFI_ERROR (PpiStatus)) { + Status = LoadFile->LoadFile ( + LoadFile, + FileHandle, + &ImageAddress, + &ImageSize, + EntryPoint, + AuthenticationState + ); + if (!EFI_ERROR (Status)) { + // + // Only support image machine type that is the same as PEI core. + // Get the image's machine type to check if supported. + // + Magic = *(UINT16 *)(UINTN) ImageAddress; + if (Magic == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TeHdr = (EFI_TE_IMAGE_HEADER *)(UINTN) ImageAddress; + Machine = TeHdr->Machine; + } else { + if (Magic == EFI_IMAGE_DOS_SIGNATURE) { + PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN) ImageAddress + (UINTN) ((((EFI_IMAGE_DOS_HEADER *)(UINTN) ImageAddress)->e_lfanew) & 0x0ffff)); + } else { + PeHdr = (EFI_IMAGE_NT_HEADERS *)(UINTN) ImageAddress; + } + Machine = PeHdr->FileHeader.Machine; + } + if (Machine == EFI_IMAGE_MACHINE_TYPE) { +//*** AMI PORTING BEGIN ***// +//break from the loop to print debug message (see below) +// return EFI_SUCCESS; + PpiStatus=EFI_SUCCESS; + break; +//*** AMI PORTING END *****// + } else { +//*** AMI PORTING BEGIN ***// +//break from the loop to print debug message (see below) +// return EFI_UNSUPPORTED; + PpiStatus=EFI_SUCCESS; + break; +//*** AMI PORTING END *****// + } + } + } + Index++; + } while (!EFI_ERROR (PpiStatus)); +//*** AMI PORTING BEGIN ***// +//Print debug message +#ifdef EFI_DEBUG +{ + EFI_FFS_FILE_HEADER *PeimFileHeader = (EFI_FFS_FILE_HEADER*)FileHandle; + if(!EFI_ERROR(PpiStatus)) + { + char sName[0x100]; + if (!GetName((VOID*)(UINTN)ImageAddress,sName)) + Sprintf_s(sName,sizeof(sName),"[%G]",&PeimFileHeader->Name); + PeiTrace(TRACE_PEICORE, PeiServices, "%s.Entry(%X)\n", sName, *EntryPoint); + } + else + { + PeiTrace( + TRACE_PEICORE, PeiServices, + "ERROR: attempt to load FFS file [%G] has failed\n", + &PeimFileHeader->Name + ); + } +} +#endif +//New image is loaded and is about to be launched +//Update LoadedImage PPI information + if(!EFI_ERROR(PpiStatus)) + UpdatedLoadedImagePpi(PeiServices,ImageAddress,ImageSize,FileHandle); +//*** AMI PORTING END *****// + return PpiStatus; +} + + +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Regitser PeCoffLoader to PeiCore PrivateData. And install + Pei Load File PPI. + +Arguments: + + PrivateData - Pointer to PEI_CORE_INSTANCE. + OldCoreData - Pointer to PEI_CORE_INSTANCE. + +Returns: + + NONE. + +--*/ +{ + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + + InstallEfiPeiPeCoffLoader (&PrivateData->PS, &PeiEfiPeiPeCoffLoader, NULL); + PrivateData->PeCoffLoader = PeiEfiPeiPeCoffLoader; + + if (OldCoreData == NULL) { + // + // The first time we are XIP (running from FLASH). We need to remember the + // FLASH address so we can reinstall the memory version that runs faster + // + PrivateData->XipLoadFile = &gPpiLoadFilePpiList; + PeiInstallPpi (&PrivateData->PS, PrivateData->XipLoadFile); + } else { + // + // 2nd time we are running from memory so replace the XIP version with the + // new memory version. + // + PeiReInstallPpi (&PrivateData->PS, PrivateData->XipLoadFile, &gPpiLoadFilePpiList); + } +} + + +EFI_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for get PE image entry point. + +Arguments: + + Pe32Data - Pointer to PE image. + EntryPoint - Pointer to entry point of PE image. + +Returns: + + EFI_SUCCESS. + +--*/ +{ + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_SERVICES **PeiServices; + + PeHdr = NULL; + PeiServices = GetPeiServicesTablePointer(); + + PEI_ASSERT (PeiServices, (Pe32Data != NULL)); + PEI_ASSERT (PeiServices,(EntryPoint != NULL)); + + PeHdr = GetPeHeader(PeiServices, Pe32Data); + + // + // Calculate the entry point relative to the start of the image. + // AddressOfEntryPoint is common for PE32 & PE32+ + // + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + return EFI_SUCCESS; +} + +EFI_IMAGE_NT_HEADERS* +EFIAPI +GetPeHeader ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Pe32Data + ) +/*++ + +Routine Description: + + Routine for get PE image header. + +Arguments: + PeiServices - The PEI core services table. + Pe32Data - Pointer to PE image. + +Returns: + + Pointer to PE header. + +--*/ +{ + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *PeHdr; + + PeHdr = NULL; + PEI_ASSERT (PeiServices, (Pe32Data != NULL)); + + DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) Pe32Data)->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + return PeHdr; +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/MemoryServices.c b/Core/CORE_PEI/CORE_PEI_PI/MemoryServices.c new file mode 100644 index 0000000..05a0ff3 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/MemoryServices.c @@ -0,0 +1,392 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + MemoryServices.c + +Abstract: + + EFI PEI Core memory services + +--*/ + +#include "Tiano.h" +#include "PeiApi.h" +#include "PeiCore.h" +#include "PeiLib.h" +//*** AMI PORTING BEGIN ***// +//use SDL token 'DXE_STACK_SIZE' to define stack size +#include <Token.h> +#undef PEI_STACK_SIZE +#define PEI_STACK_SIZE DXE_STACK_SIZE +//*** AMI PORTING END *****// + +VOID +InitializeMemoryServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +{ + PrivateData->SwitchStackSignal = FALSE; + + if (OldCoreData == NULL) { + // + // 1st time through we are using Temp memory + // + PrivateData->PeiMemoryInstalled = FALSE; + PrivateData->BottomOfCarHeap = SecCoreData->PeiTemporaryRamBase; + PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + SecCoreData->PeiTemporaryRamSize); + + PEI_DEBUG_CODE ( + { + PrivateData->SizeOfCacheAsRam = SecCoreData->PeiTemporaryRamSize + SecCoreData->StackSize; + PrivateData->MaxTopOfCarHeap = (VOID*)((UINTN)PrivateData->BottomOfCarHeap + PrivateData->SizeOfCacheAsRam); + } + ) + + PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap; + + PeiCoreBuildHobHandoffInfoTable ( + BOOT_WITH_FULL_CONFIGURATION, + (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap, + (UINTN) SecCoreData->PeiTemporaryRamSize + ); + } + + return; +} + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob; + EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob; + UINT64 PeiStackSize; + UINT64 EfiFreeMemorySize; + EFI_PHYSICAL_ADDRESS PhysicalAddressOfOldHob; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + +//*** AMI PORTING BEGIN ***// + if (PrivateData->PeiMemoryInstalled) { + //This function should be called once. Report error if this is the second call + PEI_ERROR_CODE(PeiServices, PEI_MEMORY_INSTALLED_TWICE, EFI_ERROR_MINOR); + }else { + //Debug message + PEI_TRACE((TRACE_PEICORE, PeiServices, "Memory Installed: Address=%lX; Length=%lX\n",MemoryBegin,MemoryLength)); + } +//*** AMI PORTING END *****// + + PrivateData->SwitchStackSignal = TRUE; + PrivateData->PeiMemoryInstalled = TRUE; + + PrivateData->StackBase = MemoryBegin; + + PeiStackSize = RShiftU64 (MemoryLength, 1); + if (PEI_STACK_SIZE > PeiStackSize) { + PrivateData->StackSize = PeiStackSize; + } else { + PrivateData->StackSize = PEI_STACK_SIZE; + } + + OldHandOffHob = PrivateData->HobList.HandoffInformationTable; + + PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize)); + NewHandOffHob = PrivateData->HobList.HandoffInformationTable; + PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob; + + EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob; + + PeiCoreCopyMem ( + NewHandOffHob, + OldHandOffHob, + (UINTN)EfiFreeMemorySize + ); + + NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength; + NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop; + NewHandOffHob->EfiMemoryBottom = MemoryBegin; + + NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize; + + NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob + + (OldHandOffHob->EfiEndOfHobList - + PhysicalAddressOfOldHob); + + ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob); + + PeiBuildHobStack ((EFI_PEI_SERVICES**)PeiServices, PrivateData->StackBase, PrivateData->StackSize); + +//*** AMI PORTING BEGIN ***// +//Update LoadedImage pointers +PrivateData->LoadedImage = (EFI_PEI_PPI_DESCRIPTOR*) + ( (UINTN)PrivateData->LoadedImage + ((UINTN)NewHandOffHob - (UINTN)OldHandOffHob) ); +//*** AMI PORTING END *****// + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob)); + PEI_DEBUG ((PeiServices, EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob)); + } + ) + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS Offset; + EFI_STATUS Status; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Check if Hob already available + // + if (!PrivateData->PeiMemoryInstalled) { + return EFI_NOT_AVAILABLE_YET; + } + + Hob.Raw = PrivateData->HobList.Raw; + + // + // Check to see if on 4k boundary + // + Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF; + + // + // If not aligned, make the allocation aligned. + // + if (Offset != 0) { + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset; + } + + // + // Verify that there is sufficient memory to satisfy the allocation + // + if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < + Hob.HandoffInformationTable->EfiFreeMemoryBottom) { + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_ERROR, "PeiAllocatePages fail: Pages - 0x%08x\n", Pages)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom)); + } + ) + return EFI_OUT_OF_RESOURCES; + } else { + // + // Update the PHIT to reflect the memory usage + // + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE; + + // + // Update the value for the caller + // + *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop; + + // + // Create a memory allocation HOB. + // + Status = PeiBuildHobMemoryAllocation ( + (EFI_PEI_SERVICES**)PeiServices, + Hob.HandoffInformationTable->EfiFreeMemoryTop, + Pages * EFI_PAGE_SIZE + Offset, + NULL, + MemoryType + ); + + return Status; + } +} + + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_POOL *Hob; + + + Status = PeiCreateHob ( + PeiServices, + EFI_HOB_TYPE_PEI_MEMORY_POOL, + (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size), + &Hob + ); + *Buffer = Hob+1; + + + return Status; +} + +VOID +EFIAPI +PeiCoreCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +{ + EfiCommonLibCopyMem (Destination, Source, Length); +} + +VOID +EFIAPI +PeiCoreSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Set Size bytes at Buffer address with Value + +Arguments: + + Buffer - Target of set + + Size - Amount of memory to set + + Value - Value to place in memory + +Returns: + + None + +--*/ +{ + EfiCommonLibSetMem (Buffer, Size, Value); +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/PeiCore.h b/Core/CORE_PEI/CORE_PEI_PI/PeiCore.h new file mode 100644 index 0000000..2913deb --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/PeiCore.h @@ -0,0 +1,1416 @@ +/*++ + +Copyright (c) 2004 - 2009, 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: + + PeiCore.h + +Abstract: + + Definition of Pei Core Structures and Services + +Revision History + +--*/ + +#ifndef _PEICORE_H_ +#define _PEICORE_H_ + +#include "EfiImage.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeiApi.h" +#include "PeiHob.h" +#include "PeiDebug.h" +#include "EfiFirmwareFileSystem.h" +#include "EfiFirmwareVolumeHeader.h" +#ifdef EFI64 +#include "SalApi.h" +#endif + +#include "EfiCommonLib.h" +#include EFI_GUID_DEFINITION (FirmwareFileSystem2) +#include EFI_GUID_DEFINITION (PeiApriori) +#include EFI_GUID_DEFINITION (PeiPeCoffLoader) +#include EFI_PPI_DEFINITION (Reset) +#include EFI_PPI_DEFINITION (DxeIpl) +#include EFI_PPI_DEFINITION (StatusCode) +#include EFI_PPI_DEFINITION (Security2) +#include EFI_PPI_DEFINITION (Decompress) +#include EFI_PPI_DEFINITION (FirmwareVolumeInfo) +#include EFI_PPI_DEFINITION (LoadFile2) +#include EFI_PPI_DEFINITION (FirmwareVolume) +#include EFI_PPI_DEFINITION (GuidedSectionExtraction) + + +#ifdef EFI_NT_EMULATOR +#include EFI_PPI_DEFINITION (NtPeiLoadFile) +#endif + +//*** AMI PORTING BEGIN ***// +#include <PPI/LoadedImagePpi.h> +//*** AMI PORTING END *****// + +// +//Build private HOB to PEI core to transfer old NEM-range data to new NEM-range +// +#define EFI_PEI_CORE_PRIVATE_GUID \ + {0xd641a0f5, 0xcb7c, 0x4846, 0xa3, 0x80, 0x1d, 0x01, 0xb4, 0xd9, 0xe3, 0xb9} + +#define PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE 0xff + +// +// Pei Core private data structures +// +typedef union { + EFI_PEI_PPI_DESCRIPTOR *Ppi; + EFI_PEI_NOTIFY_DESCRIPTOR *Notify; + VOID *Raw; +} PEI_PPI_LIST_POINTERS; + + +#define PEI_STACK_SIZE 0x20000 +#define MAX_PPI_DESCRIPTORS 128 + +typedef struct { + INTN PpiListEnd; + INTN NotifyListEnd; + INTN DispatchListEnd; + INTN LastDispatchedInstall; + INTN LastDispatchedNotify; + PEI_PPI_LIST_POINTERS PpiListPtrs[MAX_PPI_DESCRIPTORS]; +} PEI_PPI_DATABASE; + + +#define PEI_CORE_MAX_FV_SUPPORTED 8 +#define PEI_CORE_MAX_PEIM_PER_FV 64 + +// +// PEI_CORE_FV_HANDE.PeimState +// Do not change these values as there is code doing math to change states. +// Look for Private->Fv[FvCount].PeimState[PeimCount]++; +// +#define PEIM_STATE_NOT_DISPATCHED 0x00 +#define PEIM_STATE_DISPATCHED 0x01 +#define PEIM_STATE_REGISITER_FOR_SHADOW 0x02 +#define PEIM_STATE_DONE 0x03 + +typedef struct { + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINT8 PeimState[PEI_CORE_MAX_PEIM_PER_FV]; + EFI_PEI_FILE_HANDLE FvFileHandles[PEI_CORE_MAX_PEIM_PER_FV]; + BOOLEAN ScanFv; +} PEI_CORE_FV_HANDLE; + +// +// Pei Core private data structure instance +// +#define PEI_CORE_HANDLE_SIGNATURE EFI_SIGNATURE_32('P','e','i','C') + +typedef struct{ + UINTN Signature; + EFI_PEI_SERVICES *PS; + PEI_PPI_DATABASE PpiData; + UINTN FvCount; + PEI_CORE_FV_HANDLE Fv[PEI_CORE_MAX_FV_SUPPORTED]; + EFI_PEI_FILE_HANDLE CurrentFvFileHandles[PEI_CORE_MAX_PEIM_PER_FV]; + UINTN AprioriCount; + UINTN CurrentPeimFvCount; + UINTN CurrentPeimCount; + EFI_PEI_FILE_HANDLE CurrentFileHandle; + BOOLEAN PeimNeedingDispatch; + BOOLEAN PeimDispatchOnThisPass; + BOOLEAN PeimDispatcherReenter; + UINTN AllFvCount; + EFI_PEI_FV_HANDLE AllFv[PEI_CORE_MAX_FV_SUPPORTED]; + EFI_PEI_HOB_POINTERS HobList; + BOOLEAN SwitchStackSignal; + BOOLEAN PeiMemoryInstalled; + EFI_PHYSICAL_ADDRESS StackBase; + UINT64 StackSize; + VOID *BottomOfCarHeap; + VOID *TopOfCarHeap; + VOID *CpuIo; + EFI_PEI_SECURITY2_PPI *PrivateSecurityPpi; + EFI_PEI_SERVICES ServiceTableShadow; + UINTN SizeOfCacheAsRam; + VOID *MaxTopOfCarHeap; + EFI_PEI_PPI_DESCRIPTOR *XipLoadFile; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeCoffLoader; + EFI_PEI_PE_COFF_LOADER_READ_FILE ImageReadFile; +//*** AMI PORTING BEGIN ***// + EFI_PEI_PPI_DESCRIPTOR *LoadedImage; + EFI_PEI_LOADED_IMAGE_PPI LoadedImagePpi; +//*** AMI PORTING END *****// +} PEI_CORE_INSTANCE; + + +// +// Pei Core Instance Data Macros +// + +#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \ + (PEI_CR(a, PEI_CORE_INSTANCE, PS, PEI_CORE_HANDLE_SIGNATURE)) + + +typedef +EFI_STATUS +(EFIAPI *PEI_CORE_ENTRY_POINT) ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList, + IN PEI_CORE_INSTANCE *OldCoreData + ); + + +VOID +SwitchCoreStacks ( + IN VOID *EntryPoint, + IN UINTN Parameter1, + IN UINTN Parameter2, + IN UINTN Parameter3, + IN VOID *NewStack + ) +/*++ + +Routine Description: + + Routine for PEI switching stacks. + +Arguments: + + EntryPoint - Entry point with new stack. + Parameter1 - First parameter for entry point. + Parameter2 - Second parameter for entry point. + NewStack - Pointer to new stack. + +Returns: + + None + +--*/ +; +extern EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList; + + +typedef +VOID +(EFIAPI *SWITCH_STACK_ENTRY_POINT) ( + IN VOID *Context1, OPTIONAL + IN VOID *Context2 OPTIONAL + ); + + + +// +// Main PEI entry +// +EFI_STATUS +EFIAPI +PeiMain ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + PpList - Pointer to Ppi list provided by SEC phase. + +Returns: + + This function never returns + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiCore ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + PpList - Pointer to Ppi list provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + +--*/ +; + + +// +// Dispatcher support functions +// + +BOOLEAN +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +; + + +VOID +PeiDispatcher ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *Private + ) + +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + Private - Pointer to the private data passed in from caller + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +; + + +VOID +InitializeDispatcherData ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + SecCoreData - Information and services provided by SEC phase. + + +Returns: + + None + +--*/ +; + + +BOOLEAN +DepexSatisfied ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + + Private - Pointer to the private data passed in from caller. + FileHandle - File handle of PEIM. + PeimCount - The PEIM sequence in one FV. + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +; + +#ifdef EFI64 + // + // In Ipf we should make special changes for the PHIT pointers to support + // recovery boot in cache mode. + // +#define SWITCH_TO_CACHE_MODE(CoreData) SwitchToCacheMode(CoreData) +#define CACHE_MODE_ADDRESS_MASK 0x7FFFFFFFFFFFFFFFULL +VOID +SwitchToCacheMode ( + IN PEI_CORE_INSTANCE *CoreData +) +/*++ + +Routine Description: + + Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR. + +Arguments: + + CoreData - The PEI core Private Data + +Returns: + +--*/ +; + +#else + +#define SWITCH_TO_CACHE_MODE(CoreData) + +#endif + +// +// PPI support functions +// +VOID +InitializePpiServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +; + +VOID +ConvertPpiPointers ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Migrate the Hob list from the CAR stack to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR * PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +; + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR * OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR * NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID * Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor OPTIONAL, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +; + + +VOID * +PeiReturnPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid + ); + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR * NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +; + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ +; + +VOID +DispatchNotify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ +; + +// +// Boot mode support functions +// +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +; + +// +// Security support functions +// +VOID +InitializeSecurityServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +; + +EFI_STATUS +VerifyFv ( + IN EFI_PEI_FV_HANDLE VolumeHandle + ) +/*++ + +Routine Description: + + Provide a callout to the OEM FV verification service. + +Arguments: + + VolumeHandle - Pointer to the FV under investigation. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + + +EFI_STATUS +VerifyPeim ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +; + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +; + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +; + + +// +// FFS Fw Volume support functions +// + +EFI_STATUS +EFIAPI +PeiFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +/*++ + +Routine Description: + + Search the next FV Volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + Instance - The Fv Volume Instance. + VolumeHandle - Pointer to the current Fv Volume to search. + +Returns: + EFI_INVALID_PARAMETER - VolumeHandle is NULL. + EFI_NOT_FOUND - No FV Volume is found. + EFI_SUCCESS - The next FV Volume is found. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input FvHandle, search for the next matching type file in the FV Volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only file of this type. + FvHandle - Pointer to the current FV to search. + FileHandle - Pointer to the file matching SearchType in FwVolHeader. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FileHandle - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +// +// Memory support functions +// +VOID +InitializeMemoryServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS * Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of allocation. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +; + +VOID +EFIAPI +PeiCoreCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +; + +VOID +EFIAPI +PeiCoreSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Set Size bytes at Buffer address with Value + +Arguments: + + Buffer - Target of set + + Size - Amount of memory to set + + Value - Value to place in memory + +Returns: + + None + +--*/ +; + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for load image file. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + + CodeType - Type of Status Code. + + Value - Value to output for Status Code. + + Instance - Instance Number of this status code. + + CallerId - ID of the caller of this status code. + + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +; + + +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize PeiCore Fv List. + +Arguments: + PrivateData - Pointer to PEI_CORE_INSTANCE. + SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. + +Returns: + NONE + +--*/ +; + + +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Process Firmware Volum Information once FvInfoPPI install. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the interface could be successfully + installed + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input VolumeHandle, search for the next matching name file. + +Arguments: + + FileName - File name to search. + VolumeHandle - The current FV to search. + FileHandle - Pointer to the file matching name in VolumeHandle. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +/*++ + +Routine Description: + + Collect information of given file. + +Arguments: + FileHandle - The handle to file. + FileInfo - Pointer to the file information. + +Returns: + EFI_STATUS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +/*++ + +Routine Description: + + Collect information of given Fv Volume. + +Arguments: + VolumeHandle - The handle to Fv Volume. + VolumeInfo - The pointer to volume information. + +Returns: + EFI_STATUS + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + This routine enable a PEIM to register itself to shadow when PEI Foundation + discovery permanent memory. + +Arguments: + FileHandle - File handle of a PEIM. + +Returns: + EFI_NOT_FOUND - The file handle doesn't point to PEIM itself. + EFI_ALREADY_STARTED - Indicate that the PEIM has been registered itself. + EFI_SUCCESS - Successfully to register itself. + +--*/ +; + + +EFI_STATUS +PeiFindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName, OPTIONAL + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle, + IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + Flag - Indicator for if this is for PEI Dispath search + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Regitser PeCoffLoader to PeiCore PrivateData. And install + Pei Load File PPI. + +Arguments: + + PrivateData - Pointer to PEI_CORE_INSTANCE. + OldCoreData - Pointer to PEI_CORE_INSTANCE. + +Returns: + + NONE. + +--*/ +; + +//*** AMI PORTING BEGIN ***// +//This function is used to update LoadedImage PPI information +//LoadedImage PPI is defined in PI 1.0 specification +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +); + +#include <AmiPeiLib.h> +//*** AMI PORTING END *****// +#endif diff --git a/Core/CORE_PEI/CORE_PEI_PI/PeiMain.c b/Core/CORE_PEI/CORE_PEI_PI/PeiMain.c new file mode 100644 index 0000000..31c5db1 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/PeiMain.c @@ -0,0 +1,404 @@ +/*++ + +Copyright (c) 2006 - 2007, 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: + + PeiMain.c + +Abstract: + + Pei Core Main Entry Point + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_PPI_DEFINITION (MemoryDiscovered) +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) +#include EFI_GUID_DEFINITION (StatusCode) + +// +// CAR is filled with this initial value during SEC phase +// +#define INIT_CAR_VALUE 0x5AA55AA5 + +#ifdef EFI_PEI_PERFORMANCE + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ); + +#endif + +//*** AMI PORTING BEGIN ***// +VOID InitParts(VOID* p1, VOID*p2); +VOID InitPartsMem(VOID* p1, VOID*p2); +VOID ProcessLoadHob(EFI_PEI_SERVICES **PeiServices); +VOID AmiInitParts(IN EFI_PEI_SERVICES **PeiServices, VOID* InitFunction); +//*** AMI PORTING END *****// + +// +// PPI that represents memory being discoverd in PEI. +// +static EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiMemoryDiscoveredPpiGuid, + NULL +}; + +static EFI_PEI_SERVICES mPS = { + { + PEI_SERVICES_SIGNATURE, + PEI_SERVICES_REVISION, + sizeof (EFI_PEI_SERVICES), + 0, + 0 + }, + PeiInstallPpi, + PeiReInstallPpi, + PeiLocatePpi, + PeiNotifyPpi, + + PeiGetBootMode, + PeiSetBootMode, + + PeiGetHobList, + PeiCreateHob, + + PeiFfsFindNextVolume, + PeiFfsFindNextFile, + PeiFfsFindSectionData, + + PeiInstallPeiMemory, + PeiAllocatePages, + PeiAllocatePool, + PeiCoreCopyMem, + PeiCoreSetMem, + + PeiReportStatusCode, + PeiResetSystem, + + NULL, + NULL, + + PeiFfsFindFileByName, + PeiFfsGetFileInfo, + PeiFfsGetVolumeInfo, + PeiRegisterForShadow +}; + + +// +// Main entry point to the PEI Core +// +EFI_PEI_CORE_ENTRY_POINT (PeiMain) + +EFI_STATUS +EFIAPI +PeiMain ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + SecCoreData - Information about the PEI core's operating environment. + PpList - Points to a list of one or more PPI descriptors to be + installed initially by the PEI core. + +Returns: + + This function never returns + +--*/ +{ + return PeiCore (SecCoreData,PpList, NULL); +} + +EFI_STATUS +EFIAPI +PeiCore ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + PpList - Pointer to Ppi list provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + EFI_NOT_FOUND - Never reach + +--*/ +{ + PEI_CORE_INSTANCE PrivateData; + EFI_PEI_SERVICES **PeiServices; + EFI_STATUS Status; + EFI_DXE_IPL_PPI *DxeIpl; + EFI_PEI_CPU_IO_PPI *CpuIo; + EFI_PEI_PCI_CFG2_PPI *PciCfg; + +#ifdef EFI_PEI_PERFORMANCE + UINT64 mTick; + + mTick = 0; + if (OldCoreData == NULL) { + GetTimerValue (&mTick); + } +#endif + + + // + // For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory() + // the 63-bit of address is set to 1. + // + SWITCH_TO_CACHE_MODE (OldCoreData); + + if (OldCoreData != NULL) { + + // + // 2nd time through we are using System Memory and we restore a previous + // state by copying the OldCoreData into PrivateData. A lot of the + // init code will note initialize PrivateData on the 2nd pass. + // + PeiCoreCopyMem (&PrivateData, OldCoreData, sizeof (PEI_CORE_INSTANCE)); + + // + // 2nd time through Pei Core has been shadowed. To Pei Services, + // CpuIo and PciCfg services may have been updated by some Pei Modules. So before + // update PrivateData.ServiceTableShadow with memory version, save the CpuIo + // PciCfg and restore them then. + // + CpuIo = (VOID*)PrivateData.ServiceTableShadow.CpuIo; + PciCfg = (VOID*)PrivateData.ServiceTableShadow.PciCfg; + PeiCoreCopyMem (&(PrivateData.ServiceTableShadow), &mPS, sizeof (EFI_PEI_SERVICES)); + PrivateData.ServiceTableShadow.CpuIo = CpuIo; + PrivateData.ServiceTableShadow.PciCfg = PciCfg; + } else { + + // + // 1st time through we are using Temp memory + // + PeiCoreSetMem (&PrivateData, sizeof (PEI_CORE_INSTANCE),0); + PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; + + // + // Copy PeiServices from ROM to Temp memory in PrivateData + // + PeiCoreCopyMem (&(PrivateData.ServiceTableShadow), &mPS, sizeof (EFI_PEI_SERVICES)); + } + + PrivateData.PS = &PrivateData.ServiceTableShadow; + PeiServices = &PrivateData.PS; + + InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData); + + InitializePpiServices (&PrivateData, OldCoreData); + + // + // Save PeiServicePointer so that it can be retrieved anywhere. + // + SetPeiServicesTablePointer(PeiServices); + + if (OldCoreData != NULL) { + + PEI_PERF_END (&PrivateData.PS,L"PreMem", NULL, 0); + PEI_PERF_START (&PrivateData.PS,L"PostMem", NULL, 0); + + // + // The following code dumps out interesting cache as RAM usage information + // so we can keep tabs on how the cache as RAM is being utilized. The + // PEI_DEBUG_CODE macro is used to prevent this code from being compiled + // on a debug build. + // + PEI_DEBUG_CODE ( + { + UINTN *StackPointer; + UINTN StackValue; + + StackValue = INIT_CAR_VALUE; + for (StackPointer = (UINTN *) OldCoreData->TopOfCarHeap; + ((UINTN) StackPointer < ((UINTN) OldCoreData->BottomOfCarHeap + OldCoreData->SizeOfCacheAsRam)) + && StackValue == INIT_CAR_VALUE; + StackPointer++) { + StackValue = *StackPointer; + } + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", OldCoreData->SizeOfCacheAsRam)); + PEI_DEBUG ( + ( + &PrivateData.PS, EFI_D_INFO, " CAR stack ever used: %d bytes.\n", + ((UINTN) OldCoreData->MaxTopOfCarHeap - (UINTN) StackPointer) + ) + ); + PEI_DEBUG ( + ( + &PrivateData.PS, EFI_D_INFO, " CAR heap used: %d bytes.\n", + ((UINTN) OldCoreData->HobList.HandoffInformationTable->EfiFreeMemoryBottom - + (UINTN) OldCoreData->HobList.Raw) + ) + ); + } + ) + +//*** AMI PORTING BEGIN ***// + PrivateData.LoadedImage->Ppi = &PrivateData.LoadedImagePpi; +//*** AMI PORTING END *****// + + // + // Alert any listeners that there is permanent memory available + // + PEI_PERF_START (&PrivateData.PS,L"DisMem", NULL, 0); + Status = PeiInstallPpi (&PrivateData.PS, &mMemoryDiscoveredPpi); + PEI_PERF_END (&PrivateData.PS,L"DisMem", NULL, 0); + + } else { + + // + // Report Status Code EFI_SW_PC_INIT + // + PEI_REPORT_STATUS_CODE ( + &(PrivateData.PS), + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT, + 0, + NULL, + NULL + ); + + // + // If first pass, start performance measurement. + // + PEI_PERF_START (&PrivateData.PS,L"PreMem", NULL, mTick); + + // + // If SEC provided any PPI services to PEI, install them. + // + if (PpList != NULL) { + Status = PeiInstallPpi (&PrivateData.PS, PpList); + ASSERT_PEI_ERROR (&PrivateData.PS, Status); + } +//*** AMI PORTING BEGIN ***// +{ + static EFI_GUID gEfiPeiLoadedImagePpiGuid = EFI_PEI_LOADED_IMAGE_PPI_GUID; + static EFI_PEI_PPI_DESCRIPTOR LoadedImagePpiDesc = + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiLoadedImagePpiGuid, NULL + }; + PeiAllocatePool(&PrivateData.PS,sizeof(EFI_PEI_PPI_DESCRIPTOR),&PrivateData.LoadedImage); + *PrivateData.LoadedImage = LoadedImagePpiDesc; + PrivateData.LoadedImage->Ppi = &PrivateData.LoadedImagePpi; + PeiInstallPpi (&PrivateData.PS, PrivateData.LoadedImage); +} +//*** AMI PORTING END *****// + } + + InitializeSecurityServices (&PrivateData, OldCoreData); + + InitializeDispatcherData (&PrivateData, OldCoreData, SecCoreData); + + // + // Install Pei Load File PPI. + // + InitializeImageServices (&PrivateData, OldCoreData); + + // + // Call PEIM dispatcher + // +//*** AMI PORTING BEGIN ***// + if (OldCoreData != NULL) { + AmiInitParts(PeiServices, InitPartsMem); + ProcessLoadHob(PeiServices); + } else { + AmiInitParts(PeiServices, InitParts); + } +//*** AMI PORTING END *****// + PeiDispatcher (SecCoreData, &PrivateData); + + // + // Check if InstallPeiMemory service was called. + // +//*** AMI PORTING BEGIN ***// + //report MEMORY_NOT_INSTALLED error + if (!PrivateData.PeiMemoryInstalled) + PEI_ERROR_CODE(&PrivateData.PS, PEI_MEMORY_NOT_INSTALLED, EFI_ERROR_MAJOR); +// PEI_ASSERT(&PrivateData.PS, PrivateData.PeiMemoryInstalled == TRUE); +//*** AMI PORTING END *****// + + PEI_PERF_END (&PrivateData.PS, L"PostMem", NULL, 0); + + DxeIpl = PeiReturnPpi (&PrivateData.PS, &gEfiDxeIplPpiGuid); +//*** AMI PORTING BEGIN ***// + //report DXEIPL_NOT_FOUND error + if (DxeIpl==NULL) + PEI_ERROR_CODE(&PrivateData.PS, PEI_DXEIPL_NOT_FOUND, EFI_ERROR_MAJOR); +// PEI_ASSERT (&PrivateData.PS, DxeIpl != NULL); +//*** AMI PORTING END *****// + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "DXE IPL Entry\n")); + +//*** AMI PORTING BEGIN ***// + //DxeIpl->Entry (DxeIpl, &PrivateData.PS, PrivateData.HobList); + DxeIpl->Entry (DxeIpl, &PrivateData.PS, PrivateData.HobList.Raw); +//*** AMI PORTING END *****// +//*** AMI PORTING BEGIN ***// + // If DXE IPL returned control, let's call dispatcher again + // DXE IPL might have dicovered new FV or have changed a boot mode + + // reset previous bitmap so that the dispatcher will attempt to execute any new PEIMs + // dispatch + PeiDispatcher (SecCoreData, &PrivateData); + // DXE IPL + DxeIpl->Entry (DxeIpl, &PrivateData.PS, PrivateData.HobList.Raw); +//*** AMI PORTING END *****// + PEI_ASSERT (&PrivateData.PS,FALSE); + return EFI_NOT_FOUND; + +} + +//*** AMI PORTING BEGIN ***// +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +) +{ + PEI_CORE_INSTANCE *Private = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + Private->LoadedImagePpi.ImageAddress = ImageAddress; + Private->LoadedImagePpi.ImageSize = ImageSize; + Private->LoadedImagePpi.FileHandle = FileHandle; + PeiReInstallPpi(PeiServices,Private->LoadedImage,Private->LoadedImage); +} +//*** AMI PORTING END *****// diff --git a/Core/CORE_PEI/CORE_PEI_PI/Ppi.c b/Core/CORE_PEI/CORE_PEI_PI/Ppi.c new file mode 100644 index 0000000..01236e7 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Ppi.c @@ -0,0 +1,687 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + Ppi.c + +Abstract: + + EFI PEI Core PPI services + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +VOID +InitializePpiServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +{ + if (OldCoreData == NULL) { + PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1; + } + + return; +} + +VOID +ConvertPpiPointers ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Convert PPI pointers after the Hob list was migrated from the temporary memory + to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + None + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + UINT8 Index; + PEI_PPI_LIST_POINTERS *PpiPointer; + UINTN Fixup; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Fixup = (UINTN)NewHandOffHob - (UINTN)OldHandOffHob; + + for (Index = 0; Index < MAX_PPI_DESCRIPTORS; Index++) { + if (Index < PrivateData->PpiData.PpiListEnd || + Index > PrivateData->PpiData.NotifyListEnd) { + PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index]; + + if (((UINTN)PpiPointer->Raw < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Raw >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the PEIM descriptor from the old HOB heap + // to the relocated HOB heap. + // + PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup); + + // + // Only when the PEIM descriptor is in the old HOB should it be necessary + // to try to convert the pointers in the PEIM descriptor + // + + if (((UINTN)PpiPointer->Ppi->Guid < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Ppi->Guid >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the GUID in the PPI or NOTIFY descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup); + } + + // + // Assume that no code is located in the temporary memory, so the pointer to + // the notification function in the NOTIFY descriptor needs not be converted. + // + if (Index < PrivateData->PpiData.PpiListEnd && + (UINTN)PpiPointer->Ppi->Ppi < (UINTN)OldHandOffHob->EfiFreeMemoryBottom && + (UINTN)PpiPointer->Ppi->Ppi >= (UINTN)OldHandOffHob) { + // + // Convert the pointer to the PPI interface structure in the PPI descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup); + } + } + } + } +} + + + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN LastCallbackInstall; + + + if (PpiList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + Index = PrivateData->PpiData.PpiListEnd; + LastCallbackInstall = Index; + + // + // This is loop installs all PPI descriptors in the PpiList. It is terminated + // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_PPI_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the NotifyList + // + if (Index == PrivateData->PpiData.NotifyListEnd + 1) { + return EFI_OUT_OF_RESOURCES; + } + // + // Check if it is a valid PPI. + // If not, rollback list to exclude all in this list. + // Try to indicate which item failed. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + PrivateData->PpiData.PpiListEnd = LastCallbackInstall; + PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi)); + return EFI_INVALID_PARAMETER; + } + +//*** AMI PORTING BEGIN ***// +//Disable PPI messages +// PEI_DEBUG((PeiServices, EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); +//*** AMI PORTING END ***// + PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*)PpiList; + PrivateData->PpiData.PpiListEnd++; + + // + // Continue until the end of the PPI List. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + PpiList++; + Index++; + } + + // + // Dispatch any callback level notifies for newly installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + LastCallbackInstall, + PrivateData->PpiData.PpiListEnd, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + + + if ((OldPpi == NULL) || (NewPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Find the old PPI instance in the database. If we can not find it, + // return the EFI_NOT_FOUND error. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) { + break; + } + } + if (Index == PrivateData->PpiData.PpiListEnd) { + return EFI_NOT_FOUND; + } + + // + // Remove the old PPI from the database, add the new one. + // +//*** AMI PORTING BEGIN ***// +//Disable PPI messages +// PEI_DEBUG((PeiServices, EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); +//*** AMI PORTING END ***// + PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*)NewPpi; + + // + // Dispatch any callback level notifies for the newly installed PPI. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + Index, + Index+1, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor OPTIONAL, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + EFI_GUID *CheckGuid; + EFI_PEI_PPI_DESCRIPTOR *TempPtr; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Search the data base for the matching instance of the GUIDed PPI. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi; + CheckGuid = TempPtr->Guid; + + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) { + if (Instance == 0) { + + if (PpiDescriptor != NULL) { + *PpiDescriptor = TempPtr; + } + + if (Ppi != NULL) { + *Ppi = TempPtr->Ppi; + } + + + return EFI_SUCCESS; + } + Instance--; + } + } + + return EFI_NOT_FOUND; + +} + + + +VOID * +PeiReturnPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid + ) +{ + EFI_STATUS Status; + VOID *Ppi; + + Status = PeiLocatePpi (PeiServices, Guid, 0, NULL, &Ppi); + + return (EFI_ERROR (Status)) ? NULL : Ppi; +} + + + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN NotifyIndex; + INTN LastCallbackNotify; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr; + UINTN NotifyDispatchCount; + + + NotifyDispatchCount = 0; + + if (NotifyList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + Index = PrivateData->PpiData.NotifyListEnd; + LastCallbackNotify = Index; + + // + // This is loop installs all Notify descriptors in the NotifyList. It is + // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_NOTIFY_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the PpiList + // + if (Index == PrivateData->PpiData.PpiListEnd - 1) { + return EFI_OUT_OF_RESOURCES; + } + + // + // If some of the PPI data is invalid restore original Notify PPI database value + // + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { + PrivateData->PpiData.NotifyListEnd = LastCallbackNotify; + PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify)); + return EFI_INVALID_PARAMETER; + } + + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyDispatchCount ++; + } + + PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR*)NotifyList; + + PrivateData->PpiData.NotifyListEnd--; + PEI_DEBUG((PeiServices, EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + // + // Go the next descriptor. Remember the NotifyList moves down. + // + NotifyList++; + Index--; + } + + // + // If there is Dispatch Notify PPI installed put them on the bottom + // + if (NotifyDispatchCount > 0) { + for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) { + if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify; + + for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){ + PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify; + } + PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr; + PrivateData->PpiData.DispatchListEnd--; + } + } + + LastCallbackNotify -= NotifyDispatchCount; + } + + // + // Dispatch any callback level notifies for all previously installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + 0, + PrivateData->PpiData.PpiListEnd, + LastCallbackNotify, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN TempValue; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + + while (TRUE) { + // + // Check if the PEIM that was just dispatched resulted in any + // Notifies getting installed. If so, go process any dispatch + // level Notifies that match the previouly installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // DispatchListEnd (with NotifyPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) { + TempValue = PrivateData->PpiData.DispatchListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + 0, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.LastDispatchedNotify, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedNotify = TempValue; + } + + + // + // Check if the PEIM that was just dispatched resulted in any + // PPIs getting installed. If so, go process any dispatch + // level Notifies that match the installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // PpiListEnd (with InstallPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) { + TempValue = PrivateData->PpiData.PpiListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.PpiListEnd, + MAX_PPI_DESCRIPTORS-1, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedInstall = TempValue; + } + + if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) { + break; + } + } + return; +} + +VOID +DispatchNotify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index1; + INTN Index2; + EFI_GUID *SearchGuid; + EFI_GUID *CheckGuid; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Remember that Installs moves up and Notifies moves down. + // + for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) { + NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify; + + CheckGuid = NotifyDescriptor->Guid; + + for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { + SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid; + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) { + PEI_DEBUG ( + ( + PeiServices, + EFI_D_INFO, + "Notify: PPI Guid: %g, Peim notify entry point: %x\n", + SearchGuid, + NotifyDescriptor->Notify + ) + ); + NotifyDescriptor->Notify ( + (EFI_PEI_SERVICES**)PeiServices, + NotifyDescriptor, + (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi + ); + } + } + } + + return; +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/Reset.c b/Core/CORE_PEI/CORE_PEI_PI/Reset.c new file mode 100644 index 0000000..eb824f3 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Reset.c @@ -0,0 +1,76 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + Reset.c + +Abstract: + + Pei Core Reset System Support + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#include EFI_PPI_DEFINITION (Reset) +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +{ + EFI_STATUS Status; + PEI_RESET_PPI *ResetPpi; + + Status = PeiLocatePpi ( + PeiServices, + &gPeiResetPpiGuid, + 0, + NULL, + (VOID **)&ResetPpi + ); + + // + // LocatePpi returns EFI_NOT_FOUND on error + // + if (!EFI_ERROR (Status)) { + return ResetPpi->ResetSystem (PeiServices); + } +//*** AMI PORTING BEGIN ***// + //Report error + PEI_ERROR_CODE(PeiServices,PEI_RESET_NOT_AVAILABLE,EFI_ERROR_MINOR); +//*** AMI PORTING END *****// + return EFI_NOT_AVAILABLE_YET; +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/Security.c b/Core/CORE_PEI/CORE_PEI_PI/Security.c new file mode 100644 index 0000000..8d85b86 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Security.c @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + Security.c + +Abstract: + + EFI PEI Core Security services + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include EFI_PPI_DEFINITION (Security2) + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiSecurity2PpiGuid, + SecurityPpiNotifyCallback +}; + +VOID +InitializeSecurityServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +{ + if (OldCoreData == NULL) { + PeiNotifyPpi (&PrivateData->PS, &mNotifyList); + } + return; +} + + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Provide a callback for when the security PPI is installed. + +Arguments: + + PeiServices - The PEI core services table. + NotifyDescriptor - The descriptor for the notification event. + Ppi - Pointer to the PPI in question. + +Returns: + + EFI_SUCCESS - The function is successfully processed. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + // + // Get PEI Core private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // If there isn't a security PPI installed, use the one from notification + // + if (PrivateData->PrivateSecurityPpi == NULL) { + PrivateData->PrivateSecurityPpi = (EFI_PEI_SECURITY2_PPI *)Ppi; + } + return EFI_SUCCESS; +} + + +EFI_STATUS +VerifyPeim ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +{ + EFI_STATUS Status; + UINT32 AuthenticationStatus; + BOOLEAN DeferExection; + + // + // Set a default authentication state + // + AuthenticationStatus = 0; + + if (PrivateData->PrivateSecurityPpi == NULL) { + Status = EFI_NOT_FOUND; + } else { + // + // Check to see if the image is OK + // + Status = PrivateData->PrivateSecurityPpi->AuthenticationState ( + &PrivateData->PS, + PrivateData->PrivateSecurityPpi, + AuthenticationStatus, + VolumeHandle, + FileHandle, + &DeferExection + ); + if (DeferExection) { + Status = EFI_SECURITY_VIOLATION; + } + } + return Status; +} + + +EFI_STATUS +VerifyFv ( + IN EFI_PEI_FV_HANDLE VolumeHandle + ) +/*++ + +Routine Description: + + Verify a Firmware volume + +Arguments: + + CurrentFvAddress - Pointer to the current Firmware Volume under consideration + +Returns: + + EFI_SUCCESS - Firmware Volume is legal + EFI_SECURITY_VIOLATION - Firmware Volume fails integrity test + +--*/ +{ + // + // Right now just pass the test. Future can authenticate and/or check the + // FV-header or other metric for goodness of binary. + // + return EFI_SUCCESS; +} diff --git a/Core/CORE_PEI/CORE_PEI_PI/StatusCode.c b/Core/CORE_PEI/CORE_PEI_PI/StatusCode.c new file mode 100644 index 0000000..8df4058 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/StatusCode.c @@ -0,0 +1,94 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + StatusCode.c + +Abstract: + + Pei Core Status Code Support + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#include EFI_PPI_DEFINITION (StatusCode) + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + CodeType - Type of Status Code. + Value - Value to output for Status Code. + Instance - Instance Number of this status code. + CallerId - ID of the caller of this status code. + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +{ + EFI_STATUS Status; + PEI_STATUS_CODE_PPI *StatusCodePpi; + + + // + //Locate StatusCode Ppi. + // + Status = PeiLocatePpi ( + PeiServices, + &gPeiStatusCodePpiGuid, + 0, + NULL, + (VOID **)&StatusCodePpi + ); + + if (!EFI_ERROR (Status)) { + Status = StatusCodePpi->ReportStatusCode ( + PeiServices, + Type, + Value, + Instance, + CallerId, + Data + ); + return Status; + } + + + return EFI_NOT_AVAILABLE_YET; +} + + + diff --git a/Core/CORE_PEI/CORE_PEI_PI/dependency.c b/Core/CORE_PEI/CORE_PEI_PI/dependency.c new file mode 100644 index 0000000..f890a42 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/dependency.c @@ -0,0 +1,265 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + dependency.c + +Abstract: + + PEI Dispatcher Dependency Evaluator + + This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine + if a driver can be scheduled for execution. The criteria for + schedulability is that the dependency expression is satisfied. + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include "EfiDependency.h" +#include "Dependency.h" + +STATIC +BOOLEAN +IsPpiInstalled ( + IN EFI_PEI_SERVICES **PeiServices, + IN EVAL_STACK_ENTRY *Stack + ) +/*++ + +Routine Description: + + This routine determines if a PPI has been installed. + The truth value of a GUID is determined by if the PPI has + been published and can be queried from the PPI database. + +Arguments: + PeiServices - The PEI core services table. + Stack - Reference to EVAL_STACK_ENTRY that contains PPI GUID to check + +Returns: + + True if the PPI is already installed. + False if the PPI has yet to be installed. + +--*/ +{ + VOID *PeiInstance; + EFI_STATUS Status; + EFI_GUID PpiGuid; + + // + // If there is no GUID to evaluate, just return current result on stack. + // + if (Stack->Operator == NULL) { + return Stack->Result; + } + + // + // Copy the Guid into a locale variable so that there are no + // possibilities of alignment faults for cross-compilation + // environments such as Intel?Itanium(TM). + // + PeiCoreCopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID)); + + // + // Check if the PPI is installed. + // + Status = (**PeiServices).LocatePpi( + PeiServices, + &PpiGuid, // GUID + 0, // INSTANCE + NULL, // EFI_PEI_PPI_DESCRIPTOR + &PeiInstance // PPI + ); + + if (EFI_ERROR(Status)) { + return FALSE; + } + + return TRUE; +} + + +BOOLEAN +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +{ + EFI_STATUS Status; + DEPENDENCY_EXPRESSION_OPERAND *Iterator; + EVAL_STACK_ENTRY *StackPtr; + EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE]; + + Status = EFI_SUCCESS; + Iterator = DependencyExpression; + + StackPtr = &EvalStack[0]; + + while (TRUE) { + + switch (*(Iterator++)) { + + // + // For performance reason we put the frequently used items in front of + // the rarely used items + // + + case (EFI_DEP_PUSH): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return FALSE; + } + + // + // Push the pointer to the PUSH opcode operator (pointer to PPI GUID) + // We will evaluate if the PPI is insalled on the POP operation. + // + StackPtr->Operator = (VOID *) Iterator; + Iterator = Iterator + sizeof (EFI_GUID); + StackPtr++; + break; + + case (EFI_DEP_AND): + case (EFI_DEP_OR): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the two POPs for the AND operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did two POPs. + // + if (StackPtr < &EvalStack[2]) { + return FALSE; + } + + // + // Evaluate the first POPed operator only. If the operand is + // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the + // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE, + // we don't need to check the second operator, and the result will be + // evaluation of the POPed operator. Otherwise, don't POP the second + // operator since it will now evaluate to the final result on the + // next operand that causes a POP. + // + StackPtr--; + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_AND) { + if (!(IsPpiInstalled (PeiServices, StackPtr))) { + (StackPtr-1)->Result = FALSE; + (StackPtr-1)->Operator = NULL; + } + } else { + if (IsPpiInstalled (PeiServices, StackPtr)) { + (StackPtr-1)->Result = TRUE; + (StackPtr-1)->Operator = NULL; + } + } + break; + + case (EFI_DEP_END): + StackPtr--; + // + // Check to make sure EvalStack is balanced. If not, then there is + // an error in the dependency grammar, so return EFI_INVALID_PARAMETER. + // + if (StackPtr != &EvalStack[0]) { + return FALSE; + } + return IsPpiInstalled (PeiServices, StackPtr); + break; + + case (EFI_DEP_NOT): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the POP for the NOT operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did a POP. + // + if (StackPtr < &EvalStack[1]) { + return FALSE; + } + (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1)); + (StackPtr-1)->Operator = NULL; + break; + + case (EFI_DEP_TRUE): + case (EFI_DEP_FALSE): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return FALSE; + } + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_TRUE) { + StackPtr->Result = TRUE; + } else { + StackPtr->Result = FALSE; + } + StackPtr->Operator = NULL; + StackPtr++; + break; + + default: + // + // The grammar should never arrive here + // + return FALSE; + break; + } + } +} diff --git a/Core/CORE_PEI/CORE_PEI_PI/dependency.h b/Core/CORE_PEI/CORE_PEI_PI/dependency.h new file mode 100644 index 0000000..413c068 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/dependency.h @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 2004 - 2007, 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: + + dependency.h + +Abstract: + + This module contains data specific to dependency expressions + and local function prototypes. + +--*/ + +#ifndef _PEI_DEPENDENCY_H_ +#define _PEI_DEPENDENCY_H_ + +#define MAX_GRAMMAR_SIZE 256 + +// +// type definitions +// +typedef UINT8 DEPENDENCY_EXPRESSION_OPERAND; + +typedef struct { + BOOLEAN Result; + VOID *Operator; +} EVAL_STACK_ENTRY; + +#endif |