]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmVirtualizationPkg/PciHostBridgeDxe: accommodate general address spaces
authorLaszlo Ersek <lersek@redhat.com>
Mon, 23 Feb 2015 16:03:28 +0000 (16:03 +0000)
committerlersek <lersek@Edk2>
Mon, 23 Feb 2015 16:03:28 +0000 (16:03 +0000)
The RootBridgeIoCheckParameter() function currently relies on the range
limit being of the form (2^n - 1). This assumption is not necessarily
true; handle the general case.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <Olivier.martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16901 6f19259b-4bc3-4df7-8a09-765794883524

ArmPlatformPkg/ArmVirtualizationPkg/PciHostBridgeDxe/PciRootBridgeIo.c

index ea895e8d68eb033b521400cd378d28ab5fe152ff..8ff15734f43e5954b94306a70a03ac5cf1962509 100644 (file)
@@ -754,7 +754,7 @@ RootBridgeIoCheckParameter (
 {\r
   PCI_ROOT_BRIDGE_INSTANCE                     *PrivateData;\r
   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  *PciRbAddr;\r
-  UINT64                                       MaxCount;\r
+  UINT32                                       Stride;\r
   UINT64                                       Base;\r
   UINT64                                       Limit;\r
 \r
@@ -792,7 +792,8 @@ RootBridgeIoCheckParameter (
   //\r
   // Check to see if Address is aligned\r
   //\r
-  if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {\r
+  Stride = mInStride[Width];\r
+  if ((Address & (UINT64)(Stride - 1)) != 0) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -809,9 +810,6 @@ RootBridgeIoCheckParameter (
   // Since Limit can be the maximum integer value supported by the CPU and Count \r
   // can also be the maximum integer value supported by the CPU, this range\r
   // check must be adjusted to avoid all oveflow conditions.\r
-  //   \r
-  // The following form of the range check is equivalent but assumes that \r
-  // Limit is of the form (2^n - 1).\r
   //\r
   if (OperationType == IoOperation) {\r
     Base = PrivateData->IoBase;\r
@@ -838,20 +836,31 @@ RootBridgeIoCheckParameter (
     Limit = MAX_PCI_REG_ADDRESS;\r
   }\r
 \r
+  if (Limit < Address) {\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   if (Address < Base) {\r
       return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (Count == 0) {\r
-    if (Address > Limit) {\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  } else {  \r
-    MaxCount = RShiftU64 (Limit, Width);\r
-    if (MaxCount < (Count - 1)) {\r
+  //\r
+  // Base <= Address <= Limit\r
+  //\r
+  if (Address == 0 && Limit == MAX_UINT64) {\r
+    //\r
+    // 2^64 bytes are valid to transfer. With Stride == 1, that's simply\r
+    // impossible to reach in Count; with Stride in {2, 4, 8}, we can divide\r
+    // both 2^64 and Stride with 2.\r
+    //\r
+    if (Stride > 1 && Count > DivU64x32 (BIT63, Stride / 2)) {\r
       return EFI_UNSUPPORTED;\r
     }\r
-    if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {\r
+  } else {\r
+    //\r
+    // (Limit - Address) does not wrap, and it is smaller than MAX_UINT64.\r
+    //\r
+    if (Count > DivU64x32 (Limit - Address + 1, Stride)) {\r
       return EFI_UNSUPPORTED;\r
     }\r
   }\r