BlockIo Protocol devices specify 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 <[email protected]>
---
 MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c 
b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
index e7449f9..8cb08ce 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;
 }
 
-- 
2.4.3


_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to