summaryrefslogtreecommitdiffstats
path: root/flashrom.c
diff options
context:
space:
mode:
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2009-10-31 01:53:09 +0000
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2009-10-31 01:53:09 +0000
commit115d390f1f2da287c444adc9ce1d1cd121546dda (patch)
tree26e572be821ba5ee4d85a439dc55740ff34f3f08 /flashrom.c
parent3291030fc1e876d3f20606721475a1c14df30bd3 (diff)
downloadast2050-flashrom-115d390f1f2da287c444adc9ce1d1cd121546dda.zip
ast2050-flashrom-115d390f1f2da287c444adc9ce1d1cd121546dda.tar.gz
Add infrastructure to check the maximum supported flash size of chipsets and mainboards
The rationale is to warn users when they, for example, try to flash a 512KB parallel flash chip but their chipset only supports 256KB, or they try to flash 512KB and the chipset _does_ theoretically support 512KB but their special board doesn't wire all address lines and thus supports only 256 KB ROM chips at maximum. This has cost Uwe hours of debugging on some board already, until he figured out what was going on. We should try warn our users where possible about this. The chipset and the chip may have more than one bus in common (e.g. SB600 and Pm49* can both speak LPC+FWH) and on SB600/SB7x0/SB8x0 there are different limits for LPC and FWH. The only way to tell the user about the exact circumstances is to spew error messages per bus. The code will issue a warning during probe (which does fail for some chips if the size is too big) and abort before the first real read/write/erase action. If no action is specified, the warning is printed anyway. That way, a user can find out why probe might not have worked, and will be stopped before he/she gets incorrect results. Add a bitcount function to the infrastructure. Corresponding to flashrom svn r755. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
Diffstat (limited to 'flashrom.c')
-rw-r--r--flashrom.c75
1 files changed, 72 insertions, 3 deletions
diff --git a/flashrom.c b/flashrom.c
index 804df53..d1a86cb 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -299,6 +299,15 @@ int max(int a, int b)
return (a > b) ? a : b;
}
+int bitcount(unsigned long a)
+{
+ int i = 0;
+ for (; a != 0; a >>= 1)
+ if (a & 1)
+ i++;
+ return i;
+}
+
char *strcat_realloc(char *dest, const char *src)
{
dest = realloc(dest, strlen(dest) + strlen(src) + 1);
@@ -398,10 +407,60 @@ out_free:
return ret;
}
+int check_max_decode(enum chipbustype buses, uint32_t size)
+{
+ int limitexceeded = 0;
+ if ((buses & CHIP_BUSTYPE_PARALLEL) &&
+ (max_rom_decode.parallel < size)) {
+ limitexceeded++;
+ printf_debug("Chip size %u kB is bigger than supported "
+ "size %u kB of chipset/board/programmer "
+ "for %s interface, "
+ "probe/read/erase/write may fail. ", size / 1024,
+ max_rom_decode.parallel / 1024, "Parallel");
+ }
+ if ((buses & CHIP_BUSTYPE_LPC) && (max_rom_decode.lpc < size)) {
+ limitexceeded++;
+ printf_debug("Chip size %u kB is bigger than supported "
+ "size %u kB of chipset/board/programmer "
+ "for %s interface, "
+ "probe/read/erase/write may fail. ", size / 1024,
+ max_rom_decode.lpc / 1024, "LPC");
+ }
+ if ((buses & CHIP_BUSTYPE_FWH) && (max_rom_decode.fwh < size)) {
+ limitexceeded++;
+ printf_debug("Chip size %u kB is bigger than supported "
+ "size %u kB of chipset/board/programmer "
+ "for %s interface, "
+ "probe/read/erase/write may fail. ", size / 1024,
+ max_rom_decode.fwh / 1024, "FWH");
+ }
+ if ((buses & CHIP_BUSTYPE_SPI) && (max_rom_decode.spi < size)) {
+ limitexceeded++;
+ printf_debug("Chip size %u kB is bigger than supported "
+ "size %u kB of chipset/board/programmer "
+ "for %s interface, "
+ "probe/read/erase/write may fail. ", size / 1024,
+ max_rom_decode.spi / 1024, "SPI");
+ }
+ if (!limitexceeded)
+ return 0;
+ /* Sometimes chip and programmer have more than one bus in common,
+ * and the limit is not exceeded on all buses. Tell the user.
+ */
+ if (bitcount(buses) > limitexceeded)
+ printf_debug("There is at least one common chip/programmer "
+ "interface which can support a chip of this size. "
+ "You can try --force at your own risk.\n");
+ return 1;
+}
+
struct flashchip *probe_flash(struct flashchip *first_flash, int force)
{
struct flashchip *flash;
- unsigned long base = 0, size;
+ unsigned long base = 0;
+ uint32_t size;
+ enum chipbustype buses_common;
char *tmp;
for (flash = first_flash; flash && flash->name; flash++) {
@@ -413,7 +472,8 @@ struct flashchip *probe_flash(struct flashchip *first_flash, int force)
printf_debug("failed! flashrom has no probe function for this flash chip.\n");
continue;
}
- if (!(buses_supported & flash->bustype)) {
+ buses_common = buses_supported & flash->bustype;
+ if (!buses_common) {
tmp = flashbuses_to_text(buses_supported);
printf_debug("skipped. Host bus type %s ", tmp);
free(tmp);
@@ -424,6 +484,7 @@ struct flashchip *probe_flash(struct flashchip *first_flash, int force)
}
size = flash->total_size * 1024;
+ check_max_decode(buses_common, size);
base = flashbase ? flashbase : (0xffffffff - size + 1);
flash->virtual_memory = (chipaddr)programmer_map_flash_region("flash chip", base, size);
@@ -956,6 +1017,15 @@ int main(int argc, char *argv[])
"mainboard you tested. Thanks for your help!\n===\n");
}
+ size = flash->total_size * 1024;
+ if (check_max_decode((buses_supported & flash->bustype), size) &&
+ (!force)) {
+ fprintf(stderr, "Chip is too big for this programmer "
+ "(-V gives details). Use --force to override.\n");
+ programmer_shutdown();
+ return 1;
+ }
+
if (!(read_it | write_it | verify_it | erase_it)) {
printf("No operations were specified.\n");
// FIXME: flash writes stay enabled!
@@ -974,7 +1044,6 @@ int main(int argc, char *argv[])
if (write_it && !dont_verify_it)
verify_it = 1;
- size = flash->total_size * 1024;
buf = (uint8_t *) calloc(size, sizeof(char));
if (erase_it) {
OpenPOWER on IntegriCloud