1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 15:12:36 +02:00

Check vendor_id for PCI based external programmers

Restructure PCI device detection code.
Rename pcidev_validate to pcidev_readbar.

Note: Slight changes in behaviour are possible, especially on dual/quad
chip NICs which appear as more than one PCI device. Found devices are no
longer printed at _pinfo level, but rather at _pdbg level.

Corresponding to flashrom svn r1548.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
This commit is contained in:
Carl-Daniel Hailfinger 2012-07-16 21:32:19 +00:00
parent 6e48a026f7
commit 3834c2d7e5
3 changed files with 123 additions and 140 deletions

View File

@ -87,7 +87,7 @@ int nicintel_init(void)
goto error_out_unmap; goto error_out_unmap;
/* FIXME: Using pcidev_dev _will_ cause pretty explosions in the future. */ /* FIXME: Using pcidev_dev _will_ cause pretty explosions in the future. */
addr = pcidev_validate(pcidev_dev, PCI_BASE_ADDRESS_0, nics_intel); addr = pcidev_readbar(pcidev_dev, PCI_BASE_ADDRESS_0);
/* FIXME: This is not an aligned mapping. Use 4k? */ /* FIXME: This is not an aligned mapping. Use 4k? */
nicintel_control_bar = physmap("Intel NIC control/status reg", nicintel_control_bar = physmap("Intel NIC control/status reg",
addr, NICINTEL_CONTROL_MEMMAP_SIZE); addr, NICINTEL_CONTROL_MEMMAP_SIZE);

View File

