1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 07:02:34 +02:00
flashrom/pcidev.c
Carl-Daniel Hailfinger a73fb4983d Refine -L output to include all programmer modules
Flashrom -L output did not contain a list of programmers nor were
all programmers listed. Fix it and mention at least the name of each
programmer. Wiki output is unchanged, and will need separate fixups.

Corresponding to flashrom svn r1199.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
2010-10-06 23:48:34 +00:00

143 lines
4.0 KiB
C

/*
* This file is part of the flashrom project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <string.h>
#include "flash.h"
#include "programmer.h"
uint32_t io_base_addr;
struct pci_access *pacc;
struct pci_dev *pcidev_dev = NULL;
uint32_t pcidev_validate(struct pci_dev *dev, uint32_t bar,
const struct pcidev_status *devs)
{
int i;
/* FIXME: 64 bit memory BARs need a 64 bit addr. */
uint32_t addr;
for (i = 0; devs[i].device_name != NULL; i++) {
if (dev->device_id != devs[i].device_id)
continue;
/*
* Don't use dev->base_addr[x] (as value for 'bar'), won't
* work on older libpci.
*/
addr = pci_read_long(dev, bar);
msg_pinfo("Found \"%s %s\" (%04x:%04x, BDF %02x:%02x.%x).\n",
devs[i].vendor_name, devs[i].device_name,
dev->vendor_id, dev->device_id, dev->bus, dev->dev,
dev->func);
msg_pdbg("Requested BAR is %s", (addr & 0x1) ? "IO" : "MEM");
if (addr & 0x1) {
/* Mask off IO space indicator and reserved bit. */
msg_pdbg("\n");
addr &= ~0x3;
} else {
msg_pdbg(", %sbit, %sprefetchable\n",
((addr & 0x6) == 0x0) ? "32" :
(((addr & 0x6) == 0x4) ? "64" : "reserved"),
(addr & 0x8) ? "" : "not ");
/* Mask off Mem space indicator, 32/64bit type indicator
* and Prefetchable indicator.
*/
addr &= ~0xf;
}
if (devs[i].status == NT) {
msg_pinfo("===\nThis PCI device is UNTESTED. Please "
"report the 'flashrom -p xxxx' output \n"
"to flashrom@flashrom.org if it works "
"for you. Thank you for your help!\n===\n");
}
return addr;
}
return 0;
}
uint32_t pcidev_init(uint16_t vendor_id, uint32_t bar,
const struct pcidev_status *devs)
{
struct pci_dev *dev;
struct pci_filter filter;
char *pcidev_bdf;
char *msg = NULL;
int found = 0;
uint32_t addr = 0, curaddr = 0;
pacc = pci_alloc(); /* Get the pci_access structure */
pci_init(pacc); /* Initialize the PCI library */
pci_scan_bus(pacc); /* We want to get the list of devices */
pci_filter_init(pacc, &filter);
/* Filter by vendor and also bb:dd.f (if supplied by the user). */
filter.vendor = vendor_id;
pcidev_bdf = extract_programmer_param("pci");
if (pcidev_bdf != NULL) {
if ((msg = pci_filter_parse_slot(&filter, pcidev_bdf))) {
msg_perr("Error: %s\n", msg);
exit(1);
}
}
free(pcidev_bdf);
for (dev = pacc->devices; dev; dev = dev->next) {
if (pci_filter_match(&filter, dev)) {
if ((addr = pcidev_validate(dev, bar, devs)) != 0) {
curaddr = addr;
pcidev_dev = dev;
found++;
}
}
}
/* Only continue if exactly one supported PCI dev has been found. */
if (found == 0) {
msg_perr("Error: No supported PCI device found.\n");
exit(1);
} else if (found > 1) {
msg_perr("Error: Multiple supported PCI devices found. "
"Use 'flashrom -p xxxx:pci=bb:dd.f' \n"
"to explicitly select the card with the given BDF "
"(PCI bus, device, function).\n");
exit(1);
}
return curaddr;
}
void print_supported_pcidevs(const struct pcidev_status *devs)
{
int i;
msg_pinfo("PCI devices:\n");
for (i = 0; devs[i].vendor_name != NULL; i++) {
msg_pinfo("%s %s [%02x:%02x]%s\n", devs[i].vendor_name,
devs[i].device_name, devs[i].vendor_id,
devs[i].device_id,
(devs[i].status == NT) ? " (untested)" : "");
}
}