summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortsi <tsi>2008-06-21 18:11:55 +0000
committertsi <tsi>2008-06-21 18:11:55 +0000
commit3d71ca695647fd3027ed258ae4a6948e6c04a27d (patch)
treed1905cfd06c558f72569013d9664811eacae715c
parent1d4e3dd4066d90e5cb376caf3860348256474f4a (diff)
54. Fix possible reference to freed memory in HP ZX1 PCI chipset scan and
emulate configuration space more closely for its fake bridges (Marc La France).
-rw-r--r--programs/Xserver/hw/xfree86/CHANGELOG5
-rw-r--r--programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c80
2 files changed, 56 insertions, 29 deletions
diff --git a/programs/Xserver/hw/xfree86/CHANGELOG b/programs/Xserver/hw/xfree86/CHANGELOG
index 5dff911f4..e5c40c710 100644
--- a/programs/Xserver/hw/xfree86/CHANGELOG
+++ b/programs/Xserver/hw/xfree86/CHANGELOG
@@ -1,4 +1,7 @@
XFree86 4.7.99.20 (xx June 2008)
+ 54. Fix possible reference to freed memory in HP ZX1 PCI chipset scan and
+ emulate configuration space more closely for its fake bridges
+ (Marc La France).
53. Fix bug that caused the PCI scan to ignore bus segments that are known to
exist before the scan starts (Marc La France).
@@ -20763,4 +20766,4 @@ XFree86 3.0a (28 April 1994)
XFree86 3.0 (26 April 1994)
-$XFree86: xc/programs/Xserver/hw/xfree86/CHANGELOG,v 3.3966 2008/06/19 16:37:45 tsi Exp $
+$XFree86: xc/programs/Xserver/hw/xfree86/CHANGELOG,v 3.3967 2008/06/19 16:54:46 tsi Exp $
diff --git a/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c b/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c
index a464af3bf..3dd9be497 100644
--- a/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c
+++ b/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c,v 1.11tsi Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/zx1PCI.c,v 1.12tsi Exp $ */
/*
* Copyright (C) 2002-2003 The XFree86 Project, Inc.
* All rights reserved.
@@ -216,6 +216,7 @@ static int zx1_fakebus = -1;
static Bool zx1_hasvga = FALSE;
static pointer pZX1IoRes[8], pZX1MemRes[8]; /* Rope resources */
+static pciConfigPtr pFakePciBridge[8];
static unsigned int sbaid;
@@ -243,6 +244,11 @@ static CARD64 bot[MAX_RANGE], top[MAX_RANGE], msk[MAX_RANGE], siz[MAX_RANGE];
static INT8 *pDecode[MAX_RANGE];
static int nRange = 0;
+/* Forward declarations */
+static CARD32 zx1FakeReadLong(PCITAG tag, int offset);
+static void zx1FakeWriteLong(PCITAG tag, int offset, CARD32 val);
+static void zx1FakeSetBits(PCITAG tag, int offset, CARD32 mask, CARD32 bits);
+
/* Track a resource range and assign a granularity to it */
static void
SetRange(CARD64 base, CARD64 last, CARD8 width)
@@ -443,18 +449,48 @@ GetZX1BridgeResources(int bus,
}
/* The fake bus */
+static pciBusFuncs_t zx1FakeBusFuncs = {
+ zx1FakeReadLong,
+ zx1FakeWriteLong,
+ zx1FakeSetBits
+};
+
+static pciBusInfo_t zx1FakeBus = {
+ 0, /* configMech -- copied from bus 0 */
+ 0, /* numDevices -- copied from bus 0 */
+ FALSE, /* secondary */
+ 0, /* primary_bus -- dynamically set */
+#ifdef PowerMAX_OS
+ 0, /* ppc_io_base -- ignored */
+ 0, /* ppc_io_size -- ignored */
+#endif
+ &zx1FakeBusFuncs, /* funcs */
+ NULL, /* pciBusPriv -- none */
+ NULL, /* bridge -- dynamically set */
+};
+
static CARD32
zx1FakeReadLong(PCITAG tag, int offset)
{
- FatalError("zx1FakeReadLong(0x%lX, 0x%X) called\n",
- (unsigned long)tag, offset);
+ pciConfigPtr pPCI;
+
+ if ((offset < 0) || (offset & 3) || (offset >= zx1FakeBus.pciMaxOffset))
+ return PCI_NOT_FOUND;
+
+ if (!(pPCI = zx1FakeBus.bridge) || (tag != pPCI->tag)) {
+ if (!(pPCI = pFakePciBridge[PCI_DEV_FROM_TAG(tag) & 0x07]) ||
+ (tag != pPCI->tag))
+ return PCI_NOT_FOUND;
+ }
+
+ return pPCI->cfgspc.dwords[offset >> 2];
}
static void
zx1FakeWriteLong(PCITAG tag, int offset, CARD32 val)
{
- FatalError("zx1FakeWriteLong(0x%lX, 0x%X, 0x%08X) called\n",
- (unsigned long)tag, offset, val);
+ ErrorF("zx1FakeWriteLong(0x%lX, 0x%X, 0x%08X) called\n",
+ (unsigned long)tag, offset, val);
}
static void
@@ -468,26 +504,6 @@ zx1FakeSetBits(PCITAG tag, int offset, CARD32 mask, CARD32 bits)
zx1FakeWriteLong(tag, offset, val);
}
-static pciBusFuncs_t zx1FakeBusFuncs = {
- zx1FakeReadLong,
- zx1FakeWriteLong,
- zx1FakeSetBits
-};
-
-static pciBusInfo_t zx1FakeBus = {
- 0, /* configMech -- copied from bus 0 */
- 0, /* numDevices -- copied from bus 0 */
- FALSE, /* secondary */
- 0, /* primary_bus -- dynamically set */
-#ifdef PowerMAX_OS
- 0, /* ppc_io_base -- ignored */
- 0, /* ppc_io_size -- ignored */
-#endif
- &zx1FakeBusFuncs, /* funcs */
- NULL, /* pciBusPriv -- none */
- NULL, /* bridge -- dynamically set */
-};
-
/*
* This checks for, and validates, the presence of the ZX1 chipset, and sets
* pZX1mio to a non-NULL pointer accordingly. This function is called before
@@ -974,6 +990,12 @@ xf86PostScanZX1(void)
(void)memset(zx1_busnmpt, FALSE, sizeof(zx1_busnmpt));
pBusInfo = pciBusInfo[0];
+ /* Bus 0 might be deleted below; Save some of its data */
+ zx1BusFuncs = *(pBusInfo->funcs);
+ zx1FakeBus.configMech = pBusInfo->configMech;
+ zx1FakeBus.numDevices = pBusInfo->numDevices;
+ zx1FakeBus.pciMaxOffset = pBusInfo->pciMaxOffset;
+
/*
* Certain Linux kernels add fake PCI devices. Remove them to prevent any
* possible interference with our PCI validation.
@@ -1061,13 +1083,10 @@ xf86PostScanZX1(void)
}
/* Set up our extra bus functions */
- zx1BusFuncs = *(pBusInfo->funcs);
zx1BusFuncs.pciControlBridge = ControlZX1Bridge;
zx1BusFuncs.pciGetBridgeResources = GetZX1BridgeResources;
/* Set up our own fake bus to act as the root segment */
- zx1FakeBus.configMech = pBusInfo->configMech;
- zx1FakeBus.numDevices = pBusInfo->numDevices;
zx1FakeBus.primary_bus = zx1_fakebus;
pciBusInfo[zx1_fakebus] = &zx1FakeBus;
@@ -1079,6 +1098,7 @@ xf86PostScanZX1(void)
pPCI->busnum = zx1_fakebus;
/* pPCI->devnum = pPCI->funcnum = 0; */
pPCI->pci_device_vendor = sbaid;
+ pPCI->pci_status_command = PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE;
pPCI->pci_base_class = PCI_CLASS_BRIDGE;
/* pPCI->pci_sub_class = PCI_SUBCLASS_BRIDGE_HOST; */
pPCI->fakeDevice = TRUE;
@@ -1102,6 +1122,7 @@ xf86PostScanZX1(void)
/* Add a fake PCI-to-PCI bridge to represent each active rope */
for (i = 0; i < 8; i++) {
+ pFakePciBridge[i] = NULL;
if ((zx1_ropemap[i] != i) || (zx1_busno[i] > zx1_subno[i]) ||
!(pBusInfo = pciBusInfo[zx1_busno[i]]))
continue;
@@ -1114,13 +1135,16 @@ xf86PostScanZX1(void)
/* pPCI->funcnum = 0; */
pPCI->tag = PCI_MAKE_TAG(zx1_fakebus, pPCI->devnum, 0);
pPCI->pci_device_vendor = zx1_pciids[i];
+ pPCI->pci_status_command = PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE;
pPCI->pci_base_class = PCI_CLASS_BRIDGE;
pPCI->pci_sub_class = PCI_SUBCLASS_BRIDGE_PCI;
pPCI->pci_header_type = 1;
pPCI->pci_primary_bus_number = zx1_fakebus;
pPCI->pci_secondary_bus_number = zx1_busno[i];
pPCI->pci_subordinate_bus_number = zx1_subno[i];
+
pPCI->fakeDevice = TRUE;
+ pFakePciBridge[i] = pPCI;
pBusInfo->bridge = pPCI;
pBusInfo->secondary = TRUE;