summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2015-02-23 16:03:28 +0000
committerlersek <lersek@Edk2>2015-02-23 16:03:28 +0000
commit286c88bcce13dc88fffbcedd0fd2455790078e97 (patch)
tree9356e257bb5b8d0326109a9efe9eab82396c2caa
parent1cfa1957bb6979c6b7b30cd270cab44842639f56 (diff)
downloadedk2-platforms-286c88bcce13dc88fffbcedd0fd2455790078e97.tar.xz
ArmVirtualizationPkg/PciHostBridgeDxe: accommodate general address spaces
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
-rw-r--r--ArmPlatformPkg/ArmVirtualizationPkg/PciHostBridgeDxe/PciRootBridgeIo.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/PciHostBridgeDxe/PciRootBridgeIo.c b/ArmPlatformPkg/ArmVirtualizationPkg/PciHostBridgeDxe/PciRootBridgeIo.c
index ea895e8d68..8ff15734f4 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/PciHostBridgeDxe/PciRootBridgeIo.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -754,7 +754,7 @@ RootBridgeIoCheckParameter (
{
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;
- UINT64 MaxCount;
+ UINT32 Stride;
UINT64 Base;
UINT64 Limit;
@@ -792,7 +792,8 @@ RootBridgeIoCheckParameter (
//
// Check to see if Address is aligned
//
- if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
+ Stride = mInStride[Width];
+ if ((Address & (UINT64)(Stride - 1)) != 0) {
return EFI_UNSUPPORTED;
}
@@ -809,9 +810,6 @@ RootBridgeIoCheckParameter (
// Since Limit can be the maximum integer value supported by the CPU and Count
// can also be the maximum integer value supported by the CPU, this range
// check must be adjusted to avoid all oveflow conditions.
- //
- // The following form of the range check is equivalent but assumes that
- // Limit is of the form (2^n - 1).
//
if (OperationType == IoOperation) {
Base = PrivateData->IoBase;
@@ -838,20 +836,31 @@ RootBridgeIoCheckParameter (
Limit = MAX_PCI_REG_ADDRESS;
}
+ if (Limit < Address) {
+ return EFI_INVALID_PARAMETER;
+ }
+
if (Address < Base) {
return EFI_INVALID_PARAMETER;
}
- if (Count == 0) {
- if (Address > Limit) {
- return EFI_UNSUPPORTED;
- }
- } else {
- MaxCount = RShiftU64 (Limit, Width);
- if (MaxCount < (Count - 1)) {
+ //
+ // Base <= Address <= Limit
+ //
+ if (Address == 0 && Limit == MAX_UINT64) {
+ //
+ // 2^64 bytes are valid to transfer. With Stride == 1, that's simply
+ // impossible to reach in Count; with Stride in {2, 4, 8}, we can divide
+ // both 2^64 and Stride with 2.
+ //
+ if (Stride > 1 && Count > DivU64x32 (BIT63, Stride / 2)) {
return EFI_UNSUPPORTED;
}
- if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+ } else {
+ //
+ // (Limit - Address) does not wrap, and it is smaller than MAX_UINT64.
+ //
+ if (Count > DivU64x32 (Limit - Address + 1, Stride)) {
return EFI_UNSUPPORTED;
}
}