/** @file @copyright Copyright 2012 - 2021 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include //notes //1: security variable and non-security variable may have different implementation //2. BP core variable sync may need update this module //3 different generation need to sync base on RP variable and Generation variable // this library to use a lightweight get variable service to patch variable hob before PEI variable service is ready /** Gets a vairable store header from FFS inserted by FCE Arguments: DefaultId - Specifies the type of defaults to retrieve. BoardId - Specifies the platform board of defaults to retrieve. @return The start address of VARIABLE_STORE_HEADER *. Null if cannot find it **/ VOID * FindDefaultHobinFfs ( IN UINT16 DefaultId, IN UINT16 BoardId ) { EFI_PEI_SERVICES **PeiServices; UINTN FvInstance; EFI_PEI_FV_HANDLE FvHandle; EFI_PEI_FILE_HANDLE *FfsHandle; EFI_FFS_FILE_HEADER *FfsHeader; UINT32 FileSize; EFI_COMMON_SECTION_HEADER *Section; UINT32 SectionLength; BOOLEAN DefaultFileIsFound; DEFAULT_DATA *DefaultData; DEFAULT_INFO *DefaultInfo; VARIABLE_STORE_HEADER *VarStoreHeader; UINT32 FFSSize = 0; // // Find the FFS file that stores all default data. // DefaultFileIsFound = FALSE; FvInstance = 0; FfsHandle = NULL; while ((PeiServicesFfsFindNextVolume (FvInstance, &FvHandle) == EFI_SUCCESS) && (!DefaultFileIsFound)) { FfsHandle = NULL; while (PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_FREEFORM, FvHandle, FfsHandle) == EFI_SUCCESS) { if (CompareGuid ((EFI_GUID *) FfsHandle, &gDefaultDataFileGuid)) { DefaultFileIsFound = TRUE; FfsHeader = (EFI_FFS_FILE_HEADER *) FfsHandle; break; } } FvInstance ++; } // // FFS file is not found. // if (!DefaultFileIsFound) { if (PcdGet32 (PcdFailSafeVarFfsSize) != 0 ){ // // try to search other FVS // FfsHeader = (EFI_FFS_FILE_HEADER *) AllocatePool (PcdGet32 (PcdFailSafeVarFfsSize)); if (FfsHeader == NULL) { return NULL; } if (EFI_SUCCESS != ReadFFSFile ((EFI_FIRMWARE_VOLUME_HEADER *) PcdGet32 (PcdFailSafeVarFvBase), gDefaultDataFileGuid, 0, FfsHeader, &FFSSize, FALSE)) { return NULL; } ASSERT (PcdGet32 (PcdFailSafeVarFfsSize) Size) & 0x00FFFFFF; while (((UINTN) Section < (UINTN) FfsHeader + FileSize) && (VarStoreHeader == NULL)) { DefaultData = (DEFAULT_DATA *) (Section + 1); DefaultInfo = &(DefaultData->DefaultInfo[0]); while ((UINTN) DefaultInfo < (UINTN) DefaultData + DefaultData->HeaderSize) { if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->BoardId == BoardId) { VarStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) DefaultData + DefaultData->HeaderSize); break; } DefaultInfo ++; } // // 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 = (SectionLength + 3) & (~3); ASSERT (SectionLength != 0); Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); } return VarStoreHeader; } /** This function searches the first instance of a HOB from the starting HOB pointer. Such HOB should satisfy two conditions: its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. If there does not exist such HOB from the starting HOB pointer, it will return NULL. Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () to extract the data section and its size info respectively. In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer unconditionally: it returns HobStart back if HobStart itself meets the requirement; caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. If Guid is NULL, then ASSERT(). If HobStart is NULL, then ASSERT(). @param Guid The GUID to match with in the HOB list. @param HobStart A pointer to a Guid. @return The next instance of the matched GUID HOB from the starting HOB. **/ VOID * InternalGetNextGuidHob ( IN CONST EFI_GUID *Guid, IN CONST VOID *HobStart ) { EFI_PEI_HOB_POINTERS GuidHob; GuidHob.Raw = (UINT8 *) HobStart; while (!END_OF_HOB_LIST (GuidHob)) { if (GuidHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION && CompareGuid (Guid, &GuidHob.Guid->Name)) { break; } GuidHob.Raw = GET_NEXT_HOB (GuidHob); } return GuidHob.Raw; } EFI_STATUS CreateDefaultVariableHob ( IN UINT16 DefaultId, IN UINT16 BoardId ) /*++ Description: This function finds the matched default data and create GUID hob for it. Arguments: DefaultId - Specifies the type of defaults to retrieve. BoardId - Specifies the platform board of defaults to retrieve. Returns: EFI_SUCCESS - The matched default data is found. EFI_NOT_FOUND - The matched default data is not found. EFI_OUT_OF_RESOURCES - No enough resource to create HOB. --*/ { VARIABLE_STORE_HEADER *VarStoreHeader; VARIABLE_STORE_HEADER *VarStoreHeaderHob; UINT8 *VarHobPtr; UINT8 *VarPtr; UINT32 VarDataOffset; UINT32 VarHobDataOffset; EFI_PEI_SERVICES **PeiServices; // // Get PeiService pointer // PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (); VarStoreHeader = (VARIABLE_STORE_HEADER*)FindDefaultHobinFfs( DefaultId, BoardId); // // Matched default data is not found. // if (VarStoreHeader == NULL) { return EFI_NOT_FOUND; } // // Create HOB to store defautl data so that Variable driver can use it. // Allocate more data for header alignment. // VarStoreHeaderHob = (VARIABLE_STORE_HEADER *) BuildGuidHob (&VarStoreHeader->Signature, VarStoreHeader->Size + HEADER_ALIGNMENT - 1); if (VarStoreHeaderHob == NULL) { // // No enough hob resource. // return EFI_OUT_OF_RESOURCES; } // // Copy variable storage header. // CopyMem (VarStoreHeaderHob, VarStoreHeader, sizeof (VARIABLE_STORE_HEADER)); // // Copy variable data. // VarPtr = (UINT8 *) HEADER_ALIGN ((UINTN) (VarStoreHeader + 1)); VarDataOffset = (UINT32) ((UINTN) VarPtr - (UINTN) VarStoreHeader); VarHobPtr = (UINT8 *) HEADER_ALIGN ((UINTN) (VarStoreHeaderHob + 1)); VarHobDataOffset = (UINT32) ((UINTN) VarHobPtr - (UINTN) VarStoreHeaderHob); CopyMem (VarHobPtr, VarPtr, VarStoreHeader->Size - VarDataOffset); // // Update variable size. // VarStoreHeaderHob->Size = VarStoreHeader->Size - VarDataOffset + VarHobDataOffset; // SyncSetupVariable(PeiServices,VarStoreHeaderHob,FALSE); return EFI_SUCCESS; }