mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +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:
parent
6e48a026f7
commit
3834c2d7e5
@ -87,7 +87,7 @@ int nicintel_init(void)
|
||||
goto error_out_unmap;
|
||||
|
||||
/* 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? */
|
||||
nicintel_control_bar = physmap("Intel NIC control/status reg",
|
||||
addr, NICINTEL_CONTROL_MEMMAP_SIZE);
|
||||
|
259
pcidev.c
259
pcidev.c
@ -35,157 +35,122 @@ enum pci_bartype {
|
||||
TYPE_UNKNOWN
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
uint64_t addr;
|
||||
uint32_t upperaddr;
|
||||
uint8_t headertype;
|
||||
uint16_t supported_cycles;
|
||||
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;
|
||||
msg_pspew("PCI header type 0x%02x\n", headertype);
|
||||
|
||||
headertype = pci_read_byte(dev, PCI_HEADER_TYPE) & 0x7f;
|
||||
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. */
|
||||
addr = pci_read_long(dev, bar);
|
||||
|
||||
/*
|
||||
* Don't use dev->base_addr[x] (as value for 'bar'), won't
|
||||
* work on older libpci.
|
||||
*/
|
||||
addr = pci_read_long(dev, bar);
|
||||
|
||||
/* Sanity checks. */
|
||||
switch (headertype) {
|
||||
case PCI_HEADER_TYPE_NORMAL:
|
||||
switch (bar) {
|
||||
case PCI_BASE_ADDRESS_0:
|
||||
case PCI_BASE_ADDRESS_1:
|
||||
case PCI_BASE_ADDRESS_2:
|
||||
case PCI_BASE_ADDRESS_3:
|
||||
case PCI_BASE_ADDRESS_4:
|
||||
case PCI_BASE_ADDRESS_5:
|
||||
if ((addr & PCI_BASE_ADDRESS_SPACE) ==
|
||||
PCI_BASE_ADDRESS_SPACE_IO)
|
||||
bartype = TYPE_IOBAR;
|
||||
else
|
||||
bartype = TYPE_MEMBAR;
|
||||
break;
|
||||
case PCI_ROM_ADDRESS:
|
||||
bartype = TYPE_ROMBAR;
|
||||
break;
|
||||
}
|
||||
/* Sanity checks. */
|
||||
switch (headertype) {
|
||||
case PCI_HEADER_TYPE_NORMAL:
|
||||
switch (bar) {
|
||||
case PCI_BASE_ADDRESS_0:
|
||||
case PCI_BASE_ADDRESS_1:
|
||||
case PCI_BASE_ADDRESS_2:
|
||||
case PCI_BASE_ADDRESS_3:
|
||||
case PCI_BASE_ADDRESS_4:
|
||||
case PCI_BASE_ADDRESS_5:
|
||||
if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
|
||||
bartype = TYPE_IOBAR;
|
||||
else
|
||||
bartype = TYPE_MEMBAR;
|
||||
break;
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
switch (bar) {
|
||||
case PCI_BASE_ADDRESS_0:
|
||||
case PCI_BASE_ADDRESS_1:
|
||||
if ((addr & PCI_BASE_ADDRESS_SPACE) ==
|
||||
PCI_BASE_ADDRESS_SPACE_IO)
|
||||
bartype = TYPE_IOBAR;
|
||||
else
|
||||
bartype = TYPE_MEMBAR;
|
||||
break;
|
||||
case PCI_ROM_ADDRESS1:
|
||||
bartype = TYPE_ROMBAR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
break;
|
||||
default:
|
||||
msg_perr("Unknown PCI header type 0x%02x, BAR type "
|
||||
"cannot be determined reliably.\n", headertype);
|
||||
case PCI_ROM_ADDRESS:
|
||||
bartype = TYPE_ROMBAR;
|
||||
break;
|
||||
}
|
||||
|
||||
supported_cycles = pci_read_word(dev, PCI_COMMAND);
|
||||
|
||||
msg_pdbg("Requested BAR is ");
|
||||
switch (bartype) {
|
||||
case TYPE_MEMBAR:
|
||||
msg_pdbg("MEM");
|
||||
if (!(supported_cycles & PCI_COMMAND_MEMORY)) {
|
||||
msg_perr("MEM BAR access requested, but device "
|
||||
"has MEM space accesses disabled.\n");
|
||||
/* TODO: Abort here? */
|
||||
}
|
||||
msg_pdbg(", %sbit, %sprefetchable\n",
|
||||
((addr & 0x6) == 0x0) ? "32" :
|
||||
(((addr & 0x6) == 0x4) ? "64" : "reserved"),
|
||||
(addr & 0x8) ? "" : "not ");
|
||||
if ((addr & 0x6) == 0x4) {
|
||||
/* The spec says that a 64-bit register consumes
|
||||
* two subsequent dword locations.
|
||||
*/
|
||||
upperaddr = pci_read_long(dev, bar + 4);
|
||||
if (upperaddr != 0x00000000) {
|
||||
/* Fun! A real 64-bit resource. */
|
||||
if (sizeof(uintptr_t) != sizeof(uint64_t)) {
|
||||
msg_perr("BAR unreachable!");
|
||||
/* TODO: Really abort here? If
|
||||
* multiple PCI devices match,
|
||||
* we might never tell the user
|
||||
* about the other devices.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
addr |= (uint64_t)upperaddr << 32;
|
||||
}
|
||||
}
|
||||
addr &= PCI_BASE_ADDRESS_MEM_MASK;
|
||||
break;
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
switch (bar) {
|
||||
case PCI_BASE_ADDRESS_0:
|
||||
case PCI_BASE_ADDRESS_1:
|
||||
if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
|
||||
bartype = TYPE_IOBAR;
|
||||
else
|
||||
bartype = TYPE_MEMBAR;
|
||||
break;
|
||||
case TYPE_IOBAR:
|
||||
msg_pdbg("I/O\n");
|
||||
#if __FLASHROM_HAVE_OUTB__
|
||||
if (!(supported_cycles & PCI_COMMAND_IO)) {
|
||||
msg_perr("I/O BAR access requested, but device "
|
||||
"has I/O space accesses disabled.\n");
|
||||
/* TODO: Abort here? */
|
||||
}
|
||||
#else
|
||||
msg_perr("I/O BAR access requested, but flashrom does "
|
||||
"not support I/O BAR access on this platform "
|
||||
"(yet).\n");
|
||||
#endif
|
||||
addr &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
case PCI_ROM_ADDRESS1:
|
||||
bartype = TYPE_ROMBAR;
|
||||
break;
|
||||
case TYPE_ROMBAR:
|
||||
msg_pdbg("ROM\n");
|
||||
/* Not sure if this check is needed. */
|
||||
if (!(supported_cycles & PCI_COMMAND_MEMORY)) {
|
||||
msg_perr("MEM BAR access requested, but device "
|
||||
"has MEM space accesses disabled.\n");
|
||||
/* TODO: Abort here? */
|
||||
}
|
||||
addr &= PCI_ROM_ADDRESS_MASK;
|
||||
break;
|
||||
case TYPE_UNKNOWN:
|
||||
msg_perr("BAR type unknown, please report a bug at "
|
||||
"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;
|
||||
break;
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
break;
|
||||
default:
|
||||
msg_perr("Unknown PCI header type 0x%02x, BAR type cannot be determined reliably.\n",
|
||||
headertype);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
supported_cycles = pci_read_word(dev, PCI_COMMAND);
|
||||
|
||||
msg_pdbg("Requested BAR is ");
|
||||
switch (bartype) {
|
||||
case TYPE_MEMBAR:
|
||||
msg_pdbg("MEM");
|
||||
if (!(supported_cycles & PCI_COMMAND_MEMORY)) {
|
||||
msg_perr("MEM BAR access requested, but device has MEM space accesses disabled.\n");
|
||||
/* TODO: Abort here? */
|
||||
}
|
||||
msg_pdbg(", %sbit, %sprefetchable\n",
|
||||
((addr & 0x6) == 0x0) ? "32" : (((addr & 0x6) == 0x4) ? "64" : "reserved"),
|
||||
(addr & 0x8) ? "" : "not ");
|
||||
if ((addr & 0x6) == 0x4) {
|
||||
/* The spec says that a 64-bit register consumes
|
||||
* two subsequent dword locations.
|
||||
*/
|
||||
upperaddr = pci_read_long(dev, bar + 4);
|
||||
if (upperaddr != 0x00000000) {
|
||||
/* Fun! A real 64-bit resource. */
|
||||
if (sizeof(uintptr_t) != sizeof(uint64_t)) {
|
||||
msg_perr("BAR unreachable!");
|
||||
/* TODO: Really abort here? If multiple PCI devices match,
|
||||
* we might never tell the user about the other devices.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
addr |= (uint64_t)upperaddr << 32;
|
||||
}
|
||||
}
|
||||
addr &= PCI_BASE_ADDRESS_MEM_MASK;
|
||||
break;
|
||||
case TYPE_IOBAR:
|
||||
msg_pdbg("I/O\n");
|
||||
#if __FLASHROM_HAVE_OUTB__
|
||||
if (!(supported_cycles & PCI_COMMAND_IO)) {
|
||||
msg_perr("I/O BAR access requested, but device has I/O space accesses disabled.\n");
|
||||
/* TODO: Abort here? */
|
||||
}
|
||||
#else
|
||||
msg_perr("I/O BAR access requested, but flashrom does not support I/O BAR access on this "
|
||||
"platform (yet).\n");
|
||||
#endif
|
||||
addr &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
break;
|
||||
case TYPE_ROMBAR:
|
||||
msg_pdbg("ROM\n");
|
||||
/* Not sure if this check is needed. */
|
||||
if (!(supported_cycles & PCI_COMMAND_MEMORY)) {
|
||||
msg_perr("MEM BAR access requested, but device has MEM space accesses disabled.\n");
|
||||
/* TODO: Abort here? */
|
||||
}
|
||||
addr &= PCI_ROM_ADDRESS_MASK;
|
||||
break;
|
||||
case TYPE_UNKNOWN:
|
||||
msg_perr("BAR type unknown, please report a bug at flashrom@flashrom.org\n");
|
||||
}
|
||||
|
||||
return (uintptr_t)addr;
|
||||
}
|
||||
|
||||
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 *msg = NULL;
|
||||
int found = 0;
|
||||
int i;
|
||||
uintptr_t addr = 0, curaddr = 0;
|
||||
|
||||
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) {
|
||||
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
|
||||
* just those with a valid BAR.
|
||||
*/
|
||||
if ((addr = pcidev_validate(dev, bar, devs)) != 0) {
|
||||
if ((addr = pcidev_readbar(dev, bar)) != 0) {
|
||||
curaddr = addr;
|
||||
pcidev_dev = dev;
|
||||
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");
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ struct pcidev_status {
|
||||
const char *vendor_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);
|
||||
/* rpci_write_* are reversible writes. The original PCI config space register
|
||||
* contents will be restored on shutdown.
|
||||
|
Loading…
x
Reference in New Issue
Block a user