audk/MdeModulePkg/Universal
Laszlo Ersek 4e39b75e7e MdeModulePkg/DiskIoDxe: fix source/destination pointer of overrun transfer
DiskIoCreateSubtaskList() may split the transfer into three segments:
- a leading segment, called underrun, which is the fractional, trailing
  subset of the first underlying block,
- a middle segment, which is an integral multiple of underlying blocks,
- a trailing segment, called overrun, which is the fractional, leading
  subset of the last underlying block.

This is an example read from the /EFI/BOOT/BOOTX64.EFI file, on the
RHEL-6.4 installation ISO (debug log enabled with EFI_D_BLKIO). The
underlying block size is 2048 bytes (IDE CD-ROM).

DiskIo: Create subtasks for task: Offset/BufferSize/Buffer = 0000000000004600/00002000/BD890018
  R:Lba/Offset/Length/WorkingBuffer/Buffer = 0000000000000008/00000600/00000200/BD90D000/BD890018
  R:Lba/Offset/Length/WorkingBuffer/Buffer = 000000000000000C/00000000/00000600/BD90D000/BD890218
  R:Lba/Offset/Length/WorkingBuffer/Buffer = 0000000000000009/00000000/00001800/00000000/BD890218

The first line corresponds to the underrun.
The second line corresponds to the overrun.
The third line corresponds to the middle segment.

In decimal:
- task: read 8192 bytes from offset 17920, storing it at BD890018
- underrun:
    - read block 8 [16384..18432) into the transfer area,
    - copy 512 bytes from offset 1536 of the transfer area to BD890018
      (target buffer offset 0, running total: 512)
- middle segment:
    - read blocks 9, 10, 11 [18432..24576) into the transfer area,
    - copy 6144 bytes from offset 0 of the transfer area to BD890218
      (target buffer offset 512, running total: 6656)
- overrun:
    - read block 12 [24576..26624) into the transfer area,
    - copy 1536 bytes from offset 0 of the transfer area to BD890218 (!!!)
      (target buffer offset 512 (!!!), running total 8192)

The values marked with (!!!) constitute the bug --
DiskIoCreateSubtaskList() doesn't take the size of the middle segment into
account when it calculates the destination (for reads) or source (for
writes) pointer for the overrun. This leads to data corruption.

When reading, data is copied form the transfer area to the target buffer
with

  CopyMem (Subtask->Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);

calls in DiskIo2OnReadWriteComplete() for nonblocking reads, and in
DiskIo2ReadWriteDisk() for blocking reads. Therefore it's enough to adjust
Subtask->Buffer when it is initialized. (See BD891A18 below.)

DiskIo: Create subtasks for task: Offset/BufferSize/Buffer = 0000000000004600/00002000/BD890018
  R:Lba/Offset/Length/WorkingBuffer/Buffer = 0000000000000008/00000600/00000200/BD90D000/BD890018
  R:Lba/Offset/Length/WorkingBuffer/Buffer = 000000000000000C/00000000/00000600/BD90D000/BD891A18
  R:Lba/Offset/Length/WorkingBuffer/Buffer = 0000000000000009/00000000/00001800/00000000/BD890218

The patched call to DiskIoCreateSubtask() is also executed for write
requests. The changed Subtask->Buffer initialization fixes the "overrun
half writes" in DiskIo2ReadWriteDisk() too:

  //
  // A sub task before this one should be a block read operation, causing
  // the WorkingBuffer filled with the entire one block data.
  //
  CopyMem (Subtask->WorkingBuffer + Subtask->Offset, Subtask->Buffer, Subtask->Length);

This code doubles for underrun and overrun half-writes. The patch doesn't
modify the underrun case.

