diff --git a/flashrom.8 b/flashrom.8 index 7a48041ef..abfafaaad 100644 --- a/flashrom.8 +++ b/flashrom.8 @@ -1,13 +1,17 @@ -.TH FLASHROM 8 "April 11, 2009" +.TH FLASHROM 8 "May 14, 2009" .SH NAME -flashrom \- read, write, verify and erase BIOS/ROM/flash chips +flashrom \- detect, read, write, verify and erase flash chips .SH SYNOPSIS -.B flashrom \fR[\fB\-rwvEVfLhR\fR] [\fB\-c\fR chipname] [\fB\-s\fR exclude_start] [\fB\-e\fR exclude_end] - [\fB-m\fR [vendor:]part] [\fB-l\fR file.layout] [\fB-i\fR image_name] [file] +.B flashrom \fR[\fB\-EVfLhR\fR] [\fB\-r\fR file] [\fB\-w\fR file] [\fB\-v\fR file] + [\fB\-c\fR chipname] [\fB\-s\fR addr] [\fB\-e\fR addr] [\fB\-m\fR [vendor:]part] + [\fB\-l\fR file] [\fB\-i\fR image] [\fB\-p\fR programmer] [file] .SH DESCRIPTION .B flashrom -is a utility for reading, writing, verifying and erasing flash ROM chips. -It's often used to flash BIOS/coreboot/firmware images. +is a utility for detecting, reading, writing, verifying and erasing flash ROM +chips. It's often used to flash BIOS/EFI/coreboot/firmware images in-system +using a supported mainboard, but it also supports flashing of network cards +(NICs), SATA controller cards, and other external devices which can program +flash chips. .PP It supports a wide range of DIP32, PLCC32, DIP8, SO8/SOIC8, TSOP32, and TSOP40 chips, which use various protocols such as LPC, FWH, parallel flash, @@ -126,11 +130,24 @@ of the box. .B "\-p, \-\-programmer " Specify the programmer device. Currently supported are: .sp -.BR " internal" " (default, for in-system flashing in the mainboard)" -.br -.BR " nic3com" " (for flash ROMs on 3COM network cards)" -.br -.BR " dummy" " (just prints all operations and accesses)" +.BR "* internal" " (default, for in-system flashing in the mainboard)" +.sp +.BR "* nic3com" " (for flash ROMs on 3COM network cards)" +.sp +If you have multiple supported NICs in your system, you must use +.B "flashrom -p nic3com=bb:dd.f" +to explicitly select one of them, where +.B bb +is the PCI bus number, +.B dd +is the PCI device number, and +.B f +is the PCI function number of the desired NIC. +.sp +Example: +.B "flashrom -p nic3com=05:04.0" +.sp +.BR "* dummy" " (just prints all operations and accesses)" .TP .B "\-h, \-\-help" Show a help text and exit. diff --git a/nic3com.c b/nic3com.c index a98226720..baaec4b7e 100644 --- a/nic3com.c +++ b/nic3com.c @@ -67,18 +67,18 @@ static struct nic_status { uint32_t nic3com_validate(struct pci_dev *dev) { - int i = 0; - uint32_t addr = -1; + int i; + uint32_t addr; for (i = 0; nics[i].device_name != NULL; i++) { if (dev->device_id != nics[i].device_id) continue; - addr = pci_read_long(dev, PCI_IO_BASE_ADDRESS) & ~0x03; + addr = (uint32_t)(dev->base_addr[0] & ~0x03); - printf("Found NIC \"3COM %s\" (%04x:%04x), addr = 0x%x\n", - nics[i].device_name, PCI_VENDOR_ID_3COM, - nics[i].device_id, addr); + printf("Found NIC \"3COM %s\" (%04x:%04x, BDF %02x:%02x.%x)\n", + nics[i].device_name, dev->vendor_id, + dev->device_id, dev->bus, dev->dev, dev->func); if (nics[i].status == NT) { printf("===\nThis NIC is UNTESTED. Please email a " @@ -90,41 +90,48 @@ uint32_t nic3com_validate(struct pci_dev *dev) return addr; } - return addr; + return 0; } int nic3com_init(void) { struct pci_dev *dev; char *msg = NULL; + int found = 0; get_io_perms(); 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 = PCI_VENDOR_ID_3COM; if (nic_pcidev != NULL) { - pci_filter_init(pacc, &filter); - if ((msg = pci_filter_parse_slot(&filter, nic_pcidev))) { fprintf(stderr, "Error: %s\n", msg); exit(1); } } - if (!filter.vendor && !filter.device) { - pci_filter_init(pacc, &filter); - filter.vendor = PCI_VENDOR_ID_3COM; + for (dev = pacc->devices; dev; dev = dev->next) { + if (pci_filter_match(&filter, dev)) { + if ((io_base_addr = nic3com_validate(dev)) != 0) + found++; + } } - dev = pci_dev_find_filter(filter); - - if (dev && (dev->vendor_id == PCI_VENDOR_ID_3COM)) - io_base_addr = nic3com_validate(dev); - else { + /* Only continue if exactly one supported NIC has been found. */ + if (found == 0) { fprintf(stderr, "Error: No supported 3COM NIC found.\n"); exit(1); + } else if (found > 1) { + fprintf(stderr, "Error: Multiple supported NICs found. " + "Please use 'flashrom -p nic3com=bb:dd.f' \n" + "to explicitly select the card with the given BDF " + "(PCI bus, device, function).\n"); + exit(1); } /*