]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Enhance DxeCore to handle the all block sized allowed by the PI Specification and...
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 4 Feb 2009 03:37:14 +0000 (03:37 +0000)
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 4 Feb 2009 03:37:14 +0000 (03:37 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7426 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Core/Dxe/FwVol/FwVol.c

index 5984b3f436514207241ea1fe8cda835c81e80e5f..2829092e178cdc9ee3852c22b69f42ab23ffb469 100644 (file)
@@ -53,8 +53,114 @@ FV_DEVICE mFvDevice = {
 // FFS helper functions\r
 //\r
 /**\r
-  given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and\r
-  copy the volume header into it.\r
+  Read data from Firmware Block by FVB protocol Read. \r
+  The data may cross the multi block ranges.\r
+\r
+  @param  Fvb                   The FW_VOL_BLOCK_PROTOCOL instance from which to read data.\r
+  @param  StartLba              Pointer to StartLba.\r
+                                On input, the start logical block index from which to read.\r
+                                On output,the end logical block index after reading.\r
+  @param  Offset                Pointer to Offset\r
+                                On input, offset into the block at which to begin reading.\r
+                                On output, offset into the end block after reading.\r
+  @param  DataSize              Size of data to be read.\r
+  @param  Data                  Pointer to Buffer that the data will be read into.\r
+\r
+  @retval EFI_SUCCESS           Successfully read data from firmware block.\r
+  @retval others\r
+**/\r
+EFI_STATUS\r
+ReadFvbData (\r
+  IN     EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *Fvb,\r
+  IN OUT EFI_LBA                                *StartLba,\r
+  IN OUT UINTN                                  *Offset,\r
+  IN     UINTN                                  DataSize,\r
+  OUT    UINT8                                  *Data\r
+  )\r
+{\r
+  UINTN                       BlockSize;\r
+  UINTN                       NumberOfBlocks;\r
+  UINTN                       BlockIndex;\r
+  UINTN                       ReadDataSize;\r
+  EFI_STATUS                  Status;\r
+  \r
+  //\r
+  // Try read data in current block\r
+  //\r
+  BlockIndex   = 0;\r
+  ReadDataSize = DataSize;\r
+  Status = Fvb->Read (Fvb, *StartLba, *Offset, &ReadDataSize, Data);\r
+  if (Status == EFI_SUCCESS) {\r
+    *Offset  += DataSize;\r
+    return EFI_SUCCESS;\r
+  } else if (Status != EFI_BAD_BUFFER_SIZE) {\r
+    //\r
+    // other error will direct return\r
+    //\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Data crosses the blocks, read data from next block\r
+  //\r
+  DataSize -= ReadDataSize;\r
+  Data     += ReadDataSize;\r
+  *StartLba = *StartLba + 1;\r
+  while (DataSize > 0) {\r
+    Status = Fvb->GetBlockSize (Fvb, *StartLba, &BlockSize, &NumberOfBlocks);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Read data from the crossing blocks\r
+    //\r
+    BlockIndex = 0; \r
+    while (BlockIndex < NumberOfBlocks && DataSize >= BlockSize) {\r
+      Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &BlockSize, Data);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Data += BlockSize;\r
+      DataSize -= BlockSize;\r
+      BlockIndex ++;\r
+    }\r
+    \r
+    //\r
+    // Data doesn't exceed the current block range.\r
+    //\r
+    if (DataSize < BlockSize) {\r
+      break;\r
+    }\r
+    \r
+    //\r
+    // Data must be got from the next block range.\r
+    //\r
+    *StartLba += NumberOfBlocks;\r
+  }\r
+  \r
+  //\r
+  // read the remaining data\r
+  //\r
+  if (DataSize > 0) {\r
+    Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &DataSize, Data);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Update Lba and Offset used by the following read.\r
+  //\r
+  *StartLba += BlockIndex;\r
+  *Offset   = DataSize;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and\r
+  copy the real length volume header into it.\r
 \r
   @param  Fvb                   The FW_VOL_BLOCK_PROTOCOL instance from which to\r
                                 read the volume header\r
@@ -75,14 +181,17 @@ GetFwVolHeader (
   EFI_STATUS                  Status;\r
   EFI_FIRMWARE_VOLUME_HEADER  TempFvh;\r
   UINTN                       FvhLength;\r
+  EFI_LBA                     StartLba;\r
+  UINTN                       Offset;\r
   UINT8                       *Buffer;\r
-\r
-\r
+  \r
   //\r
-  //Determine the real length of FV header\r
+  // Read the standard FV header\r
   //\r
+  StartLba = 0;\r
+  Offset   = 0;\r
   FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
-  Status = Fvb->Read (Fvb, 0, 0, &FvhLength, (UINT8 *)&TempFvh);\r
+  Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, (UINT8 *)&TempFvh);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -105,7 +214,7 @@ GetFwVolHeader (
   //\r
   FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
   Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
-  Status = Fvb->Read (Fvb, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvhLength, Buffer);\r
+  Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, Buffer);\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // Read failed so free buffer\r
@@ -191,6 +300,7 @@ FvCheck (
   EFI_FFS_FILE_HEADER                   *FfsHeader;\r
   UINT8                                 *CacheLocation;\r
   UINTN                                 LbaOffset;\r
+  UINTN                                 HeaderSize;\r
   UINTN                                 Index;\r
   EFI_LBA                               LbaIndex;\r
   UINTN                                 Size;\r
@@ -231,24 +341,44 @@ FvCheck (
   BlockMap = FwVolHeader->BlockMap;\r
   CacheLocation = FvDevice->CachedFv;\r
   LbaIndex = 0;\r
-  LbaOffset = FwVolHeader->HeaderLength;\r
+  LbaOffset = 0;\r
+  HeaderSize = FwVolHeader->HeaderLength;\r
   while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
+    Index = 0;\r
+    Size  = BlockMap->Length;\r
+    if (HeaderSize > 0) {\r
+      //\r
+      // Skip header size\r
+      //\r
+      for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) {\r
+        HeaderSize -= BlockMap->Length;\r
+        LbaIndex ++;\r
+      }\r
 \r
-    for (Index = 0; Index < BlockMap->NumBlocks; Index ++) {\r
-\r
-      Size = BlockMap->Length;\r
-      if (Index == 0) {\r
-        //\r
-        // Cache does not include FV Header\r
-        //\r
-        Size -= LbaOffset;\r
+      //\r
+      // Check whether FvHeader is crossing the multi block range.\r
+      //\r
+      if (HeaderSize > BlockMap->Length) {\r
+        BlockMap++;\r
+        continue;\r
+      } else if (HeaderSize > 0) {\r
+        LbaOffset = HeaderSize;\r
+        Size = BlockMap->Length - HeaderSize;\r
+        HeaderSize = 0;\r
       }\r
+    }\r
+    \r
+    //\r
+    // read the FV data  \r
+    //\r
+    for (; Index < BlockMap->NumBlocks; Index ++) {\r
       Status = Fvb->Read (Fvb,\r
                       LbaIndex,\r
                       LbaOffset,\r
                       &Size,\r
                       CacheLocation\r
                       );\r
+\r
       //\r
       // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
       //\r
@@ -256,14 +386,16 @@ FvCheck (
         goto Done;\r
       }\r
 \r
+      LbaIndex++;\r
+      CacheLocation += Size;\r
+\r
       //\r
       // After we skip Fv Header always read from start of block\r
       //\r
       LbaOffset = 0;\r
-\r
-      LbaIndex++;\r
-      CacheLocation += Size;\r
+      Size  = BlockMap->Length;\r
     }\r
+\r
     BlockMap++;\r
   }\r
 \r