diff options
author | Tristan Corrick <tristan@corrick.kiwi> | 2018-12-06 22:47:42 +1300 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2019-01-03 18:10:48 +0000 |
commit | 05b75241565ae91d0b8ee8b45eb2d8ac55291297 (patch) | |
tree | 4213618939857f48da995710490e9e447667979b /src/southbridge/intel/lynxpoint | |
parent | 09a5323480fae9ad20075751cad9d1f25d61a3ab (diff) |
sb/intel/lynxpoint/pcie.c: Add more checks for NULL pointers
If PCIe root port `n` is disabled, then `rpc.ports[n - 1]` remains NULL.
The existing Lynx Point systems probably don't end up dereferencing
NULL pointers this way. However, it might occur on a system using
Flexible I/O to remap PCIe root ports to other functions.
Tested on an ASRock H81M-HDS and an Acer C720 (Google Peppy). No issues
presented themselves.
Change-Id: I2c22fa36217766c2c4d6e8046f99989063066b16
Signed-off-by: Tristan Corrick <tristan@corrick.kiwi>
Reviewed-on: https://review.coreboot.org/c/30079
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/southbridge/intel/lynxpoint')
-rw-r--r-- | src/southbridge/intel/lynxpoint/pcie.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/src/southbridge/intel/lynxpoint/pcie.c b/src/southbridge/intel/lynxpoint/pcie.c index 750b53395c..695abf2605 100644 --- a/src/southbridge/intel/lynxpoint/pcie.c +++ b/src/southbridge/intel/lynxpoint/pcie.c @@ -14,6 +14,8 @@ * GNU General Public License for more details. */ +#include <assert.h> +#include <commonlib/helpers.h> #include <console/console.h> #include <device/device.h> #include <device/pci.h> @@ -22,6 +24,8 @@ #include <device/pci_ops.h> #include "pch.h" #include <southbridge/intel/common/gpio.h> +#include <stddef.h> +#include <stdint.h> #define MAX_NUM_ROOT_PORTS 8 @@ -68,6 +72,16 @@ static inline int root_port_number(struct device *dev) return PCI_FUNC(dev->path.pci.devfn) + 1; } +static bool is_rp_enabled(int rp) +{ + ASSERT(rp > 0 && rp <= ARRAY_SIZE(rpc.ports)); + + if (rpc.ports[rp - 1] == NULL) + return false; + + return rpc.ports[rp - 1]->enabled; +} + static void root_port_config_update_gbe_port(void) { /* Is the Gbe Port enabled? */ @@ -163,7 +177,7 @@ static void pch_pcie_device_set_func(int index, int pci_func) /* Determine the new devfn for this port */ new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, pci_func); - if (dev->path.pci.devfn != new_devfn) { + if (dev && dev->path.pci.devfn != new_devfn) { printk(BIOS_DEBUG, "PCH: PCIe map %02x.%1x -> %02x.%1x\n", PCI_SLOT(dev->path.pci.devfn), @@ -188,9 +202,12 @@ static void pcie_enable_clock_gating(void) int rp; dev = rpc.ports[i]; + if (!dev) + continue; + rp = root_port_number(dev); - if (!dev->enabled) { + if (!is_rp_enabled(rp)) { static const uint32_t high_bit = (1UL << 31); /* Configure shared resource clock gating. */ @@ -198,17 +215,13 @@ static void pcie_enable_clock_gating(void) pci_update_config8(dev, 0xe1, 0xc3, 0x3c); if (!is_lp) { - if (rp == 1 && !rpc.ports[1]->enabled && - !rpc.ports[2]->enabled && - !rpc.ports[3]->enabled) { + if (rp == 1 && !is_rp_enabled(2) && + !is_rp_enabled(3) && !is_rp_enabled(4)) { pci_update_config8(dev, 0xe2, ~1, 1); pci_update_config8(dev, 0xe1, 0x7f, 0x80); } - if (rp == 5 && !rpc.ports[5]->enabled && - (rpc.ports[6] == NULL || - !rpc.ports[6]->enabled) && - (rpc.ports[7] == NULL || - !rpc.ports[7]->enabled)) { + if (rp == 5 && !is_rp_enabled(6) && + !is_rp_enabled(7) && !is_rp_enabled(8)) { pci_update_config8(dev, 0xe2, ~1, 1); pci_update_config8(dev, 0xe1, 0x7f, 0x80); } @@ -223,8 +236,8 @@ static void pcie_enable_clock_gating(void) pci_update_config32(dev, 0x420, ~0, (3 << 29)); /* Enable static clock gating. */ - if (rp == 1 && !rpc.ports[1]->enabled && - !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) { + if (rp == 1 && !is_rp_enabled(2) && + !is_rp_enabled(3) && !is_rp_enabled(4)) { pci_update_config8(dev, 0xe2, ~1, 1); pci_update_config8(dev, 0xe1, 0x7f, 0x80); } else if (rp == 5 || rp == 6) { @@ -258,7 +271,7 @@ static void pcie_enable_clock_gating(void) pci_update_config8(dev, 0xe1, 0xc3, 0x3c); } - if (!enabled_ports && is_lp) + if (!enabled_ports && is_lp && rpc.ports[0]) pci_update_config8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6)); } @@ -267,7 +280,7 @@ static void root_port_commit_config(void) int i; /* If the first root port is disabled the coalesce ports. */ - if (!rpc.ports[0]->enabled) + if (!is_rp_enabled(1)) rpc.coalesce = 1; /* Perform clock gating configuration. */ @@ -307,7 +320,7 @@ static void root_port_commit_config(void) * function numbers. */ current_func = 0; for (i = 0; i < rpc.num_ports; i++) { - if (!rpc.ports[i]->enabled) + if (!is_rp_enabled(i + 1)) continue; pch_pcie_device_set_func(i, current_func); current_func++; @@ -315,7 +328,7 @@ static void root_port_commit_config(void) /* Allocate the disabled devices' PCI function number. */ for (i = 0; i < rpc.num_ports; i++) { - if (rpc.ports[i]->enabled) + if (is_rp_enabled(i + 1)) continue; pch_pcie_device_set_func(i, current_func); current_func++; |