From 8b2982cd59533486c31f6effae45cdf7899209b8 Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Sat, 17 Mar 2018 07:41:44 +0800 Subject: PurleyOpenBoardPkg: Initial version. Cc: Isaac W Oram Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao Reviewed-by: Isaac W Oram --- .../Policy/S3NvramSave/S3NvramSave.c | 262 +++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c (limited to 'Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c') diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c new file mode 100644 index 0000000000..27d5efbeef --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c @@ -0,0 +1,262 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "S3NvramSave.h" +#include +#include +#include + +/** + + This function will retrieve the S3 data from HOBs produced by MRC + and will save it to NVRAM if the data is absent or different from + the previously saved data. + + @param VOID + + @retval VOID + +**/ +VOID +SaveS3StructToNvram ( + VOID + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + UINTN CurrentHobSize; + UINTN S3ChunkSize; + CHAR16 EfiMemoryConfigVariable[] = L"MemoryConfig0"; + EFI_HOB_GUID_TYPE *GuidHob = NULL; + VOID *HobData = NULL; + VOID *VariableData = NULL; + + UINTN CompressedDataSize; + UINT32 ScratchSize; + VOID *CompressedData = NULL; + VOID *Scratch = NULL; + EFI_DECOMPRESS_PROTOCOL *Decompress = NULL; + VOID *CompressedVariableData = NULL; + UINTN CompressedBufferSize; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock = NULL; + + // + // Get first S3 data HOB + // + GuidHob = GetFirstGuidHob (&gEfiMemoryConfigDataHobGuid); + + Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress); + DEBUG((DEBUG_INFO, "[SaveMemoryConfigEntryPoint] Locate Decompress protocol - %r\n", Status)); + if(EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock); + DEBUG((DEBUG_INFO, "[SaveMemoryConfigEntryPoint] Locate Variable Lock protocol - %r\n", Status)); + ASSERT_EFI_ERROR(Status); + + while (TRUE) { + if (GuidHob == NULL) { + break; + } + HobData = GET_GUID_HOB_DATA(GuidHob); + CurrentHobSize = GET_GUID_HOB_DATA_SIZE (GuidHob); + + DEBUG((EFI_D_INFO, " Current Hob Size(bytes) is: %d\n", CurrentHobSize)); + // + // Use the HOB data to save Memory Configuration Data + // + BufferSize = CurrentHobSize; + Status = gBS->AllocatePool ( + EfiBootServicesData, + BufferSize, + (VOID**)&VariableData + ); + + ASSERT (VariableData != NULL); + S3ChunkSize = MAX_HOB_ENTRY_SIZE / 8; + DEBUG((EFI_D_INFO, " S3ChunkSize Hob Size(bytes): %d\n", S3ChunkSize)); + + while (CurrentHobSize) { + if (S3ChunkSize > CurrentHobSize) { + S3ChunkSize = CurrentHobSize; + } + BufferSize = S3ChunkSize; + CompressedDataSize = 0; + ScratchSize = 0; + Status = gRT->GetVariable ( + EfiMemoryConfigVariable, + &gEfiMemoryConfigDataGuid, + NULL, + &CompressedDataSize, + NULL + ); + + if(Status == EFI_BUFFER_TOO_SMALL) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + CompressedDataSize, + (VOID**)&CompressedData + ); + ASSERT (Status == EFI_SUCCESS); + } + + if(!EFI_ERROR (Status)) + { + Status = gRT->GetVariable ( + EfiMemoryConfigVariable, + &gEfiMemoryConfigDataGuid, + NULL, + &CompressedDataSize, + CompressedData + ); + + if (!EFI_ERROR (Status)) { + Status = Decompress->GetInfo ( + Decompress, + CompressedData, + (UINT32)CompressedDataSize, + (UINT32*)&BufferSize, + &ScratchSize + ); + } + + if (!EFI_ERROR (Status)) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + ScratchSize, + (VOID**)&Scratch + ); + } + + if (!EFI_ERROR (Status)) { + Status = Decompress->Decompress ( + Decompress, + CompressedData, + (UINT32)CompressedDataSize, + VariableData, + (UINT32)BufferSize, + Scratch, + ScratchSize + ); + } + + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "Getting variables error: 0x%x\n", Status)); + ASSERT (Status == EFI_SUCCESS); + } + + if(Scratch != NULL) { + gBS->FreePool (Scratch); + Scratch = NULL; + } + } + + if(CompressedData != NULL) { + gBS->FreePool (CompressedData); + CompressedData = NULL; + } + + if ( (EFI_ERROR(Status)) || (CompareMem (HobData, VariableData, S3ChunkSize) != 0) ) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + BufferSize, + (VOID**)&CompressedVariableData + ); + ASSERT (CompressedVariableData != NULL); + if (Status == EFI_SUCCESS) { + CompressedBufferSize = BufferSize; + Status = Compress(HobData, S3ChunkSize, CompressedVariableData, &CompressedBufferSize); + if (Status == EFI_BUFFER_TOO_SMALL){ + gBS->FreePool(CompressedVariableData); + Status = gBS->AllocatePool( + EfiBootServicesData, + CompressedBufferSize, + (VOID**)&CompressedVariableData + ); + ASSERT (CompressedVariableData != NULL); + Status = Compress(HobData, S3ChunkSize, CompressedVariableData, &CompressedBufferSize); + } + if(Status == EFI_SUCCESS) { + Status = gRT->SetVariable ( + EfiMemoryConfigVariable, + &gEfiMemoryConfigDataGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + CompressedBufferSize, + CompressedVariableData + ); + } + if(CompressedVariableData != NULL) { + gBS->FreePool(CompressedVariableData); + CompressedVariableData = NULL; + } + } + + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "Set variable error. Status: 0x%x\n", Status)); + ASSERT_EFI_ERROR (Status); + } + } + // + // Lock the Memory Config Variable + // + Status = VariableLock->RequestToLock(VariableLock, EfiMemoryConfigVariable, &gEfiMemoryConfigDataGuid); + ASSERT_EFI_ERROR(Status); + HobData = (UINT8 *) (HobData) + S3ChunkSize; + + CurrentHobSize -= S3ChunkSize; + EfiMemoryConfigVariable[12]++; // Increment number in the string + } + // + // Get next S3 Config data hob, if none left, results NULL + // + GuidHob = GET_NEXT_HOB (GuidHob); // Increment to next HOB + GuidHob = GetNextGuidHob (&gEfiMemoryConfigDataHobGuid, GuidHob); // Now search for next MemConfig HOB + + if(VariableData != NULL) { + gBS->FreePool(VariableData); + VariableData = NULL; + } + } + + return; +} + +EFI_STATUS +EFIAPI +S3NvramSaveEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/** + + This is the main entry point of the S3 NVRAM Save module. + + @param ImageHandle - Handle for the image of this driver. + @param SystemTable - Pointer to the EFI System Table. + + @retval EFI_SUCCESS - Module launched successfully. + +**/ +{ + EFI_STATUS Status = EFI_SUCCESS; + + // + // Save the s3 strututre from MRC into NVRAM if needed + // + SaveS3StructToNvram(); + + return Status; + +} -- cgit v1.2.3