+{\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