summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Linton <jeremy.linton@arm.com>2016-07-26 18:10:22 +0000
committerRyan Harkin <ryan.harkin@linaro.org>2017-01-11 12:18:41 +0000
commit0dc2ebe895568f989ccb87403b64ff7ee3a73bf4 (patch)
treeef1d672b1746cdfd39b6925d4fde57578cad4a0d
parent0e3eb40fcfb2cc9688d5541881ab3e0f6671b561 (diff)
MdeModulePkg, AtaBusDxe: Bounce buffer IO operations if unalignedarmlt-20170206-001armlt-20170116-001armlt-17.0117.01
BlockIo Protocol devices specify an a buffer alignment requirement in their media descriptors. This should be honored by users of the protocol. In cases where the user of the protocol (grub2 in this case) fail to correctly align their buffers, IO failures occur. Apparently this has been known for a while as numerous other BlockIo protocol providers in edk2 bounce IO operations rather than simply allowing them to fail. This patch adds bounce buffer logic to the AtaBusDxe. This logic is only triggered if the buffers are not correctly aligned. It assures that a wide range of adapters work regardless of buggy EFI applications. Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
-rw-r--r--MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
index cb7f1f031e..e405ec0d8d 100644
--- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
+++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
@@ -1038,6 +1038,7 @@ BlockIoReadWrite (
UINTN BlockSize;
UINTN NumberOfBlocks;
UINTN IoAlign;
+ VOID *IoBounceBuffer;
if (IsBlockIo2) {
Media = ((EFI_BLOCK_IO2_PROTOCOL *) This)->Media;
@@ -1078,7 +1079,18 @@ BlockIoReadWrite (
IoAlign = Media->IoAlign;
if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
- return EFI_INVALID_PARAMETER;
+ IoBounceBuffer=AllocateAlignedBuffer(AtaDevice,BufferSize);
+ if (IoBounceBuffer == NULL) {
+ //both bad parameter and out of resources..
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsWrite) {
+ CopyMem(IoBounceBuffer,Buffer,BufferSize);
+ }
+ }
+ else {
+ IoBounceBuffer=Buffer;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
@@ -1086,10 +1098,20 @@ BlockIoReadWrite (
//
// Invoke low level AtaDevice Access Routine.
//
- Status = AccessAtaDevice (AtaDevice, Buffer, Lba, NumberOfBlocks, IsWrite, Token);
+ Status = AccessAtaDevice (AtaDevice, IoBounceBuffer, Lba,
+ NumberOfBlocks, IsWrite, Token);
gBS->RestoreTPL (OldTpl);
+ // were we using a bounce buffer?
+ if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
+ if (!IsWrite) {
+ // for reads copy the data back to the original buffer
+ CopyMem(Buffer,IoBounceBuffer,BufferSize);
+ }
+ FreeAlignedBuffer(IoBounceBuffer,BufferSize);
+ }
+
return Status;
}