[PATCH 3/4] bios: mtrr: don't use lspci to get PCI specific data (LP: #1244673)
Colin King
colin.king at canonical.com
Fri Oct 25 14:12:33 UTC 2013
From: Colin Ian King <colin.king at canonical.com>
Rather than do some messy parsing of the output from lspci, instead
just use the raw data from /sys/bus/pci/devices
Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
src/bios/mtrr/mtrr.c | 84 ++++++++++++++++++++++++++++++++++++----------------
1 file changed, 58 insertions(+), 26 deletions(-)
diff --git a/src/bios/mtrr/mtrr.c b/src/bios/mtrr/mtrr.c
index 15ed37c..a32fd96 100644
--- a/src/bios/mtrr/mtrr.c
+++ b/src/bios/mtrr/mtrr.c
@@ -201,35 +201,70 @@ static int check_prefetchable(
uint64_t address,
bool *pref)
{
- char line[4096];
- fwts_list *lspci_output;
- fwts_list_link *item;
- int status;
+ char path[PATH_MAX];
+ uint8_t config[64];
+ int fd, i, n, bars;
+ uint32_t *bar;
*pref = false;
+ snprintf(path, sizeof(path), FWTS_PCI_DEV_PATH "/%s/config", device);
+ if ((fd = open(path, O_RDONLY)) < 0) {
+ fwts_log_error(fw, "Cannot read PCI config for device %s\n", device);
+ return FWTS_ERROR;
+ }
- memset(line,0,4096);
+ n = read(fd, config, sizeof(config));
+ close(fd);
- snprintf(line, sizeof(line), "%s -v -s %s", fw->lspci, device);
- if (fwts_pipe_exec(line, &lspci_output, &status) != FWTS_OK)
- return FWTS_ERROR;
+ /* config space too small? ignore for now */
+ if (n < 64)
+ return FWTS_OK;
- /* Nothing for this decice? That seems like a failure */
- if (lspci_output == NULL)
- return FWTS_ERROR;
+ switch (config[FWTS_PCI_CONFIG_HEADER_TYPE]) {
+ case FWTS_PCI_CONFIG_HEADER_TYPE_NON_BRIDGE:
+ bars = 6;
+ break;
+ case FWTS_PCI_CONFIG_HEADER_TYPE_PCI_BRIDGE:
+ bars = 2;
+ break;
+ default:
+ /* No BARs, ignore */
+ return FWTS_OK;
+ }
+
+ /*
+ * Check BAR addresses, do they match and are they prefetchable
+ * See http://wiki.osdev.org/PCI
+ */
+ bar = (uint32_t*)&config[0x10];
+ for (i = 0; i < bars; i++) {
+ if ((bar[i] & 1) == 0) {
+ uint64_t bar_addr;
+ bool is_prefetchable =
+ (bar[i] & FWTS_PCI_CONFIG_BAR_PREFETCHABLE);
+
+ switch ((bar[i] >> 1) & 0x03) {
+ case FWTS_PCI_CONFIG_BAR_TYPE_ADDR_16BIT:
+ bar_addr = bar[i] & 0xfff0;
+ break;
+ case FWTS_PCI_CONFIG_BAR_TYPE_ADDR_32BIT:
+ bar_addr = bar[i] & 0xfffffff0;
+ break;
+ case FWTS_PCI_CONFIG_BAR_TYPE_ADDR_64BIT:
+ bar_addr = (bar[i] & 0xfffffff0) |
+ (((uint64_t)bar[i+1]) << 32);
+ i++;
+ break;
+ default:
+ continue;
+ }
- fwts_list_foreach(item, lspci_output) {
- char *str = strstr(fwts_text_list_text(item), "Memory at ");
- if (str && strtoull(str+10, NULL, 16) == address) {
- if (strstr(str, "non-prefetchable"))
- *pref = false;
- else if (strstr(str, "(prefetchable"))
- *pref = true;
- else if (strstr(str, ", prefetchable"))
- *pref = true;
+ if (bar_addr == address) {
+ *pref = is_prefetchable;
+ break;
+ }
}
}
- fwts_list_free(lspci_output, free);
return FWTS_OK;
}
@@ -334,8 +369,8 @@ static int validate_iomem(fwts_framework *fw)
if (guess_cache_type(fw, c2, &type_must, &type_mustnot, start) != FWTS_OK) {
/* This has failed, give up at this point */
- fwts_skipped(fw,
- "Could not guess cache type, lspci seems to be failing.");
+ fwts_skipped(fw,
+ "Could not guess cache type.");
fclose(file);
return FWTS_ERROR;
}
@@ -404,9 +439,6 @@ static void do_mtrr_resource(fwts_framework *fw)
static int mtrr_init(fwts_framework *fw)
{
- if (fwts_check_executable(fw, fw->lspci, "lspci"))
- return FWTS_ERROR;
-
if (get_mtrrs() != FWTS_OK) {
fwts_log_error(fw, "Failed to read /proc/mtrr.");
return FWTS_ERROR;
--
1.8.3.2
More information about the fwts-devel
mailing list