@ -35,32 +35,19 @@ enum pci_bartype {
TYPE_UNKNOWN TYPE_UNKNOWN
}; };
uintptr_t pcidev_validate(struct pci_dev *dev, int bar, uintptr_t pcidev_readbar(struct pci_dev *dev, int bar)
const struct pcidev_status *devs)
{ {
int i;
uint64_t addr; uint64_t addr;
uint32_t upperaddr; uint32_t upperaddr;
uint8_t headertype; uint8_t headertype;
uint16_t supported_cycles; uint16_t supported_cycles;
enum pci_bartype bartype = TYPE_UNKNOWN; enum pci_bartype bartype = TYPE_UNKNOWN;
for (i = 0; devs[i].device_name != NULL; i++) {
if (dev->device_id != devs[i].device_id)
continue;
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);
headertype = pci_read_byte(dev, PCI_HEADER_TYPE) & 0x7f; headertype = pci_read_byte(dev, PCI_HEADER_TYPE) & 0x7f;
msg_pspew("PCI header type 0x%02x\n", headertype); msg_pspew("PCI header type 0x%02x\n", headertype);
/* /* Don't use dev->base_addr[x] (as value for 'bar'), won't work on older libpci. */
* Don't use dev->base_addr[x] (as value for 'bar'), won't
* work on older libpci.
*/
addr = pci_read_long(dev, bar); addr = pci_read_long(dev, bar);
/* Sanity checks. */ /* Sanity checks. */
@ -73,8 +60,7 @@ uintptr_t pcidev_validate(struct pci_dev *dev, int bar,
case PCI_BASE_ADDRESS_3: case PCI_BASE_ADDRESS_3:
case PCI_BASE_ADDRESS_4: case PCI_BASE_ADDRESS_4:
case PCI_BASE_ADDRESS_5: case PCI_BASE_ADDRESS_5:
if ((addr & PCI_BASE_ADDRESS_SPACE) == if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
PCI_BASE_ADDRESS_SPACE_IO)
bartype = TYPE_IOBAR; bartype = TYPE_IOBAR;
else else
bartype = TYPE_MEMBAR; bartype = TYPE_MEMBAR;
@ -88,8 +74,7 @@ uintptr_t pcidev_validate(struct pci_dev *dev, int bar,
switch (bar) { switch (bar) {
case PCI_BASE_ADDRESS_0: case PCI_BASE_ADDRESS_0:
case PCI_BASE_ADDRESS_1: case PCI_BASE_ADDRESS_1:
if ((addr & PCI_BASE_ADDRESS_SPACE) == if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
PCI_BASE_ADDRESS_SPACE_IO)
bartype = TYPE_IOBAR; bartype = TYPE_IOBAR;
else else
bartype = TYPE_MEMBAR; bartype = TYPE_MEMBAR;
@ -102,8 +87,8 @@ uintptr_t pcidev_validate(struct pci_dev *dev, int bar,
case PCI_HEADER_TYPE_CARDBUS: case PCI_HEADER_TYPE_CARDBUS:
break; break;
default: default:
msg_perr("Unknown PCI header type 0x%02x, BAR type " msg_perr("Unknown PCI header type 0x%02x, BAR type cannot be determined reliably.\n",
"cannot be determined reliably.\n", headertype); headertype);
break; break;
} }
@ -114,13 +99,11 @@ uintptr_t pcidev_validate(struct pci_dev *dev, int bar,
case TYPE_MEMBAR: case TYPE_MEMBAR:
msg_pdbg("MEM"); msg_pdbg("MEM");
if (!(supported_cycles & PCI_COMMAND_MEMORY)) { if (!(supported_cycles & PCI_COMMAND_MEMORY)) {
msg_perr("MEM BAR access requested, but device " msg_perr("MEM BAR access requested, but device has MEM space accesses disabled.\n");
"has MEM space accesses disabled.\n");
/* TODO: Abort here? */ /* TODO: Abort here? */
} }
msg_pdbg(", %sbit, %sprefetchable\n", msg_pdbg(", %sbit, %sprefetchable\n",
((addr & 0x6) == 0x0) ? "32" : ((addr & 0x6) == 0x0) ? "32" : (((addr & 0x6) == 0x4) ? "64" : "reserved"),
(((addr & 0x6) == 0x4) ? "64" : "reserved"),
(addr & 0x8) ? "" : "not "); (addr & 0x8) ? "" : "not ");
if ((addr & 0x6) == 0x4) { if ((addr & 0x6) == 0x4) {
/* The spec says that a 64-bit register consumes /* The spec says that a 64-bit register consumes
@ -131,10 +114,8 @@ uintptr_t pcidev_validate(struct pci_dev *dev, int bar,
/* Fun! A real 64-bit resource. */ /* Fun! A real 64-bit resource. */
if (sizeof(uintptr_t) != sizeof(uint64_t)) { if (sizeof(uintptr_t) != sizeof(uint64_t)) {
msg_perr("BAR unreachable!"); msg_perr("BAR unreachable!");
/* TODO: Really abort here? If /* TODO: Really abort here? If multiple PCI devices match,
* multiple PCI devices match, * we might never tell the user about the other devices.
* we might never tell the user
* about the other devices.
*/ */
return 0; return 0;
} }
@ -147,14 +128,12 @@ uintptr_t pcidev_validate(struct pci_dev *dev, int bar,
msg_pdbg("I/O\n"); msg_pdbg("I/O\n");
#if __FLASHROM_HAVE_OUTB__ #if __FLASHROM_HAVE_OUTB__
if (!(supported_cycles & PCI_COMMAND_IO)) { if (!(supported_cycles & PCI_COMMAND_IO)) {
msg_perr("I/O BAR access requested, but device " msg_perr("I/O BAR access requested, but device has I/O space accesses disabled.\n");
"has I/O space accesses disabled.\n");
/* TODO: Abort here? */ /* TODO: Abort here? */
} }
#else #else
msg_perr("I/O BAR access requested, but flashrom does " msg_perr("I/O BAR access requested, but flashrom does not support I/O BAR access on this "
"not support I/O BAR access on this platform " "platform (yet).\n");
"(yet).\n");
#endif #endif
addr &= PCI_BASE_ADDRESS_IO_MASK; addr &= PCI_BASE_ADDRESS_IO_MASK;
break; break;
@ -162,30 +141,16 @@ uintptr_t pcidev_validate(struct pci_dev *dev, int bar,
msg_pdbg("ROM\n"); msg_pdbg("ROM\n");
/* Not sure if this check is needed. */ /* Not sure if this check is needed. */
if (!(supported_cycles & PCI_COMMAND_MEMORY)) { if (!(supported_cycles & PCI_COMMAND_MEMORY)) {
msg_perr("MEM BAR access requested, but device " msg_perr("MEM BAR access requested, but device has MEM space accesses disabled.\n");
"has MEM space accesses disabled.\n");
/* TODO: Abort here? */ /* TODO: Abort here? */
} }
addr &= PCI_ROM_ADDRESS_MASK; addr &= PCI_ROM_ADDRESS_MASK;
break; break;
case TYPE_UNKNOWN: case TYPE_UNKNOWN:
msg_perr("BAR type unknown, please report a bug at " msg_perr("BAR type unknown, please report a bug at flashrom@flashrom.org\n");
"flashrom@flashrom.org\n");
}
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. Please add the name of your\n"
"PCI device to the subject. Thank you for "
"your help!\n===\n");
} }
return (uintptr_t)addr; return (uintptr_t)addr;
}
return 0;
} }
uintptr_t pcidev_init(int bar, const struct pcidev_status *devs) uintptr_t pcidev_init(int bar, const struct pcidev_status *devs)
@ -195,6 +160,7 @@ uintptr_t pcidev_init(int bar, const struct pcidev_status *devs)
char *pcidev_bdf; char *pcidev_bdf;
char *msg = NULL; char *msg = NULL;
int found = 0; int found = 0;
int i;
uintptr_t addr = 0, curaddr = 0; uintptr_t addr = 0, curaddr = 0;
pacc = pci_alloc(); /* Get the pci_access structure */ pacc = pci_alloc(); /* Get the pci_access structure */
@ -214,10 +180,29 @@ uintptr_t pcidev_init(int bar, const struct pcidev_status *devs)
for (dev = pacc->devices; dev; dev = dev->next) { for (dev = pacc->devices; dev; dev = dev->next) {
if (pci_filter_match(&filter, dev)) { if (pci_filter_match(&filter, dev)) {
/* Check against list of supported devices. */
for (i = 0; devs[i].device_name != NULL; i++)
if ((dev->vendor_id == devs[i].vendor_id) &&
(dev->device_id == devs[i].device_id))
break;
/* Not supported, try the next one. */
if (devs[i].device_name == NULL)
continue;
msg_pdbg("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);
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. Please add the name "
"of your\n"
"PCI device to the subject. Thank you for your help!\n===\n");
/* FIXME: We should count all matching devices, not /* FIXME: We should count all matching devices, not
* just those with a valid BAR. * just those with a valid BAR.
*/ */
if ((addr = pcidev_validate(dev, bar, devs)) != 0) { if ((addr = pcidev_readbar(dev, bar)) != 0) {
curaddr = addr; curaddr = addr;
pcidev_dev = dev; pcidev_dev = dev;
found++; found++;
@ -230,10 +215,8 @@ uintptr_t pcidev_init(int bar, const struct pcidev_status *devs)
msg_perr("Error: No supported PCI device found.\n"); msg_perr("Error: No supported PCI device found.\n");
exit(1); exit(1);
} else if (found > 1) { } else if (found > 1) {
msg_perr("Error: Multiple supported PCI devices found. " msg_perr("Error: Multiple supported PCI devices found. Use 'flashrom -p xxxx:pci=bb:dd.f' \n"
"Use 'flashrom -p xxxx:pci=bb:dd.f' \n" "to explicitly select the card with the given BDF (PCI bus, device, function).\n");
"to explicitly select the card with the given BDF "
"(PCI bus, device, function).\n");
exit(1); exit(1);
} }

View File

@ -227,7 +227,7 @@ struct pcidev_status {
const char *vendor_name; const char *vendor_name;
const char *device_name; const char *device_name;
}; };
uintptr_t pcidev_validate(struct pci_dev *dev, int bar, const struct pcidev_status *devs); uintptr_t pcidev_readbar(struct pci_dev *dev, int bar);
uintptr_t pcidev_init(int bar, const struct pcidev_status *devs); uintptr_t pcidev_init(int bar, const struct pcidev_status *devs);
/* rpci_write_* are reversible writes. The original PCI config space register /* rpci_write_* are reversible writes. The original PCI config space register
* contents will be restored on shutdown. * contents will be restored on shutdown.