From a190687a9786279c67459a7f5162fe50a1d0d5d7 Mon Sep 17 00:00:00 2001 From: vanjeff Date: Thu, 28 Jun 2007 11:55:39 +0000 Subject: [PATCH] add ia32 and x64 direcotry for EdkFvbServiceLib updated module VariableRuntimeDxe git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2844 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Library/EdkFvbServiceLib/Ia32/Fvb.c | 610 +++++++++++++++++ .../Library/EdkFvbServiceLib/X64/Fvb.c | 614 ++++++++++++++++++ MdeModulePkg/MdeModulePkg.dsc | 4 +- .../Universal/VariableRuntimeDxe/Variable.c | 22 +- .../Universal/VariableRuntimeDxe/reclaim.c | 20 +- 5 files changed, 1247 insertions(+), 23 deletions(-) create mode 100644 MdeModulePkg/Library/EdkFvbServiceLib/Ia32/Fvb.c create mode 100644 MdeModulePkg/Library/EdkFvbServiceLib/X64/Fvb.c diff --git a/MdeModulePkg/Library/EdkFvbServiceLib/Ia32/Fvb.c b/MdeModulePkg/Library/EdkFvbServiceLib/Ia32/Fvb.c new file mode 100644 index 0000000000..3ec0d6f9eb --- /dev/null +++ b/MdeModulePkg/Library/EdkFvbServiceLib/Ia32/Fvb.c @@ -0,0 +1,610 @@ +/**@file + + Firmware Volume Block Protocol Runtime Abstraction + + mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the + index in the mFvbEntry array. This should be the same sequence as the FVB's + were described in the HOB. We have to remember the handle so we can tell if + the protocol has been reinstalled and it needs updateing. + + If you are using any of these lib functions.you must first call FvbInitialize (). + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "Fvb.h" + +// +// Event for Exit Boot Services Callback +// +STATIC EFI_EVENT mExitBootServicesEvent = NULL; + +// +// Lib will ASSERT if more FVB devices than this are added to the system. +// +STATIC FVB_ENTRY *mFvbEntry; +STATIC EFI_EVENT mFvbRegistration; +STATIC BOOLEAN mEfiFvbInitialized = FALSE; +STATIC UINTN mFvbCount; + +/** + Check whether an address is runtime memory or not. + + @param Address The Address being checked. + + @retval TRUE The address is runtime memory. + @retval FALSE The address is not runtime memory. +**/ +BOOLEAN +IsRuntimeMemory ( + IN VOID *Address + ) +{ + EFI_STATUS Status; + UINT8 TmpMemoryMap[1]; + UINTN MapKey; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + EFI_MEMORY_DESCRIPTOR *MemoryMapPtr; + BOOLEAN IsRuntime; + UINTN Index; + + IsRuntime = FALSE; + + // + // Get System MemoryMapSize + // + MemoryMapSize = 1; + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + // + // Enlarge space here, because we will allocate pool now. + // + MemoryMapSize += EFI_PAGE_SIZE; + Status = gBS->AllocatePool ( + EfiBootServicesData, + MemoryMapSize, + (VOID**)&MemoryMap + ); + ASSERT_EFI_ERROR (Status); + + // + // Get System MemoryMap + // + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + ASSERT_EFI_ERROR (Status); + + MemoryMapPtr = MemoryMap; + // + // Search the request Address + // + for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) { + if (((EFI_PHYSICAL_ADDRESS)(UINTN)Address >= MemoryMap->PhysicalStart) && + ((EFI_PHYSICAL_ADDRESS)(UINTN)Address < MemoryMap->PhysicalStart + + LShiftU64 (MemoryMap->NumberOfPages, EFI_PAGE_SHIFT))) { + // + // Found it + // + if (MemoryMap->Attribute & EFI_MEMORY_RUNTIME) { + IsRuntime = TRUE; + } + break; + } + // + // Get next item + // + MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize); + } + + // + // Done + // + gBS->FreePool (MemoryMapPtr); + + return IsRuntime; +} + +/** + Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is + reinstalled. + + @param Event The Event that is being processed + @param Context Event Context + +**/ +STATIC +VOID +EFIAPI +FvbNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE Handle; + UINTN Index; + UINTN UpdateIndex; + + while (TRUE) { + BufferSize = sizeof (Handle); + Status = gBS->LocateHandle ( + ByRegisterNotify, + &gEfiFirmwareVolumeBlockProtocolGuid, + mFvbRegistration, + &BufferSize, + &Handle + ); + if (EFI_ERROR (Status)) { + // + // Exit Path of While Loop.... + // + break; + } + + UpdateIndex = MAX_FVB_COUNT; + for (Index = 0; Index < mFvbCount; Index++) { + if (mFvbEntry[Index].Handle == Handle) { + // + // If the handle is already in the table just update the protocol + // + UpdateIndex = Index; + break; + } + } + + if (UpdateIndex == MAX_FVB_COUNT) { + // + // Use the next free slot for a new entry + // + UpdateIndex = mFvbCount++; + // + // Check the UpdateIndex whether exceed the maximum value. + // + ASSERT (UpdateIndex < MAX_FVB_COUNT); + mFvbEntry[UpdateIndex].Handle = Handle; + } + // + // The array does not have enough entries + // + ASSERT (UpdateIndex < MAX_FVB_COUNT); + + // + // Get the interface pointer and if it's ours, skip it + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &mFvbEntry[UpdateIndex].Fvb + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->HandleProtocol ( + Handle, + &gEfiFvbExtensionProtocolGuid, + (VOID **) &mFvbEntry[UpdateIndex].FvbExtension + ); + if (Status != EFI_SUCCESS) { + mFvbEntry[UpdateIndex].FvbExtension = NULL; + } + + // + // Check the FVB can be accessed in RUNTIME, The FVBs in FVB handle list comes + // from two way: + // 1) Dxe Core. (FVB information is transferred from FV HOB). + // 2) FVB driver. + // The FVB produced Dxe core is used for discoverying DXE driver and dispatch. These + // FVBs can only be accessed in boot time. + // FVB driver will discovery all FV in FLASH and these FVBs can be accessed in runtime. + // The FVB itself produced by FVB driver is allocated in runtime memory. So we can + // determine the what FVB can be accessed in RUNTIME by judging whether FVB itself is allocated + // in RUNTIME memory. + // + mFvbEntry[UpdateIndex].IsRuntimeAccess = IsRuntimeMemory (mFvbEntry[UpdateIndex].Fvb); + } +} + +/** + Convert all pointers in mFvbEntry after ExitBootServices. + + @param Event The Event that is being processed + @param Context Event Context + +**/ +VOID +EFIAPI +FvbVirtualAddressChangeNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + if (mFvbEntry != NULL) { + for (Index = 0; Index < MAX_FVB_COUNT; Index++) { + if (!mFvbEntry[Index].IsRuntimeAccess) { + continue; + } + + if (NULL != mFvbEntry[Index].Fvb) { + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetBlockSize); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetPhysicalAddress); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetAttributes); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->SetAttributes); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Read); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Write); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->EraseBlocks); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb); + } + + if (NULL != mFvbEntry[Index].FvbExtension) { + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension->EraseFvbCustomBlock); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension); + } + } + + EfiConvertPointer (0x0, (VOID **) &mFvbEntry); + } +} + +/** + Library constructor function entry. + + @param ImageHandle The handle of image who call this libary. + @param SystemTable The point of System Table. + + @retval EFI_SUCESS Sucess construct this library. + @retval Others Fail to contruct this libary. +**/ +EFI_STATUS +EFIAPI +FvbLibInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN Status; + mFvbCount = 0; + + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + (UINTN) sizeof (FVB_ENTRY) * MAX_FVB_COUNT, + (VOID *) &mFvbEntry + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (mFvbEntry, sizeof (FVB_ENTRY) * MAX_FVB_COUNT); + + EfiCreateProtocolNotifyEvent ( + &gEfiFirmwareVolumeBlockProtocolGuid, + TPL_CALLBACK, + FvbNotificationEvent, + NULL, + &mFvbRegistration + ); + + // + // Register SetVirtualAddressMap () notify function + // + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, + FvbVirtualAddressChangeNotifyEvent, + NULL, + &mExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + mEfiFvbInitialized = TRUE; + + return EFI_SUCCESS; +} + +// +// ============================================================================= +// The following functions wrap Fvb protocol in the Runtime Lib functions. +// The Instance translates into Fvb instance. The Fvb order defined by HOBs and +// thus the sequence of FVB protocol addition define Instance. +// +// EfiFvbInitialize () must be called before any of the following functions +// must be called. +// ============================================================================= +// + +/** + Reads specified number of bytes into a buffer from the specified block + + @param Instance The FV instance to be read from. + @param Lba The logical block address to be read from + @param Offset Offset into the block at which to begin reading + @param NumBytes Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + @param Buffer Pointer to a caller allocated buffer that will be + used to hold the data read + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to Read block + @retval Others Fail to read block +**/ +EFI_STATUS +EfiFvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->Read (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer); +} + +/** + Writes specified number of bytes from the input buffer to the block + + @param Instance The FV instance to be written to + @param Lba The starting logical block index to write to + @param Offset Offset into the block at which to begin writing + @param NumBytes Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + @param Buffer Pointer to a caller allocated buffer that contains + the source for the write + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to write block + @retval Others Fail to write block +**/ +EFI_STATUS +EfiFvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->Write (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer); +} + +/** + Erases and initializes a firmware volume block + + @param Instance The FV instance to be erased + @param Lba The logical block index to be erased + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to erase block + @retval Others Fail to erase block +**/ +EFI_STATUS +EfiFvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->EraseBlocks (mFvbEntry[Instance].Fvb, Lba, -1); +} + +/** + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + + @param Instance The FV instance whose attributes is going to be returned + @param Attributes Output buffer which contains attributes + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to get Fv attribute + @retval Others Fail to get Fv attribute +**/ +EFI_STATUS +EfiFvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetAttributes (mFvbEntry[Instance].Fvb, Attributes); +} + +/** + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + + @param Instance The FV instance whose attributes is going to be + modified + @param Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to set Fv attribute + @retval Others Fail to set Fv attribute +**/ +EFI_STATUS +EfiFvbSetVolumeAttributes ( + IN UINTN Instance, + IN EFI_FVB_ATTRIBUTES Attributes + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->SetAttributes (mFvbEntry[Instance].Fvb, &Attributes); +} + +/** + Retrieves the physical address of a memory mapped FV + + @param Instance The FV instance whose base address is going to be + returned + @param BaseAddress Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base address + of the firmware volume. + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to get physical address + @retval Others Fail to get physical address +**/ +EFI_STATUS +EfiFvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *BaseAddress + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress); +} + +/** + Retrieve the size of a logical block + + @param Instance The FV instance whose block size is going to be + returned + @param Lba Indicates which block to return the size for. + @param BlockSize A pointer to a caller allocated UINTN in which + the size of the block is returned + @param NumOfBlocks a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to get block size + @retval Others Fail to get block size +**/ +EFI_STATUS +EfiFvbGetBlockSize ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks); +} + +/** + Erases and initializes a specified range of a firmware volume + + @param Instance The FV instance to be erased + @param StartLba The starting logical block index to be erased + @param OffsetStartLba Offset into the starting block at which to + begin erasing + @param LastLba The last logical block index to be erased + @param OffsetLastLba Offset into the last block at which to end erasing + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to erase custom block range + @retval Others Fail to erase custom block range +**/ +EFI_STATUS +EfiFvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + if (!(mFvbEntry[Instance].FvbExtension)) { + return EFI_UNSUPPORTED; + } + + if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) { + return EFI_UNSUPPORTED; + } + + return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock ( + mFvbEntry[Instance].FvbExtension, + StartLba, + OffsetStartLba, + LastLba, + OffsetLastLba + ); +} diff --git a/MdeModulePkg/Library/EdkFvbServiceLib/X64/Fvb.c b/MdeModulePkg/Library/EdkFvbServiceLib/X64/Fvb.c new file mode 100644 index 0000000000..4ffc15c385 --- /dev/null +++ b/MdeModulePkg/Library/EdkFvbServiceLib/X64/Fvb.c @@ -0,0 +1,614 @@ +/**@file + + Firmware Volume Block Protocol Runtime Abstraction + + mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the + index in the mFvbEntry array. This should be the same sequence as the FVB's + were described in the HOB. We have to remember the handle so we can tell if + the protocol has been reinstalled and it needs updateing. + + If you are using any of these lib functions.you must first call FvbInitialize (). + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "Fvb.h" + +// +// Event for Exit Boot Services Callback +// +STATIC EFI_EVENT mExitBootServicesEvent = NULL; + +// +// Lib will ASSERT if more FVB devices than this are added to the system. +// +STATIC FVB_ENTRY *mFvbEntry; +STATIC EFI_EVENT mFvbRegistration; +STATIC BOOLEAN mEfiFvbInitialized = FALSE; +STATIC UINTN mFvbCount; + +/** + Check whether an address is runtime memory or not. + + @param Address The Address being checked. + + @retval TRUE The address is runtime memory. + @retval FALSE The address is not runtime memory. +**/ +BOOLEAN +IsRuntimeMemory ( + IN VOID *Address + ) +{ + EFI_STATUS Status; + UINT8 TmpMemoryMap[1]; + UINTN MapKey; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + EFI_MEMORY_DESCRIPTOR *MemoryMapPtr; + BOOLEAN IsRuntime; + UINTN Index; + + IsRuntime = FALSE; + + // + // Get System MemoryMapSize + // + MemoryMapSize = 1; + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + // + // Enlarge space here, because we will allocate pool now. + // + MemoryMapSize += EFI_PAGE_SIZE; + Status = gBS->AllocatePool ( + EfiBootServicesData, + MemoryMapSize, + (VOID**)&MemoryMap + ); + ASSERT_EFI_ERROR (Status); + + // + // Get System MemoryMap + // + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + ASSERT_EFI_ERROR (Status); + + MemoryMapPtr = MemoryMap; + // + // Search the request Address + // + for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) { + if (((EFI_PHYSICAL_ADDRESS)(UINTN)Address >= MemoryMap->PhysicalStart) && + ((EFI_PHYSICAL_ADDRESS)(UINTN)Address < MemoryMap->PhysicalStart + + LShiftU64 (MemoryMap->NumberOfPages, EFI_PAGE_SHIFT))) { + // + // Found it + // + if (MemoryMap->Attribute & EFI_MEMORY_RUNTIME) { + IsRuntime = TRUE; + } + break; + } + // + // Get next item + // + MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize); + } + + // + // Done + // + gBS->FreePool (MemoryMapPtr); + + return IsRuntime; +} + +/** + Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is + reinstalled. + + @param Event The Event that is being processed + @param Context Event Context + +**/ +STATIC +VOID +EFIAPI +FvbNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE Handle; + UINTN Index; + UINTN UpdateIndex; + + while (TRUE) { + BufferSize = sizeof (Handle); + Status = gBS->LocateHandle ( + ByRegisterNotify, + &gEfiFirmwareVolumeBlockProtocolGuid, + mFvbRegistration, + &BufferSize, + &Handle + ); + if (EFI_ERROR (Status)) { + // + // Exit Path of While Loop.... + // + break; + } + + UpdateIndex = MAX_FVB_COUNT; + for (Index = 0; Index < mFvbCount; Index++) { + if (mFvbEntry[Index].Handle == Handle) { + // + // If the handle is already in the table just update the protocol + // + UpdateIndex = Index; + break; + } + } + + if (UpdateIndex == MAX_FVB_COUNT) { + // + // Use the next free slot for a new entry + // + UpdateIndex = mFvbCount++; + // + // Check the UpdateIndex whether exceed the maximum value. + // + ASSERT (UpdateIndex < MAX_FVB_COUNT); + mFvbEntry[UpdateIndex].Handle = Handle; + } + // + // The array does not have enough entries + // + ASSERT (UpdateIndex < MAX_FVB_COUNT); + + // + // Get the interface pointer and if it's ours, skip it + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &mFvbEntry[UpdateIndex].Fvb + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->HandleProtocol ( + Handle, + &gEfiFvbExtensionProtocolGuid, + (VOID **) &mFvbEntry[UpdateIndex].FvbExtension + ); + if (Status != EFI_SUCCESS) { + mFvbEntry[UpdateIndex].FvbExtension = NULL; + } + + // + // Check the FVB can be accessed in RUNTIME, The FVBs in FVB handle list comes + // from two way: + // 1) Dxe Core. (FVB information is transferred from FV HOB). + // 2) FVB driver. + // The FVB produced Dxe core is used for discoverying DXE driver and dispatch. These + // FVBs can only be accessed in boot time. + // FVB driver will discovery all FV in FLASH and these FVBs can be accessed in runtime. + // The FVB itself produced by FVB driver is allocated in runtime memory. So we can + // determine the what FVB can be accessed in RUNTIME by judging whether FVB itself is allocated + // in RUNTIME memory. + // + mFvbEntry[UpdateIndex].IsRuntimeAccess = IsRuntimeMemory (mFvbEntry[UpdateIndex].Fvb); + } +} + +/** + Convert all pointers in mFvbEntry after ExitBootServices. + + @param Event The Event that is being processed + @param Context Event Context + +**/ +VOID +EFIAPI +FvbVirtualAddressChangeNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + if (mFvbEntry != NULL) { + for (Index = 0; Index < MAX_FVB_COUNT; Index++) { + if (!mFvbEntry[Index].IsRuntimeAccess) { + continue; + } + + if (NULL != mFvbEntry[Index].Fvb) { + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetBlockSize); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetPhysicalAddress); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetVolumeAttributes); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->SetVolumeAttributes); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Read); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Write); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->EraseBlocks); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb); + } + + if (NULL != mFvbEntry[Index].FvbExtension) { + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension->EraseFvbCustomBlock); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension); + } + } + + EfiConvertPointer (0x0, (VOID **) &mFvbEntry); + } +} + +/** + Library constructor function entry. + + @param ImageHandle The handle of image who call this libary. + @param SystemTable The point of System Table. + + @retval EFI_SUCESS Sucess construct this library. + @retval Others Fail to contruct this libary. +**/ +EFI_STATUS +EFIAPI +FvbLibInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN Status; + mFvbCount = 0; + + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + (UINTN) sizeof (FVB_ENTRY) * MAX_FVB_COUNT, + (VOID *) &mFvbEntry + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (mFvbEntry, sizeof (FVB_ENTRY) * MAX_FVB_COUNT); + + EfiCreateProtocolNotifyEvent ( + &gEfiFirmwareVolumeBlockProtocolGuid, + TPL_CALLBACK, + FvbNotificationEvent, + NULL, + &mFvbRegistration + ); + + // + // Register SetVirtualAddressMap () notify function + // + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, + FvbVirtualAddressChangeNotifyEvent, + NULL, + &mExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + mEfiFvbInitialized = TRUE; + + return EFI_SUCCESS; +} + +// +// ============================================================================= +// The following functions wrap Fvb protocol in the Runtime Lib functions. +// The Instance translates into Fvb instance. The Fvb order defined by HOBs and +// thus the sequence of FVB protocol addition define Instance. +// +// EfiFvbInitialize () must be called before any of the following functions +// must be called. +// ============================================================================= +// + +/** + Reads specified number of bytes into a buffer from the specified block + + @param Instance The FV instance to be read from. + @param Lba The logical block address to be read from + @param Offset Offset into the block at which to begin reading + @param NumBytes Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + @param Buffer Pointer to a caller allocated buffer that will be + used to hold the data read + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to Read block + @retval Others Fail to read block +**/ +EFI_STATUS +EfiFvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->Read (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer); +} + +/** + Writes specified number of bytes from the input buffer to the block + + @param Instance The FV instance to be written to + @param Lba The starting logical block index to write to + @param Offset Offset into the block at which to begin writing + @param NumBytes Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + @param Buffer Pointer to a caller allocated buffer that contains + the source for the write + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to write block + @retval Others Fail to write block +**/ +EFI_STATUS +EfiFvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->Write (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer); +} + +/** + Erases and initializes a firmware volume block + + @param Instance The FV instance to be erased + @param Lba The logical block index to be erased + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to erase block + @retval Others Fail to erase block +**/ +EFI_STATUS +EfiFvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->EraseBlocks (mFvbEntry[Instance].Fvb, Lba, -1); +} + +/** + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + + @param Instance The FV instance whose attributes is going to be returned + @param Attributes Output buffer which contains attributes + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to get Fv attribute + @retval Others Fail to get Fv attribute +**/ +EFI_STATUS +EfiFvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetVolumeAttributes (mFvbEntry[Instance].Fvb, Attributes); +} + +/** + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + + @param Instance The FV instance whose attributes is going to be + modified + @param Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to set Fv attribute + @retval Others Fail to set Fv attribute +**/ +EFI_STATUS +EfiFvbSetVolumeAttributes ( + IN UINTN Instance, + IN EFI_FVB_ATTRIBUTES Attributes + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->SetVolumeAttributes (mFvbEntry[Instance].Fvb, &Attributes); +} + +/** + Retrieves the physical address of a memory mapped FV + + @param Instance The FV instance whose base address is going to be + returned + @param BaseAddress Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base address + of the firmware volume. + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to get physical address + @retval Others Fail to get physical address +**/ +EFI_STATUS +EfiFvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *BaseAddress + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress); +} + +/** + Retrieve the size of a logical block + + @param Instance The FV instance whose block size is going to be + returned + @param Lba Indicates which block to return the size for. + @param BlockSize A pointer to a caller allocated UINTN in which + the size of the block is returned + @param NumOfBlocks a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to get block size + @retval Others Fail to get block size +**/ +EFI_STATUS +EfiFvbGetBlockSize ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks); +} + +/** + Erases and initializes a specified range of a firmware volume + + @param Instance The FV instance to be erased + @param StartLba The starting logical block index to be erased + @param OffsetStartLba Offset into the starting block at which to + begin erasing + @param LastLba The last logical block index to be erased + @param OffsetLastLba Offset into the last block at which to end erasing + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCESS Sucess to erase custom block range + @retval Others Fail to erase custom block range +**/ +EFI_STATUS +EfiFvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) { + return EFI_INVALID_PARAMETER; + } + + if (!(mFvbEntry[Instance].FvbExtension)) { + return EFI_UNSUPPORTED; + } + + if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) { + return EFI_UNSUPPORTED; + } + + return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock ( + mFvbEntry[Instance].FvbExtension, + StartLba, + OffsetStartLba, + LastLba, + OffsetLastLba + ); +} diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index cb5410bc2a..f63aaaae32 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -337,7 +337,7 @@ ${WORKSPACE}/MdeModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.inf ${WORKSPACE}/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.inf #${WORKSPACE}/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.inf - ${WORKSPACE}/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.inf + ${WORKSPACE}/MdeModulePkg/Universal/VariableRuntimeDxe/Variable.inf ${WORKSPACE}/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.inf ${WORKSPACE}/MdeModulePkg/Universal/WatchDogTimerDxe/WatchDogTimer.inf - ${WORKSPACE}/MdeModulePkg/Universal/VariablePei/Variable.inf +# ${WORKSPACE}/MdeModulePkg/Universal/VariablePei/Variable.inf diff --git a/MdeModulePkg/Universal/VariableRuntimeDxe/Variable.c b/MdeModulePkg/Universal/VariableRuntimeDxe/Variable.c index f6aa468e35..4322961630 100644 --- a/MdeModulePkg/Universal/VariableRuntimeDxe/Variable.c +++ b/MdeModulePkg/Universal/VariableRuntimeDxe/Variable.c @@ -134,15 +134,15 @@ Returns: UINTN BlockIndex2; UINTN LinearOffset; UINTN CurrWriteSize; - UINTN CurrWritePtr; - UINT8 *CurrBuffer; - EFI_LBA LbaNumber; - UINTN Size; - FRAMEWORK_EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - VARIABLE_STORE_HEADER *VolatileBase; - EFI_PHYSICAL_ADDRESS FvVolHdr; - EFI_PHYSICAL_ADDRESS DataPtr; - EFI_STATUS Status; + UINTN CurrWritePtr; + UINT8 *CurrBuffer; + EFI_LBA LbaNumber; + UINTN Size; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + VARIABLE_STORE_HEADER *VolatileBase; + EFI_PHYSICAL_ADDRESS FvVolHdr; + EFI_PHYSICAL_ADDRESS DataPtr; + EFI_STATUS Status; FwVolHeader = NULL; DataPtr = DataPtrIndex; @@ -152,7 +152,7 @@ Returns: // if (!Volatile) { EfiFvbGetPhysicalAddress (Instance, &FvVolHdr); - FwVolHeader = (FRAMEWORK_EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr); + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr); // // Data Pointer should point to the actual Address where data is to be // written @@ -198,7 +198,7 @@ Returns: return EFI_INVALID_PARAMETER; } - for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { + for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) { // // Check to see if the Variable Writes are spanning through multiple diff --git a/MdeModulePkg/Universal/VariableRuntimeDxe/reclaim.c b/MdeModulePkg/Universal/VariableRuntimeDxe/reclaim.c index 309d285e1d..3ee37367d5 100644 --- a/MdeModulePkg/Universal/VariableRuntimeDxe/reclaim.c +++ b/MdeModulePkg/Universal/VariableRuntimeDxe/reclaim.c @@ -95,13 +95,13 @@ GetLbaAndOffsetByAddress ( OUT UINTN *Offset ) { - EFI_STATUS Status; - EFI_HANDLE FvbHandle; - EFI_PHYSICAL_ADDRESS FvbBaseAddress; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - FRAMEWORK_EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry; - UINT32 LbaIndex; + EFI_STATUS Status; + EFI_HANDLE FvbHandle; + EFI_PHYSICAL_ADDRESS FvbBaseAddress; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry; + UINT32 LbaIndex; *Lba = (EFI_LBA) (-1); *Offset = 0; @@ -130,7 +130,7 @@ GetLbaAndOffsetByAddress ( return Status; } - FwVolHeader = (FRAMEWORK_EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress); + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress); // // Get the (LBA, Offset) of Address @@ -140,7 +140,7 @@ GetLbaAndOffsetByAddress ( // // BUGBUG: Assume one FV has one type of BlockLength // - FvbMapEntry = &FwVolHeader->FvBlockMap[0]; + FvbMapEntry = &FwVolHeader->BlockMap[0]; for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) { // @@ -149,7 +149,7 @@ GetLbaAndOffsetByAddress ( *Lba = LbaIndex - 1; *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1))); return EFI_SUCCESS; - } + } } } } -- 2.39.2