[PATCH 3/4] bios: mtrr: don't use lspci to get PCI specific data (LP: #1244673)
Alex Hung
alex.hung at canonical.com
Thu Oct 31 03:14:50 UTC 2013
On 10/25/2013 10:12 PM, Colin King wrote:
> 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]) {
Should we condsider mutli-function devices and mask BIT 7?
> + 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;
>
--
Cheers,
Alex Hung
More information about the fwts-devel
mailing list