summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}