1b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/** @file 2b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 3b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyCopyright (c) 2013-2015 Intel Corporation. 4b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 5b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis program and the accompanying materials 6b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyare licensed and made available under the terms and conditions of the BSD License 7b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneywhich accompanies this distribution. The full text of the license may be found at 8b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyhttp://opensource.org/licenses/bsd-license.php 9b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 10b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 13b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 14b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/ 15b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 16b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include "FwBlockService.h" 17b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 18b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyESAL_FWB_GLOBAL *mFvbModuleGlobal; 19b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 20b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = { 21b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FVB_DEVICE_SIGNATURE, // Signature 22b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 23b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // FV_DEVICE_PATH FvDevicePath 24b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 25b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 26b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 27b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 28b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney HARDWARE_DEVICE_PATH, 29b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney HW_MEMMAP_DP, 30b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 31b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), 32b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) 33b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 34b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney }, 35b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EfiMemoryMappedIO, 36b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (EFI_PHYSICAL_ADDRESS) 0, 37b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (EFI_PHYSICAL_ADDRESS) 0 38b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney }, 39b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 40b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney END_DEVICE_PATH_TYPE, 41b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney END_ENTIRE_DEVICE_PATH_SUBTYPE, 42b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 43b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney END_DEVICE_PATH_LENGTH, 44b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0 45b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 46b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 47b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney }, 48b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 49b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // UEFI_FV_DEVICE_PATH UefiFvDevicePath 50b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 51b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 52b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 53b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 54b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney MEDIA_DEVICE_PATH, 55b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney MEDIA_PIWG_FW_VOL_DP, 56b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 57b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), 58b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) 59b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 60b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney }, 61b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 0 } 62b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney }, 63b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 64b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney END_DEVICE_PATH_TYPE, 65b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney END_ENTIRE_DEVICE_PATH_SUBTYPE, 66b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 67b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney END_DEVICE_PATH_LENGTH, 68b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0 69b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 70b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 71b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney }, 72b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // Instance 73b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 74b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance 75b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 76b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney { 77b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbProtocolGetAttributes, 78b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbProtocolSetAttributes, 79b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbProtocolGetPhysicalAddress, 80b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbProtocolGetBlockSize, 81b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbProtocolRead, 82b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbProtocolWrite, 83b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbProtocolEraseBlocks, 84b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL 85b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 86b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}; 87b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 88b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyUINT32 mInSmmMode = 0; 89b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_SMM_SYSTEM_TABLE2* mSmst = NULL; 90b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 91b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID 92b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyPublishFlashDeviceInfo ( 93b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN SPI_INIT_TABLE *Found 94b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 95b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 96b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 97b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 98b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 99b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Publish info on found flash device to other drivers via PcdSpiFlashDeviceSize. 100b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 101b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 102b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Found - Pointer to entry in mSpiInitTable for found flash part. 103b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 104b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 105b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney None 106b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 107b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 108b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 109b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 110b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 111b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 112b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Publish Byte Size of found flash device. 113b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 114b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = PcdSet32S (PcdSpiFlashDeviceSize, (UINT32)(Found->BiosStartOffset + Found->BiosSize)); 115b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 116b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 117b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 118b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID 119b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbVirtualddressChangeEvent ( 120b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_EVENT Event, 121b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN VOID *Context 122b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 123b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 124b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 125b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 126b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 127b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Fixup internal data so that EFI and SAL can be call in virtual mode. 128b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Call the passed in Child Notify event and convert the mFvbModuleGlobal 129b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney date items to there virtual address. 130b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 131b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data 132b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common 133b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data. 134b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 135b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 136b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 137b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (Standard EFI notify event - EFI_EVENT_NOTIFY) 138b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 139b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 140b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 141b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney None 142b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 143b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 144b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 145b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 146b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN Index; 147b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 148b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]); 149b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 150b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 151b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Convert the base address of all the instances 152b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 153b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Index = 0; 154b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; 155b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney while (Index < mFvbModuleGlobal->NumFv) { 156b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 157b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]); 158b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 159b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // SpiWrite and SpiErase always use Physical Address instead of 160b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Virtual Address, even in Runtime. So we need not convert pointer 161b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // for FvWriteBase[FVB_VIRTUAL] 162b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 163b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // EfiConvertPointer (0, (VOID **) &FwhInstance->FvWriteBase[FVB_VIRTUAL]); 164b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 165b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = (EFI_FW_VOL_INSTANCE *) 166b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ( 167b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN) ((UINT8 *) FwhInstance) + FwhInstance->VolumeHeader.HeaderLength + 168b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 169b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 170b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Index++; 171b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 172b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 173b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]); 174b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 175b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Convert SPI_PROTOCOL instance for runtime 176b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 177b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->SpiProtocol); 178b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal); 179b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 180b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 181b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID 182b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbMemWrite8 ( 183b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT64 Dest, 184b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT8 Byte 185b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 186b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 187b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney MmioWrite8 ((UINTN)Dest, Byte); 188b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 189b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return ; 190b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 191b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 192b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 193b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGetFvbInstance ( 194b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 195b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 196b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT EFI_FW_VOL_INSTANCE **FwhInstance, 197b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 198b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 199b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 200b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 201b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 202b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Retrieves the physical address of a memory mapped FV 203b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 204b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 205b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance whose base address is going to be 206b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney returned 207b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 208b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 209b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure 210b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 211b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 212b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 213b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - Successfully returns 214b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found 215b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 216b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 217b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 218b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhRecord; 219b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 220b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (Instance >= Global->NumFv) { 221b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 222b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 223b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 224b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Find the right instance of the FVB private data 225b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 226b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhRecord = Global->FvInstance[Virtual]; 227b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney while (Instance > 0) { 228b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhRecord = (EFI_FW_VOL_INSTANCE *) 229b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ( 230b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength + 231b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 232b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 233b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance--; 234b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 235b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 236b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *FwhInstance = FwhRecord; 237b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 238b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 239b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 240b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 241b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 242b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbGetPhysicalAddress ( 243b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 244b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT EFI_PHYSICAL_ADDRESS *Address, 245b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 246b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 247b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 248b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 249b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 250b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 251b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Retrieves the physical address of a memory mapped FV 252b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 253b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 254b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance whose base address is going to be 255b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney returned 256b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS 257b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney that on successful return, contains the base address 258b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney of the firmware volume. 259b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 260b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 261b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 262b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 263b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 264b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - Successfully returns 265b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found 266b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 267b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 268b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 269b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 270b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 271b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 272b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = NULL; 273b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 274b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 275b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Find the right instance of the FVB private data 276b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 277b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 278b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 279b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *Address = FwhInstance->FvBase[Virtual]; 280b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 281b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 282b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 283b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 284b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 285b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbGetVolumeAttributes ( 286b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 287b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT EFI_FVB_ATTRIBUTES_2 *Attributes, 288b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 289b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 290b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 291b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 292b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 293b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 294b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Retrieves attributes, insures positive polarity of attribute bits, returns 295b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney resulting attributes in output parameter 296b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 297b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 298b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance whose attributes is going to be 299b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney returned 300b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Attributes - Output buffer which contains attributes 301b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 302b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 303b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 304b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 305b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 306b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - Successfully returns 307b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found 308b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 309b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 310b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 311b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 312b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 313b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 314b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = NULL; 315b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 316b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 317b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Find the right instance of the FVB private data 318b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 319b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 320b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 321b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *Attributes = FwhInstance->VolumeHeader.Attributes; 322b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 323b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 324b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 325b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 326b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 327b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbGetLbaAddress ( 328b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 329b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA Lba, 330b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT UINTN *LbaAddress, 331b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT UINTN *LbaWriteAddress, 332b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT UINTN *LbaLength, 333b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT UINTN *NumOfBlocks, 334b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 335b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 336b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 337b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 338b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 339b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 340b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Retrieves the starting address of an LBA in an FV 341b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 342b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 343b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance which the Lba belongs to 344b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Lba - The logical block address 345b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaAddress - On output, contains the physical starting address 346b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney of the Lba 347b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaWriteAddress - On output, contains the physical starting address 348b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney of the Lba for writing 349b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaLength - On output, contains the length of the block 350b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfBlocks - A pointer to a caller allocated UINTN in which the 351b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney number of consecutive blocks starting with Lba is 352b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney returned. All blocks in this range have a size of 353b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockSize 354b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 355b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 356b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 357b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 358b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 359b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - Successfully returns 360b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found 361b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 362b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 363b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 364b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 NumBlocks; 365b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 BlockLength; 366b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN Offset; 367b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_LBA StartLba; 368b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_LBA NextLba; 369b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 370b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FV_BLOCK_MAP_ENTRY *BlockMap; 371b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 372b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 373b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = NULL; 374b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 375b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 376b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Find the right instance of the FVB private data 377b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 378b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 379b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 380b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 381b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney StartLba = 0; 382b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Offset = 0; 383b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]); 384b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 385b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 386b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Parse the blockmap of the FV to find which map entry the Lba belongs to 387b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 388b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney while (TRUE) { 389b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBlocks = BlockMap->NumBlocks; 390b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockLength = BlockMap->Length; 391b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 392b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((NumBlocks == 0) || (BlockLength == 0)) { 393b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 394b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 395b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 396b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NextLba = StartLba + NumBlocks; 397b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 398b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 399b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // The map entry found 400b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 401b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (Lba >= StartLba && Lba < NextLba) { 402b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength); 403b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (LbaAddress) { 404b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *LbaAddress = FwhInstance->FvBase[Virtual] + Offset; 405b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 406b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 407b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (LbaWriteAddress) { 408b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *LbaWriteAddress = FwhInstance->FvWriteBase[Virtual] + Offset; 409b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 410b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 411b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (LbaLength) { 412b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *LbaLength = BlockLength; 413b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 414b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 415b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (NumOfBlocks) { 416b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *NumOfBlocks = (UINTN) (NextLba - Lba); 417b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 418b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 419b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 420b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 421b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 422b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney StartLba = NextLba; 423b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Offset = Offset + NumBlocks * BlockLength; 424b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockMap++; 425b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 426b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 427b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 428b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 429b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbReadBlock ( 430b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 431b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA Lba, 432b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN BlockOffset, 433b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN OUT UINTN *NumBytes, 434b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT8 *Buffer, 435b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 436b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 437b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 438b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 439b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 440b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 441b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Reads specified number of bytes into a buffer from the specified block 442b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 443b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 444b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance to be read from 445b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Lba - The logical block address to be read from 446b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockOffset - Offset into the block at which to begin reading 447b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes - Pointer that on input contains the total size of 448b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney the buffer. On output, it contains the total number 449b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney of bytes read 450b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Buffer - Pointer to a caller allocated buffer that will be 451b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney used to hold the data read 452b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 453b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 454b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 455b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 456b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 457b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The firmware volume was read successfully and 458b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney contents are in Buffer 459b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, 460b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes contains the total number of bytes returned 461b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney in Buffer 462b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state 463b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_ERROR - The block device is not functioning correctly and 464b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney could not be read 465b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL 466b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 467b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 468b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 469b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FVB_ATTRIBUTES_2 Attributes; 470b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaAddress; 471b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaLength; 472b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 473b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 474b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 475b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Check for invalid conditions 476b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 477b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((NumBytes == NULL) || (Buffer == NULL)) { 478b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 479b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 480b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 481b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (*NumBytes == 0) { 482b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 483b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 484b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 485b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, NULL, &LbaLength, NULL, Global, Virtual); 486b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 487b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 488b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 489b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 490b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Check if the FV is read enabled 491b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 492b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 493b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 494b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((Attributes & EFI_FVB2_READ_STATUS) == 0) { 495b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_ACCESS_DENIED; 496b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 497b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 498b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Perform boundary checks and adjust NumBytes 499b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 500b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (BlockOffset > LbaLength) { 501b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 502b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 503b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 504b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (LbaLength < (*NumBytes + BlockOffset)) { 505b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *NumBytes = (UINT32) (LbaLength - BlockOffset); 506b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = EFI_BAD_BUFFER_SIZE; 507b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 508b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 509b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney MmioReadBuffer8 (LbaAddress + BlockOffset, (UINTN) *NumBytes, Buffer); 510b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 511b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 512b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 513b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 514b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 515b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFlashFdWrite ( 516b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN WriteAddress, 517b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Address, 518b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN OUT UINTN *NumBytes, 519b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT8 *Buffer, 520b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN LbaLength 521b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 522b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 523b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 524b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 525b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Writes specified number of bytes from the input buffer to the address 526b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 527b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 528b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 529b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 530b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 531b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 532b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 533b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 534b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 535b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = EFI_SUCCESS; 536b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 537b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 538b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // TODO: Suggested that this code be "critical section" 539b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 540b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney WriteAddress -= ( PcdGet32 (PcdFlashAreaBaseAddress) ); 541b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (mInSmmMode == 0) { // !(EfiInManagementInterrupt ())) { 542b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SpiProtocol->Execute ( 543b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SpiProtocol, 544b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_OPCODE_WRITE_INDEX, // OpcodeIndex 545b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // PrefixOpcodeIndex 546b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // DataCycle 547b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // Atomic 548b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // ShiftOut 549b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney WriteAddress, // Address 550b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINT32) (*NumBytes), // Data Number 551b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Buffer, 552b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EnumSpiRegionBios 553b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 554b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 555b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 556b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 557b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SmmSpiProtocol, 558b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_OPCODE_WRITE_INDEX, // OpcodeIndex 559b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // PrefixOpcodeIndex 560b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // DataCycle 561b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // Atomic 562b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // ShiftOut 563b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney WriteAddress, // Address 564b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINT32) (*NumBytes), // Data Number 565b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Buffer, 566b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EnumSpiRegionBios 567b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 568b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 569b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 570b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney AsmWbinvd (); 571b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 572b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 573b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 574b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 575b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 576b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFlashFdErase ( 577b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN WriteAddress, 578b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Address, 579b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN LbaLength 580b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 581b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 582b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 583b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 584b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Erase a certain block from address LbaWriteAddress 585b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 586b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 587b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 588b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 589b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 590b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 591b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 592b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 593b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN NumBytes; 594b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 595b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes = LbaLength; 596b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 597b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney WriteAddress -= (PcdGet32 (PcdFlashAreaBaseAddress)); 598b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (mInSmmMode == 0 ) { // !(EfiInManagementInterrupt ())) { 599b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SpiProtocol->Execute ( 600b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SpiProtocol, 601b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_OPCODE_ERASE_INDEX, // OpcodeIndex 602b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // PrefixOpcodeIndex 603b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FALSE, // DataCycle 604b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // Atomic 605b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FALSE, // ShiftOut 606b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney WriteAddress, // Address 607b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // Data Number 608b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL, 609b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EnumSpiRegionBios // SPI_REGION_TYPE 610b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 611b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 612b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 613b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SmmSpiProtocol, 614b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_OPCODE_ERASE_INDEX, // OpcodeIndex 615b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // PrefixOpcodeIndex 616b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FALSE, // DataCycle 617b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // Atomic 618b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FALSE, // ShiftOut 619b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney WriteAddress, // Address 620b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // Data Number 621b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL, 622b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EnumSpiRegionBios // SPI_REGION_TYPE 623b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 624b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 625b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 626b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney AsmWbinvd (); 627b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 628b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 629b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 630b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 631b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 632b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbWriteBlock ( 633b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 634b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA Lba, 635b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN BlockOffset, 636b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN OUT UINTN *NumBytes, 637b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT8 *Buffer, 638b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 639b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 640b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 641b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 642b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 643b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 644b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Writes specified number of bytes from the input buffer to the block 645b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 646b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 647b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance to be written to 648b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Lba - The starting logical block index to write to 649b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockOffset - Offset into the block at which to begin writing 650b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes - Pointer that on input contains the total size of 651b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney the buffer. On output, it contains the total number 652b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney of bytes actually written 653b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Buffer - Pointer to a caller allocated buffer that contains 654b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney the source for the write 655b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 656b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 657b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 658b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 659b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 660b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The firmware volume was written successfully 661b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, 662b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes contains the total number of bytes 663b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney actually written 664b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 665b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_ERROR - The block device is not functioning correctly and 666b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney could not be written 667b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL 668b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 669b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 670b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 671b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FVB_ATTRIBUTES_2 Attributes; 672b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaAddress; 673b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaWriteAddress; 674b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaLength; 675b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 676b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 677b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS ReturnStatus; 678b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 679b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = NULL; 680b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 681b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 682b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Find the right instance of the FVB private data 683b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 684b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 685b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 686b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 687b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 688b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Writes are enabled in the init routine itself 689b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 690b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!FwhInstance->WriteEnabled) { 691b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_ACCESS_DENIED; 692b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 693b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 694b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Check for invalid conditions 695b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 696b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((NumBytes == NULL) || (Buffer == NULL)) { 697b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 698b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 699b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 700b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (*NumBytes == 0) { 701b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 702b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 703b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 704b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual); 705b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 706b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 707b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 708b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 709b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Check if the FV is write enabled 710b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 711b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 712b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 713b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { 714b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_ACCESS_DENIED; 715b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 716b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 717b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Perform boundary checks and adjust NumBytes 718b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 719b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (BlockOffset > LbaLength) { 720b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 721b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 722b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 723b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (LbaLength < (*NumBytes + BlockOffset)) { 724b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *NumBytes = (UINT32) (LbaLength - BlockOffset); 725b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = EFI_BAD_BUFFER_SIZE; 726b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 727b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 728b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ReturnStatus = FlashFdWrite ( 729b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaWriteAddress + BlockOffset, 730b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaAddress, 731b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes, 732b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Buffer, 733b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaLength 734b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 735b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (ReturnStatus)) { 736b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return ReturnStatus; 737b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 738b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 739b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 740b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 741b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 742b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 743b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbEraseBlock ( 744b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 745b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA Lba, 746b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 747b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 748b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 749b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 750b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 751b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 752b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Erases and initializes a firmware volume block 753b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 754b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 755b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance to be erased 756b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Lba - The logical block index to be erased 757b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 758b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 759b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 760b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 761b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 762b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The erase request was successfully completed 763b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 764b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_ERROR - The block device is not functioning correctly and 765b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney could not be written. Firmware device may have been 766b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney partially erased 767b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found 768b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 769b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 770b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 771b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 772b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FVB_ATTRIBUTES_2 Attributes; 773b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaAddress; 774b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaWriteAddress; 775b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 776b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaLength; 777b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 778b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN SectorNum; 779b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN Index; 780b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 781b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = NULL; 782b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 783b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 784b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Find the right instance of the FVB private data 785b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 786b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 787b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 788b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 789b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 790b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Writes are enabled in the init routine itself 791b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 792b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!FwhInstance->WriteEnabled) { 793b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_ACCESS_DENIED; 794b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 795b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 796b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Check if the FV is write enabled 797b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 798b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 799b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 800b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { 801b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_ACCESS_DENIED; 802b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 803b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 804b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Get the starting address of the block for erase. For debug reasons, 805b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // LbaWriteAddress may not be the same as LbaAddress. 806b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 807b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual); 808b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 809b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 810b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 811b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 812b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SectorNum = LbaLength / SPI_ERASE_SECTOR_SIZE; 813b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney for (Index = 0; Index < SectorNum; Index++){ 814b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = FlashFdErase ( 815b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaWriteAddress + Index * SPI_ERASE_SECTOR_SIZE, 816b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaAddress, 817b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_ERASE_SECTOR_SIZE 818b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 819b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (Status != EFI_SUCCESS){ 820b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney break; 821b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 822b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 823b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 824b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 825b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 826b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 827b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 828b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbEraseCustomBlockRange ( 829b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 830b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA StartLba, 831b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN OffsetStartLba, 832b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA LastLba, 833b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN OffsetLastLba, 834b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 835b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 836b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 837b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 838b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 839b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 840b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Erases and initializes a specified range of a firmware volume 841b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 842b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 843b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance to be erased 844b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney StartLba - The starting logical block index to be erased 845b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OffsetStartLba - Offset into the starting block at which to 846b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney begin erasing 847b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LastLba - The last logical block index to be erased 848b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OffsetStartLba - Offset into the last block at which to end erasing 849b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 850b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 851b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 852b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 853b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 854b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The firmware volume was erased successfully 855b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 856b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_ERROR - The block device is not functioning correctly and 857b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney could not be written. Firmware device may have been 858b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney partially erased 859b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found 860b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 861b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 862b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 863b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_LBA Index; 864b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaSize; 865b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN ScratchLbaSizeData; 866b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 867b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 868b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // First LBA. 869b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 870b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbGetLbaAddress (Instance, StartLba, NULL, NULL, &LbaSize, NULL, Global, Virtual); 871b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 872b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 873b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Use the scratch space as the intermediate buffer to transfer data 874b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Back up the first LBA in scratch space. 875b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 876b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); 877b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 878b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 879b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // erase now 880b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 881b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbEraseBlock (Instance, StartLba, Global, Virtual); 882b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ScratchLbaSizeData = OffsetStartLba; 883b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 884b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 885b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // write the data back to the first block 886b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 887b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (ScratchLbaSizeData > 0) { 888b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual); 889b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 890b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 891b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Middle LBAs 892b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 893b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (LastLba > (StartLba + 1)) { 894b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) { 895b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbEraseBlock (Instance, Index, Global, Virtual); 896b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 897b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 898b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 899b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Last LBAs, the same as first LBAs 900b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 901b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (LastLba > StartLba) { 902b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbGetLbaAddress (Instance, LastLba, NULL, NULL, &LbaSize, NULL, Global, Virtual); 903b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); 904b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbEraseBlock (Instance, LastLba, Global, Virtual); 905b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 906b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 907b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1); 908b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 909b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return FvbWriteBlock ( 910b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance, 911b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LastLba, 912b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (OffsetLastLba + 1), 913b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &ScratchLbaSizeData, 914b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global->FvbScratchSpace[Virtual], 915b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global, 916b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual 917b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 918b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 919b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 920b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 921b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbSetVolumeAttributes ( 922b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Instance, 923b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, 924b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ESAL_FWB_GLOBAL *Global, 925b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN BOOLEAN Virtual 926b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 927b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 928b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 929b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 930b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Modifies the current settings of the firmware volume according to the 931b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney input parameter, and returns the new setting of the volume 932b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 933b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 934b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Instance - The FV instance whose attributes is going to be 935b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney modified 936b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 937b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney containing the desired firmware volume settings. 938b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney On successful return, it contains the new settings 939b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney of the firmware volume 940b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Global - Pointer to ESAL_FWB_GLOBAL that contains all 941b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney instance data 942b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Virtual - Whether CPU is in virtual or physical mode 943b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 944b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 945b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - Successfully returns 946b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified 947b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are 948b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney in conflict with the capabilities as declared in the 949b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney firmware volume header 950b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 951b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 952b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 953b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 954b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FVB_ATTRIBUTES_2 OldAttributes; 955b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FVB_ATTRIBUTES_2 *AttribPtr; 956b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 Capabilities; 957b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 OldStatus; 958b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 NewStatus; 959b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 960b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 961b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = NULL; 962b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 963b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 964b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Find the right instance of the FVB private data 965b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 966b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 967b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 968b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 969b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes); 970b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OldAttributes = *AttribPtr; 971b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Capabilities = OldAttributes & EFI_FVB2_CAPABILITIES; 972b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OldStatus = OldAttributes & EFI_FVB2_STATUS; 973b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NewStatus = *Attributes & EFI_FVB2_STATUS; 974b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 975b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 976b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // If firmware volume is locked, no status bit can be updated 977b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 978b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (OldAttributes & EFI_FVB2_LOCK_STATUS) { 979b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (OldStatus ^ NewStatus) { 980b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_ACCESS_DENIED; 981b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 982b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 983b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 984b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Test read disable 985b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 986b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) { 987b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) { 988b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 989b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 990b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 991b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 992b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Test read enable 993b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 994b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) { 995b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (NewStatus & EFI_FVB2_READ_STATUS) { 996b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 997b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 998b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 999b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1000b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Test write disable 1001b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1002b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) { 1003b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) { 1004b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 1005b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1006b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1007b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1008b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Test write enable 1009b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1010b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) { 1011b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (NewStatus & EFI_FVB2_WRITE_STATUS) { 1012b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 1013b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1014b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1015b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1016b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Test lock 1017b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1018b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { 1019b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (NewStatus & EFI_FVB2_LOCK_STATUS) { 1020b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 1021b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1022b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1023b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1024b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); 1025b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *AttribPtr = (*AttribPtr) | NewStatus; 1026b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *Attributes = *AttribPtr; 1027b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1028b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 1029b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1030b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// 1031b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// FVB protocol APIs 1032b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// 1033b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1034b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 1035b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolGetPhysicalAddress ( 1036b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1037b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT EFI_PHYSICAL_ADDRESS *Address 1038b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1039b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1040b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1041b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1042b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1043b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Retrieves the physical address of the device. 1044b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1045b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1046b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1047b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This - Calling context 1048b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Address - Output buffer containing the address. 1049b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1050b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1051b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1052b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1053b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - Successfully returns 1054b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1055b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1056b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1057b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1058b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1059b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice = FVB_DEVICE_FROM_THIS (This); 1060b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1061b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ()); 1062b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1063b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1064b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1065b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolGetBlockSize ( 1066b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1067b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA Lba, 1068b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT UINTN *BlockSize, 1069b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT UINTN *NumOfBlocks 1070b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1071b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1072b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1073b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1074b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Retrieve the size of a logical block 1075b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1076b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1077b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This - Calling context 1078b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Lba - Indicates which block to return the size for. 1079b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockSize - A pointer to a caller allocated UINTN in which 1080b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney the size of the block is returned 1081b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfBlocks - a pointer to a caller allocated UINTN in which the 1082b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney number of consecutive blocks starting with Lba is 1083b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney returned. All blocks in this range have a size of 1084b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockSize 1085b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1086b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1087b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The firmware volume was read successfully and 1088b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney contents are in Buffer 1089b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1090b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1091b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1092b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1093b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1094b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice = FVB_DEVICE_FROM_THIS (This); 1095b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1096b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return FvbGetLbaAddress ( 1097b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice->Instance, 1098b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Lba, 1099b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL, 1100b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL, 1101b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BlockSize, 1102b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfBlocks, 1103b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal, 1104b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EfiGoneVirtual () 1105b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1106b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1107b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1108b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1109b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 1110b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolGetAttributes ( 1111b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1112b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT EFI_FVB_ATTRIBUTES_2 *Attributes 1113b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1114b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1115b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1116b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1117b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Retrieves Volume attributes. No polarity translations are done. 1118b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1119b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1120b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This - Calling context 1121b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Attributes - output buffer which contains attributes 1122b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1123b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1124b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - Successfully returns 1125b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1126b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1127b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1128b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1129b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1130b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice = FVB_DEVICE_FROM_THIS (This); 1131b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1132b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); 1133b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1134b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1135b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1136b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 1137b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolSetAttributes ( 1138b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1139b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes 1140b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1141b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1142b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1143b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1144b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Sets Volume attributes. No polarity translations are done. 1145b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1146b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1147b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This - Calling context 1148b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Attributes - output buffer which contains attributes 1149b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1150b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1151b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - Successfully returns 1152b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1153b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1154b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1155b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1156b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1157b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice = FVB_DEVICE_FROM_THIS (This); 1158b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1159b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); 1160b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1161b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1162b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1163b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 1164b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolEraseBlocks ( 1165b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1166b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ... 1167b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1168b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1169b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1170b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1171b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1172b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney The EraseBlock() function erases one or more blocks as denoted by the 1173b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney variable argument list. The entire parameter list of blocks must be verified 1174b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney prior to erasing any blocks. If a block is requested that does not exist 1175b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney within the associated firmware volume (it has a larger index than the last 1176b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney block of the firmware volume), the EraseBlock() function must return 1177b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. 1178b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1179b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1180b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This - Calling context 1181b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ... - Starting LBA followed by Number of Lba to erase. 1182b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney a -1 to terminate the list. 1183b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1184b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1185b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The erase request was successfully completed 1186b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 1187b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_ERROR - The block device is not functioning correctly and 1188b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney could not be written. Firmware device may have been 1189b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney partially erased 1190b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1191b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1192b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1193b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1194b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 1195b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN NumOfBlocks; 1196b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VA_LIST args; 1197b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_LBA StartingLba; 1198b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN NumOfLba; 1199b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 1200b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1201b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = NULL; 1202b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice = FVB_DEVICE_FROM_THIS (This); 1203b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1204b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ()); 1205b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1206b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1207b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfBlocks = FwhInstance->NumOfBlocks; 1208b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1209b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VA_START (args, This); 1210b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1211b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney do { 1212b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney StartingLba = VA_ARG (args, EFI_LBA); 1213b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (StartingLba == EFI_LBA_LIST_TERMINATOR) { 1214b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney break; 1215b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1216b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1217b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfLba = VA_ARG (args, UINT32); 1218b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1219b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1220b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Check input parameters 1221b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1222b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (NumOfLba == 0) { 1223b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VA_END (args); 1224b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 1225b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1226b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1227b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((StartingLba + NumOfLba) > NumOfBlocks) { 1228b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_INVALID_PARAMETER; 1229b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1230b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } while (TRUE); 1231b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1232b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VA_END (args); 1233b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1234b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VA_START (args, This); 1235b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney do { 1236b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney StartingLba = VA_ARG (args, EFI_LBA); 1237b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (StartingLba == EFI_LBA_LIST_TERMINATOR) { 1238b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney break; 1239b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1240b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1241b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfLba = VA_ARG (args, UINT32); 1242b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1243b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney while (NumOfLba > 0) { 1244b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ()); 1245b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 1246b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VA_END (args); 1247b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 1248b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1249b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1250b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney StartingLba++; 1251b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfLba--; 1252b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1253b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1254b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } while (TRUE); 1255b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1256b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VA_END (args); 1257b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1258b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 1259b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1260b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1261b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1262b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 1263b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolWrite ( 1264b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1265b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA Lba, 1266b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Offset, 1267b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN OUT UINTN *NumBytes, 1268b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT8 *Buffer 1269b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1270b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1271b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1272b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1273b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1274b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Writes data beginning at Lba:Offset from FV. The write terminates either 1275b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney when *NumBytes of data have been written, or when a block boundary is 1276b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney reached. *NumBytes is updated to reflect the actual number of bytes 1277b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney written. The write opertion does not include erase. This routine will 1278b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney attempt to write only the specified bytes. If the writes do not stick, 1279b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney it will return an error. 1280b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1281b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1282b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This - Calling context 1283b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Lba - Block in which to begin write 1284b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Offset - Offset in the block at which to begin write 1285b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes - On input, indicates the requested write size. On 1286b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney output, indicates the actual number of bytes written 1287b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Buffer - Buffer containing source data for the write. 1288b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1289b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1290b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The firmware volume was written successfully 1291b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, 1292b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes contains the total number of bytes 1293b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney actually written 1294b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 1295b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_ERROR - The block device is not functioning correctly and 1296b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney could not be written 1297b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL 1298b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1299b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1300b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1301b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1302b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1303b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1304b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice = FVB_DEVICE_FROM_THIS (This); 1305b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1306b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); 1307b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1308b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1309b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1310b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 1311b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolRead ( 1312b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1313b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_LBA Lba, 1314b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINTN Offset, 1315b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN OUT UINTN *NumBytes, 1316b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT8 *Buffer 1317b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1318b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1319b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1320b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1321b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1322b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Reads data beginning at Lba:Offset from FV. The Read terminates either 1323b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney when *NumBytes of data have been read, or when a block boundary is 1324b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney reached. *NumBytes is updated to reflect the actual number of bytes 1325b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney written. The write opertion does not include erase. This routine will 1326b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney attempt to write only the specified bytes. If the writes do not stick, 1327b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney it will return an error. 1328b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1329b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1330b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This - Calling context 1331b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Lba - Block in which to begin Read 1332b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Offset - Offset in the block at which to begin Read 1333b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes - On input, indicates the requested write size. On 1334b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney output, indicates the actual number of bytes Read 1335b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Buffer - Buffer containing source data for the Read. 1336b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1337b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1338b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The firmware volume was read successfully and 1339b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney contents are in Buffer 1340b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, 1341b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumBytes contains the total number of bytes returned 1342b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney in Buffer 1343b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state 1344b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_ERROR - The block device is not functioning correctly and 1345b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney could not be read 1346b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL 1347b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1348b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1349b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1350b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1351b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1352b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 1353b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1354b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice = FVB_DEVICE_FROM_THIS (This); 1355b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); 1356b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1357b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 1358b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1359b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1360b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1361b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyValidateFvHeader ( 1362b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader 1363b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1364b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1365b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1366b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1367b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Check the integrity of firmware volume header 1368b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1369b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1370b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwVolHeader - A pointer to a firmware volume header 1371b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1372b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1373b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SUCCESS - The firmware volume is consistent 1374b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV 1375b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1376b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1377b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1378b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT16 *Ptr; 1379b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT16 HeaderLength; 1380b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT16 Checksum; 1381b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1382b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1383b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Verify the header revision, header signature, length 1384b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Length of FvBlock cannot be 2**64-1 1385b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // HeaderLength cannot be an odd number 1386b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1387b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney #ifndef R864_BUILD 1388b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (((FwVolHeader->Revision != EFI_FVH_REVISION) && (FwVolHeader->Revision != EFI_FVH_REVISION)) || 1389b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney #else 1390b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if ((FwVolHeader->Revision != EFI_FVH_REVISION) || 1391b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney #endif 1392b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || 1393b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (FwVolHeader->FvLength == ((UINTN) -1)) || 1394b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ((FwVolHeader->HeaderLength & 0x01) != 0) 1395b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) { 1396b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_NOT_FOUND; 1397b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1398b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1399b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Verify the header checksum 1400b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1401b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney HeaderLength = (UINT16) (FwVolHeader->HeaderLength / 2); 1402b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Ptr = (UINT16 *) FwVolHeader; 1403b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Checksum = 0; 1404b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney while (HeaderLength > 0) { 1405b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Checksum = Checksum + (*Ptr); 1406b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Ptr++; 1407b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney HeaderLength--; 1408b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1409b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1410b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (Checksum != 0) { 1411b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_NOT_FOUND; 1412b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1413b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1414b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 1415b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1416b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1417b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1418b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGetFvbHeader ( 1419b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VOID **HobList, 1420b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader, 1421b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT EFI_PHYSICAL_ADDRESS *BaseAddress, 1422b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT BOOLEAN *WriteBack 1423b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1424b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1425b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 1426b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1427b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = EFI_SUCCESS; 1428b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *WriteBack = FALSE; 1429b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1430b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (*FwVolHeader == NULL) { 1431b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *BaseAddress = PcdGet32 (PcdFlashFvRecoveryBase); 1432b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else if (*FwVolHeader == (VOID *)(UINTN)PcdGet32 (PcdFlashFvRecoveryBase)) { 1433b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *BaseAddress = PcdGet32 (PcdFlashFvMainBase); 1434b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else if (*FwVolHeader == (VOID *)(UINTN)PcdGet32 (PcdFlashFvMainBase)) { 1435b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *BaseAddress = PcdGet32 (PcdFlashNvStorageVariableBase); 1436b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 1437b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_NOT_FOUND; 1438b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1439b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1440b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG((EFI_D_INFO, "Fvb base : %08x\n",*BaseAddress)); 1441b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1442b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (*BaseAddress); 1443b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = ValidateFvHeader (*FwVolHeader); 1444b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 1445b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1446b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Get FvbInfo 1447b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1448b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *WriteBack = TRUE; 1449b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1450b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbInfo (*BaseAddress, FwVolHeader); 1451b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG(( DEBUG_ERROR, "Through GetFvbInfo: %08x!\n",*BaseAddress)); 1452b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1453b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1454b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1455b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1456b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 1457b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1458b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1459b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1460b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1461b303605e1b7e113b4311daf161c6c3289350447bMichael KinneySmmSpiInit ( 1462b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VOID 1463b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1464b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1465b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT8 SpiStatus; 1466b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT8 FlashIndex; 1467b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT8 FlashID[3]; 1468b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 1469b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1470b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1471b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Obtain a handle for ICH SPI Protocol 1472b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1473b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT(mSmst != NULL); 1474b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (mFvbModuleGlobal->SmmSpiProtocol == NULL){ 1475b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SmmSpiProtocol); 1476b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR(Status); 1477b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1478b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1479b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // attempt to identify flash part and initialize spi table 1480b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1481b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) { 1482b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SmmSpiProtocol->Init ( 1483b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SmmSpiProtocol, 1484b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &(mSpiInitTable[FlashIndex]) 1485b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1486b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!EFI_ERROR (Status)) { 1487b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1488b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // read vendor/device IDs to check if flash device is supported 1489b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1490b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 1491b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SmmSpiProtocol, 1492b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_OPCODE_JEDEC_ID_INDEX, 1493b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_WREN_INDEX, 1494b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, 1495b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FALSE, 1496b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FALSE, 1497b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, 1498b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 3, 1499b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID, 1500b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EnumSpiRegionAll 1501b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1502b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!EFI_ERROR (Status)) { 1503b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1504b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) || 1505b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ((FlashID[0] == SPI_AT26DF321_ID1) && 1506b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1507b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) { 1508b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1509b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Supported SPI device found 1510b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1511b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG ( 1512b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ((EFI_D_INFO), 1513b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney "Smm Mode: Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1514b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[0], 1515b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[1], 1516b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[2]) 1517b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1518b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney break; 1519b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1520b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1521b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1522b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1523b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1524b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (FlashIndex >= EnumSpiFlashMax) { 1525b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = EFI_UNSUPPORTED; 1526b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG ( 1527b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (EFI_D_ERROR, 1528b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1529b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[0], 1530b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[1], 1531b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[2]) 1532b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1533b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1534b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1535b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1536b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SpiStatus = 0; 1537b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 1538b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SmmSpiProtocol, 1539b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex 1540b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1, // PrefixOpcodeIndex 1541b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // DataCycle 1542b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // Atomic 1543b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // ShiftOut 1544b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // Address 1545b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1, // Data Number 1546b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &SpiStatus, 1547b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EnumSpiRegionAll // SPI_REGION_TYPE 1548b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1549b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 1550b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1551b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1552b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1553b303605e1b7e113b4311daf161c6c3289350447bMichael KinneySmmSpiNotificationFunction ( 1554b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN CONST EFI_GUID *Protocol, 1555b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN VOID *Interface, 1556b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_HANDLE Handle 1557b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1558b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1559b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return SmmSpiInit(); 1560b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1561b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1562b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1563b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID 1564b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 1565b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGetFullDriverPath ( 1566b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_HANDLE ImageHandle, 1567b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_SYSTEM_TABLE *SystemTable, 1568b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OUT EFI_DEVICE_PATH_PROTOCOL **CompleteFilePath 1569b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1570b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1571b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1572b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1573b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1574b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Function is used to get the full device path for this driver. 1575b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1576b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1577b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1578b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ImageHandle - The loaded image handle of this driver. 1579b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SystemTable - The pointer of system table. 1580b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney CompleteFilePath - The pointer of returned full file path 1581b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1582b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1583b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1584b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney none 1585b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1586b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1587b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1588b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 1589b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 1590b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; 1591b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1592b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1593b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->HandleProtocol ( 1594b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ImageHandle, 1595b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiLoadedImageProtocolGuid, 1596b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID **) &LoadedImage 1597b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1598b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1599b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1600b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->HandleProtocol ( 1601b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LoadedImage->DeviceHandle, 1602b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiDevicePathProtocolGuid, 1603b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID *) &ImageDevicePath 1604b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1605b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1606b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1607b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney *CompleteFilePath = AppendDevicePath ( 1608b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ImageDevicePath, 1609b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LoadedImage->FilePath 1610b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1611b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1612b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return ; 1613b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 1614b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1615b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1616b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1617b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 1618b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbInitialize ( 1619b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_HANDLE ImageHandle, 1620b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_SYSTEM_TABLE *SystemTable 1621b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 1622b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++ 1623b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1624b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description: 1625b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This function does common initialization for FVB services 1626b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1627b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments: 1628b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1629b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns: 1630b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1631b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/ 1632b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 1633b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 1634b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_INSTANCE *FwhInstance; 1635b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; 1636b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FIRMWARE_VOLUME_HEADER *TempFwVolHeader; 1637b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VOID *HobList; 1638b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VOID *FirmwareVolumeHobList; 1639b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 BufferSize; 1640b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; 1641b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN LbaAddress; 1642b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BOOLEAN WriteEnabled; 1643b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BOOLEAN WriteLocked; 1644b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_HANDLE FwbHandle; 1645b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1646b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; 1647b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_PATH_PROTOCOL *FwbDevicePath; 1648b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_PATH_PROTOCOL *TempFwbDevicePath; 1649b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 MaxLbaSize; 1650b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_PHYSICAL_ADDRESS BaseAddress; 1651b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BOOLEAN WriteBack; 1652b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN NumOfBlocks; 1653b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN HeaderLength; 1654b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT8 SpiStatus; 1655b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT8 FlashIndex; 1656b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT8 FlashID[3]; 1657b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_DEVICE_PATH_PROTOCOL *CompleteFilePath; 1658b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT8 PrefixOpcodeIndex; 1659b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BOOLEAN InSmm; 1660b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SMM_BASE2_PROTOCOL *mSmmBase2; 1661b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_HANDLE Handle; 1662b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1663b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VOID *Registration; 1664b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_EVENT Event; 1665b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1666b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney CompleteFilePath = NULL; 1667b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney GetFullDriverPath (ImageHandle, SystemTable, &CompleteFilePath); 1668b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1669b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList); 1670b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1671b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1672b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // No FV HOBs found 1673b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1674b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1675b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1676b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1677b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1678b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Allocate runtime services data for global variable, which contains 1679b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // the private data of all firmware volume block instances 1680b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1681b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal = (ESAL_FWB_GLOBAL *)AllocateRuntimeZeroPool(sizeof (ESAL_FWB_GLOBAL )); 1682b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT(mFvbModuleGlobal); 1683b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mSmmBase2 = NULL; 1684b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->LocateProtocol ( 1685b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiSmmBase2ProtocolGuid, 1686b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL, 1687b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID **) &mSmmBase2 1688b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1689b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1690b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (mSmmBase2 == NULL) { 1691b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney InSmm = FALSE; 1692b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 1693b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mSmmBase2->InSmm (mSmmBase2, &InSmm); 1694b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mSmmBase2->GetSmstLocation (mSmmBase2, &mSmst); 1695b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1696b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1697b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1698b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!InSmm) { 1699b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mInSmmMode = 0; 1700b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1701b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Obtain a handle for ICH SPI Protocol 1702b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1703b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->LocateProtocol (&gEfiSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SpiProtocol); 1704b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1705b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1706b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1707b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // attempt to identify flash part and initialize spi table 1708b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1709b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) { 1710b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SpiProtocol->Init ( 1711b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SpiProtocol, 1712b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &(mSpiInitTable[FlashIndex]) 1713b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1714b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!EFI_ERROR (Status)) { 1715b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1716b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // read vendor/device IDs to check if flash device is supported 1717b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1718b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SpiProtocol->Execute ( 1719b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SpiProtocol, 1720b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_OPCODE_JEDEC_ID_INDEX, 1721b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_WREN_INDEX, 1722b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, 1723b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FALSE, 1724b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FALSE, 1725b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, 1726b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 3, 1727b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID, 1728b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EnumSpiRegionAll 1729b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1730b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!EFI_ERROR (Status)) { 1731b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1732b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) || 1733b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ((FlashID[0] == SPI_AT26DF321_ID1) && 1734b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1735b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) { 1736b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1737b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Supported SPI device found 1738b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1739b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG ( 1740b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ((EFI_D_INFO), 1741b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney "Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1742b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[0], 1743b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[1], 1744b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[2]) 1745b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1746b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1747b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney PublishFlashDeviceInfo (&mSpiInitTable[FlashIndex]); 1748b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney break; 1749b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1750b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1751b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1752b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1753b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1754b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (FlashIndex >= EnumSpiFlashMax) { 1755b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = EFI_UNSUPPORTED; 1756b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG ( 1757b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (DEBUG_ERROR, 1758b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1759b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[0], 1760b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[1], 1761b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FlashID[2]) 1762b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1763b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1764b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1765b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1766b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1767b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Unlock all regions by writing to status register 1768b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // This could be SPI device specific, need to follow the datasheet 1769b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // To write to Write Status Register the Spi PrefixOpcode needs to be: 1770b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 0 for Atmel parts 1771b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 0 for Intel parts 1772b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 0 for Macronix parts 1773b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 0 for Winbond parts 1774b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1 for SST parts 1775b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SpiStatus = 0; 1776b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (FlashID[0] == SPI_SST25VF016B_ID1) { 1777b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney PrefixOpcodeIndex = 1; 1778b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 1779b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney PrefixOpcodeIndex = 0; 1780b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1781b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mFvbModuleGlobal->SpiProtocol->Execute ( 1782b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->SpiProtocol, 1783b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex 1784b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney PrefixOpcodeIndex, // PrefixOpcodeIndex 1785b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // DataCycle 1786b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // Atomic 1787b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TRUE, // ShiftOut 1788b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, // Address 1789b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1, // Data Number 1790b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &SpiStatus, 1791b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EnumSpiRegionAll // SPI_REGION_TYPE 1792b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1793b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1794b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1795b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 1796b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mInSmmMode = 1; 1797b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1798b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SmmSpiProtocol); 1799b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR(Status)) { 1800b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Registration = NULL; 1801b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mSmst->SmmRegisterProtocolNotify ( 1802b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiSmmSpiProtocolGuid, 1803b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SmmSpiNotificationFunction, 1804b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &Registration 1805b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1806b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 1807b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = SmmSpiInit(); 1808b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1809b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1810b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1811b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1812b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1813b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Calculate the total size for all firmware volume block instances 1814b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1815b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BufferSize = 0; 1816b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FirmwareVolumeHobList = HobList; 1817b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwVolHeader = NULL; 1818b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney do { 1819b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, &BaseAddress, &WriteBack); 1820b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 1821b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney break; 1822b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1823b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1824b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (FwVolHeader) { 1825b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BufferSize += (FwVolHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)); 1826b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1827b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } while (TRUE); 1828b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1829b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1830b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Only need to allocate once. There is only one copy of physical memory for 1831b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // the private data of each FV instance. But in virtual mode or in physical 1832b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // mode, the address of the the physical memory may be different. 1833b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1834b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] = (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize); 1835b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT(mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]); 1836b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1837b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Make a virtual copy of the FvInstance pointer. 1838b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1839b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; 1840b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance; 1841b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1842b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->NumFv = 0; 1843b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FirmwareVolumeHobList = HobList; 1844b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TempFwVolHeader = NULL; 1845b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1846b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney MaxLbaSize = 0; 1847b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1848b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1849b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Fill in the private data of each firmware volume block instance 1850b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1851b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Foreach Fv HOB in the FirmwareVolumeHobList, loop 1852b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1853b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney do { 1854b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetFvbHeader (&FirmwareVolumeHobList, &TempFwVolHeader, &BaseAddress, &WriteBack); 1855b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 1856b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney break; 1857b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1858b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwVolHeader = TempFwVolHeader; 1859b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1860b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!FwVolHeader) { 1861b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney continue; 1862b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1863b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1864b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1865b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength); 1866b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwVolHeader = &(FwhInstance->VolumeHeader); 1867b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1868b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress; 1869b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress; 1870b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1871b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1872b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // FwhInstance->FvWriteBase may not be the same as FwhInstance->FvBase 1873b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1874b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance->FvWriteBase[FVB_PHYSICAL] = (UINTN) BaseAddress; 1875b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney WriteEnabled = TRUE; 1876b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1877b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1878b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Every pointer should have a virtual copy. 1879b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1880b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance->FvWriteBase[FVB_VIRTUAL] = FwhInstance->FvWriteBase[FVB_PHYSICAL]; 1881b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1882b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance->WriteEnabled = WriteEnabled; 1883b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL); 1884b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1885b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney LbaAddress = (UINTN) FwhInstance->FvWriteBase[0]; 1886b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfBlocks = 0; 1887b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney WriteLocked = FALSE; 1888b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1889b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (WriteEnabled) { 1890b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { 1891b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1892b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Get the maximum size of a block. The size will be used to allocate 1893b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // buffer for Scratch space, the intermediate buffer for FVB extension 1894b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // protocol 1895b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1896b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (MaxLbaSize < PtrBlockMapEntry->Length) { 1897b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney MaxLbaSize = PtrBlockMapEntry->Length; 1898b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1899b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1900b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; 1901b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1902b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1903b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Write back a healthy FV header 1904b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1905b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (WriteBack && (!WriteLocked)) { 1906b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1907b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = FlashFdErase ( 1908b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN) FwhInstance->FvWriteBase[0], 1909b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN) BaseAddress, 1910b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwVolHeader->BlockMap->Length 1911b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1912b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1913b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney HeaderLength = (UINTN) FwVolHeader->HeaderLength; 1914b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = FlashFdWrite ( 1915b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN) FwhInstance->FvWriteBase[0], 1916b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN) BaseAddress, 1917b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &HeaderLength, 1918b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINT8 *) FwVolHeader, 1919b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwVolHeader->BlockMap->Length 1920b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1921b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1922b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1923b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1924b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1925b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // The total number of blocks in the FV. 1926b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1927b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance->NumOfBlocks = NumOfBlocks; 1928b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1929b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1930b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // If the FV is write locked, set the appropriate attributes 1931b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1932b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (WriteLocked) { 1933b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1934b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // write disabled 1935b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1936b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance->VolumeHeader.Attributes &= ~EFI_FVB2_WRITE_STATUS; 1937b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1938b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // lock enabled 1939b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1940b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance->VolumeHeader.Attributes |= EFI_FVB2_LOCK_STATUS; 1941b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1942b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1943b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1944b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Allocate and initialize FVB Device in a runtime data buffer 1945b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1946b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice = AllocateRuntimeCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFvbDeviceTemplate); 1947b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT (FvbDevice); 1948b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1949b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice->Instance = mFvbModuleGlobal->NumFv; 1950b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->NumFv++; 1951b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1952b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1953b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH 1954b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1955b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (FwVolHeader->ExtHeaderOffset == 0) { 1956b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice->FvDevicePath.MemMapDevPath.StartingAddress = BaseAddress; 1957b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbDevice->FvDevicePath.MemMapDevPath.EndingAddress = BaseAddress + (FwVolHeader->FvLength - 1); 1958b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&FvbDevice->FvDevicePath; 1959b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 1960b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney CopyGuid ( 1961b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &FvbDevice->UefiFvDevicePath.FvDevPath.FvName, 1962b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (EFI_GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset) 1963b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1964b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&FvbDevice->UefiFvDevicePath; 1965b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 1966b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1967b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!InSmm) { 1968b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1969b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Find a handle with a matching device path that has supports FW Block protocol 1970b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1971b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TempFwbDevicePath = FwbDevicePath; 1972b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle); 1973b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 1974b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1975b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // LocateDevicePath fails so install a new interface and device path 1976b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1977b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwbHandle = NULL; 1978b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->InstallMultipleProtocolInterfaces ( 1979b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &FwbHandle, 1980b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiFirmwareVolumeBlockProtocolGuid, 1981b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &FvbDevice->FwVolBlockInstance, 1982b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiDevicePathProtocolGuid, 1983b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwbDevicePath, 1984b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL 1985b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1986b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1987b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) { 1988b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1989b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Device already exists, so reinstall the FVB protocol 1990b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 1991b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->HandleProtocol ( 1992b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwbHandle, 1993b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiFirmwareVolumeBlockProtocolGuid, 1994b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID **) &OldFwbInterface 1995b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 1996b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 1997b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 1998b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->ReinstallProtocolInterface ( 1999b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwbHandle, 2000b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiFirmwareVolumeBlockProtocolGuid, 2001b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney OldFwbInterface, 2002b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &FvbDevice->FwVolBlockInstance 2003b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 2004b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 2005b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 2006b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 2007b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 2008b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // There was a FVB protocol on an End Device Path node 2009b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 2010b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT (FALSE); 2011b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 2012b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 2013b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwbHandle = NULL; 2014b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = mSmst->SmmInstallProtocolInterface ( 2015b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &FwbHandle, 2016b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiSmmFirmwareVolumeBlockProtocolGuid, 2017b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_NATIVE_INTERFACE, 2018b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &FvbDevice->FwVolBlockInstance 2019b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 2020b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 2021b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 2022b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 2023b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FwhInstance = (EFI_FW_VOL_INSTANCE *) 2024b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ( 2025b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + 2026b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 2027b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 2028b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } while (TRUE); 2029b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 2030b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 2031b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Allocate for scratch space, an intermediate buffer for FVB extention 2032b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 2033b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 2034b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL] = AllocateRuntimeZeroPool (MaxLbaSize); 2035b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 2036b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT (mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]); 2037b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 2038b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]; 2039b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 2040b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (!InSmm) { 2041b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->CreateEventEx ( 2042b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EVT_NOTIFY_SIGNAL, 2043b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney TPL_NOTIFY, 2044b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FvbVirtualddressChangeEvent, 2045b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL, 2046b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiEventVirtualAddressChangeGuid, 2047b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &Event 2048b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 2049b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 2050b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 2051b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 2052b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Inform other platform drivers that SPI device discovered and 2053b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // SPI interface ready for use. 2054b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 2055b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Handle = NULL; 2056b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->InstallProtocolInterface ( 2057b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &Handle, 2058b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiSmmSpiReadyProtocolGuid, 2059b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_NATIVE_INTERFACE, 2060b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL 2061b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 2062b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 2063b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 2064b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 2065