If we're storing the overrun at the beginning of the pre-read last block
(which we're going to write out as a full block), then
- Subtask->Offset == 0,
- Subtask->Length == OverRun,
- the first byte *not* accessed in the source area is
  ((Buffer + UnderRunLength) + BufferSize) + OverRun.

Contributed-under: TianoCore Contribution Agreement 1.0

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14602 6f19259b-4bc3-4df7-8a09-765794883524
2013-08-26 02:47:41 +00:00
..
Acpi Fix the issue that FreePool is too early in FirmwarePerformanceDxe. 2013-05-27 05:45:35 +00:00
CapsulePei 1. Add debug init flag DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64 in Debug Agent Library. 2012-08-27 08:36:23 +00:00
CapsuleRuntimeDxe MdeModulePkg: Added ARM Aarch64 architecture support 2013-08-07 11:28:15 +00:00
Console Refine the validation for the input attribute before return. 2013-07-15 07:47:02 +00:00
DebugPortDxe MdeModulePkg/DebugPortDxe: Fixed the ordering of the EFI_DEBUGPORT_PROTOCOL entries 2012-03-15 15:27:18 +00:00
DebugSupportDxe MdeModulePkg: eliminate all implicit library dependencies for all modules in MdeModulePkg on PcdLib 2012-11-01 06:59:25 +00:00
DevicePathDxe Add 4 APIs to DevicePathLib: ConvertDeviceNodeToText, ConvertDevicePathToText, ConvertTextToDeviceNode and ConvertTextToDevicePath. 2013-07-26 03:00:21 +00:00
Disk MdeModulePkg/DiskIoDxe: fix source/destination pointer of overrun transfer 2013-08-26 02:47:41 +00:00
DisplayEngineDxe Refine the code logic for browser and display engine. 2013-08-12 04:49:48 +00:00
DriverSampleDxe Update all the code to consume the ConvertDevicePathToText, ConvertDevicePathNodeToText, ConvertTextToDevicePath and ConvertTextToDeviceNode APIs in DevicePathLib. 2013-07-26 03:14:08 +00:00
EbcDxe Add Missing invocations to VA_END() for VA_START(). 2012-02-01 06:06:08 +00:00
FaultTolerantWriteDxe MdeModulePkg: Add the alignment check for FTW spare area address and length, and add the check for PcdFlashNvStorageVariableSize <= PcdFlashNvStorageFtwSpareSize. 2013-07-11 08:15:47 +00:00
FaultTolerantWritePei MdeModulePkg FaultTolerantWritePei: Refine the code to avoid error report. 2013-07-11 01:40:10 +00:00
HiiDatabaseDxe Update comments for HiiConfigRoutine->ExtractConfig function, also update HiiConfigRoutine->ConfigToBlock/BlockToConfig to follow this new spec. 2013-08-23 05:53:04 +00:00
HiiResourcesSampleDxe Clean up the private GUID definition in module Level. 2011-09-18 12:21:01 +00:00
LegacyRegion2Dxe Enhance inf and dec file to follow specs. 2011-03-14 08:43:59 +00:00
LockBox/SmmLockBox Fix the TOCTOU issue of CommBufferSize itself for SMM communicate handler input. 2013-05-21 02:22:02 +00:00
MemoryTest MdeModulePkg: Add GenericMemoryTestDxe driver 2011-07-01 00:40:26 +00:00
Metronome Update the copyright notice format 2010-04-24 09:33:45 +00:00
MonotonicCounterRuntimeDxe Clean up the private GUID definition in module Level. 2011-09-18 12:21:01 +00:00
Network Update the structure of EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL, PXE_HW_UNDI, PXE_SW_UNDI to support greater than 256NICs in UNDI (Request by UEFI2.4 Mantis991). 2013-08-20 02:22:00 +00:00
PCD Adds ASSERT check in DxePcd driver when error status of read DynamicHii PCD is not EFI_NOT_FOUND to avoid the incorrect value is used. 2013-02-27 03:01:40 +00:00
PcatSingleSegmentPciCfg2Pei Update the copyright notice format 2010-04-24 09:33:45 +00:00
PlatformDriOverrideDxe Update all the code to consume the ConvertDevicePathToText, ConvertDevicePathNodeToText, ConvertTextToDevicePath and ConvertTextToDeviceNode APIs in DevicePathLib. 2013-07-26 03:14:08 +00:00
PrintDxe Update the copyright notice format 2010-04-24 09:33:45 +00:00
ReportStatusCodeRouter MdeModulePkg: eliminate all implicit library dependencies for all modules in MdeModulePkg on PcdLib 2012-11-01 06:59:25 +00:00
ResetSystemRuntimeDxe Add missing status code in several modules. 2012-10-30 04:23:40 +00:00
SecurityStubDxe Update SecurityStub SAP protocol to support SecureHandler and SecureHandler2 both. 2013-02-01 05:34:19 +00:00
SetupBrowserDxe Add some comments, clear describe the efi varstore type. 2013-08-23 05:54:33 +00:00
SmbiosDxe Fill SMBIOS BCD revision field. 2013-04-02 07:44:11 +00:00
StatusCodeHandler EFI_STATUS_CODE_DATA_MAX_SIZE is just for the maximum size of an EFI_DEBUG_INFO structure. Seemly, it is not suitable to be used in SerialStatusCodeHandler, so update SerialStatusCodeHandler to use MAX_DEBUG_MESSAGE_LENGTH (0x100) as the max printed string size to align with other DebugLib’s behavior. 2012-06-12 04:52:23 +00:00
Variable MdePkg/MdeModulePkg/SecurityPkg Variable: Forbid creation of non-spec variables in EFI_GLOBAL_VARIABLE namespace. 2013-08-19 05:16:45 +00:00
WatchdogTimerDxe Add debug print that the system is about to be reset. I was seeing watchtog timeouts in UnixPkg and they were hard to debug as gdb was exiting. This debug print should be useful in general. 2010-07-30 16:01:09 +00:00