summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2009-02-04 03:37:14 +0000
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2009-02-04 03:37:14 +0000
commit657abcff30450abc99d5f72d8872c272af96f704 (patch)
tree1b4c025a38bef500f5c888d6c066ae6aa313a4de /MdeModulePkg
parentae66d8de8713094c6dc8fad4abb3bf1339e2a817 (diff)
downloadedk2-platforms-657abcff30450abc99d5f72d8872c272af96f704.tar.xz
Enhance DxeCore to handle the all block sized allowed by the PI Specification and remove the assumption that the FV block size is always larger than the size of an FV Header.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7426 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Core/Dxe/FwVol/FwVol.c170
1 files changed, 151 insertions, 19 deletions
diff --git a/MdeModulePkg/Core/Dxe/FwVol/FwVol.c b/MdeModulePkg/Core/Dxe/FwVol/FwVol.c
index 5984b3f436..2829092e17 100644
--- a/MdeModulePkg/Core/Dxe/FwVol/FwVol.c
+++ b/MdeModulePkg/Core/Dxe/FwVol/FwVol.c
@@ -53,8 +53,114 @@ FV_DEVICE mFvDevice = {
// FFS helper functions
//
/**
- given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
- copy the volume header into it.
+ Read data from Firmware Block by FVB protocol Read.
+ The data may cross the multi block ranges.
+
+ @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to read data.
+ @param StartLba Pointer to StartLba.
+ On input, the start logical block index from which to read.
+ On output,the end logical block index after reading.
+ @param Offset Pointer to Offset
+ On input, offset into the block at which to begin reading.
+ On output, offset into the end block after reading.
+ @param DataSize Size of data to be read.
+ @param Data Pointer to Buffer that the data will be read into.
+
+ @retval EFI_SUCCESS Successfully read data from firmware block.
+ @retval others
+**/
+EFI_STATUS
+ReadFvbData (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
+ IN OUT EFI_LBA *StartLba,
+ IN OUT UINTN *Offset,
+ IN UINTN DataSize,
+ OUT UINT8 *Data
+ )
+{
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN BlockIndex;
+ UINTN ReadDataSize;
+ EFI_STATUS Status;
+
+ //
+ // Try read data in current block
+ //
+ BlockIndex = 0;
+ ReadDataSize = DataSize;
+ Status = Fvb->Read (Fvb, *StartLba, *Offset, &ReadDataSize, Data);
+ if (Status == EFI_SUCCESS) {
+ *Offset += DataSize;
+ return EFI_SUCCESS;
+ } else if (Status != EFI_BAD_BUFFER_SIZE) {
+ //
+ // other error will direct return
+ //
+ return Status;
+ }
+
+ //
+ // Data crosses the blocks, read data from next block
+ //
+ DataSize -= ReadDataSize;
+ Data += ReadDataSize;
+ *StartLba = *StartLba + 1;
+ while (DataSize > 0) {
+ Status = Fvb->GetBlockSize (Fvb, *StartLba, &BlockSize, &NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Read data from the crossing blocks
+ //
+ BlockIndex = 0;
+ while (BlockIndex < NumberOfBlocks && DataSize >= BlockSize) {
+ Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &BlockSize, Data);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data += BlockSize;
+ DataSize -= BlockSize;
+ BlockIndex ++;
+ }
+
+ //
+ // Data doesn't exceed the current block range.
+ //
+ if (DataSize < BlockSize) {
+ break;
+ }
+
+ //
+ // Data must be got from the next block range.
+ //
+ *StartLba += NumberOfBlocks;
+ }
+
+ //
+ // read the remaining data
+ //
+ if (DataSize > 0) {
+ Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &DataSize, Data);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Update Lba and Offset used by the following read.
+ //
+ *StartLba += BlockIndex;
+ *Offset = DataSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
+ copy the real length volume header into it.
@param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to
read the volume header
@@ -75,14 +181,17 @@ GetFwVolHeader (
EFI_STATUS Status;
EFI_FIRMWARE_VOLUME_HEADER TempFvh;
UINTN FvhLength;
+ EFI_LBA StartLba;
+ UINTN Offset;
UINT8 *Buffer;
-
-
+
//
- //Determine the real length of FV header
+ // Read the standard FV header
//
+ StartLba = 0;
+ Offset = 0;
FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
- Status = Fvb->Read (Fvb, 0, 0, &FvhLength, (UINT8 *)&TempFvh);
+ Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, (UINT8 *)&TempFvh);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -105,7 +214,7 @@ GetFwVolHeader (
//
FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER);
Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER);
- Status = Fvb->Read (Fvb, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvhLength, Buffer);
+ Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, Buffer);
if (EFI_ERROR (Status)) {
//
// Read failed so free buffer
@@ -191,6 +300,7 @@ FvCheck (
EFI_FFS_FILE_HEADER *FfsHeader;
UINT8 *CacheLocation;
UINTN LbaOffset;
+ UINTN HeaderSize;
UINTN Index;
EFI_LBA LbaIndex;
UINTN Size;
@@ -231,24 +341,44 @@ FvCheck (
BlockMap = FwVolHeader->BlockMap;
CacheLocation = FvDevice->CachedFv;
LbaIndex = 0;
- LbaOffset = FwVolHeader->HeaderLength;
+ LbaOffset = 0;
+ HeaderSize = FwVolHeader->HeaderLength;
while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
+ Index = 0;
+ Size = BlockMap->Length;
+ if (HeaderSize > 0) {
+ //
+ // Skip header size
+ //
+ for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) {
+ HeaderSize -= BlockMap->Length;
+ LbaIndex ++;
+ }
- for (Index = 0; Index < BlockMap->NumBlocks; Index ++) {
-
- Size = BlockMap->Length;
- if (Index == 0) {
- //
- // Cache does not include FV Header
- //
- Size -= LbaOffset;
+ //
+ // Check whether FvHeader is crossing the multi block range.
+ //
+ if (HeaderSize > BlockMap->Length) {
+ BlockMap++;
+ continue;
+ } else if (HeaderSize > 0) {
+ LbaOffset = HeaderSize;
+ Size = BlockMap->Length - HeaderSize;
+ HeaderSize = 0;
}
+ }
+
+ //
+ // read the FV data
+ //
+ for (; Index < BlockMap->NumBlocks; Index ++) {
Status = Fvb->Read (Fvb,
LbaIndex,
LbaOffset,
&Size,
CacheLocation
);
+
//
// Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length
//
@@ -256,14 +386,16 @@ FvCheck (
goto Done;
}
+ LbaIndex++;
+ CacheLocation += Size;
+
//
// After we skip Fv Header always read from start of block
//
LbaOffset = 0;
-
- LbaIndex++;
- CacheLocation += Size;
+ Size = BlockMap->Length;
}
+
BlockMap++;
}