See patch.
I'm thankful for better suggestions to track which chipsets and especially boards can decode how much.
For boards we need to autodetect them (not possible for all boards unfortunately). For those with board-enables we could reuse that table and enhance/add board-enables, whether that's a good idea is another issue.
For boards that cannot be autodetected we should at least have a table of the max. supported ROM chip size, which can be printed in "flashrom -L" and in the wiki.
Uwe.
On 06.10.2009 13:52, Uwe Hermann wrote:
I'm thankful for better suggestions to track which chipsets and especially boards can decode how much.
Could you please change chipset_max_rom_decode_kb to a struct with one value per bustype? All Intel chipsets with SPI support have two independent limits: One for FWH and one for SPI. SB600 has three limits: FWH, LPC and SPI (yes, it can speak FWH).
For boards we need to autodetect them (not possible for all boards unfortunately). For those with board-enables we could reuse that table and enhance/add board-enables, whether that's a good idea is another issue.
Board matching is already done via board enables. While the size limit is not directly a board enable, we also use board enables to add buses (e.g. behind a IT8716F SPI), so it would only be logical to use board enables for board sizing constraints.
How should we handle double limits (board+chipset)? Pick the minimum? Logical AND?
IMHO the chipset enable should set the limits for every supported bus, and the board enable should override settings where/how appropriate. That also means there's only one variable per bus. If you change your patch that way, I think I'll ack it right away.
For boards that cannot be autodetected we should at least have a table of the max. supported ROM chip size, which can be printed in "flashrom -L" and in the wiki.
Such boards will appear as "needs special board enable", though. Oh well. Maybe it is time to introduce a "reason" bitfield in the board enable table which says why the board is listed there.
Regards, Carl-Daniel
OK, completely rewritten attempt. I'm reusing Uwe's changelog. Uwe, if you're happy with this, feel free to add your signoff/ack.
Add a facility to check and report to the user the maximum supported decode size for chipsets and tested 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 (yes, this is "best effort", but still better than not to warn at all).
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-rom_decode_check/flash.h =================================================================== --- flashrom-rom_decode_check/flash.h (Revision 753) +++ flashrom-rom_decode_check/flash.h (Arbeitskopie) @@ -352,9 +352,17 @@ void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask); int board_flash_enable(const char *vendor, const char *part);
+struct decode_sizes { + uint32_t parallel; + uint32_t lpc; + uint32_t fwh; + uint32_t spi; +}; + /* chipset_enable.c */ extern enum chipbustype buses_supported; int chipset_flash_enable(void); +extern struct decode_sizes max_rom_decode;
extern unsigned long flashbase;
Index: flashrom-rom_decode_check/chipset_enable.c =================================================================== --- flashrom-rom_decode_check/chipset_enable.c (Revision 753) +++ flashrom-rom_decode_check/chipset_enable.c (Arbeitskopie) @@ -41,6 +41,12 @@ */
enum chipbustype buses_supported = CHIP_BUSTYPE_NONSPI; +struct decode_sizes max_rom_decode = { + .parallel = 0xffffffff, + .lpc = 0xffffffff, + .fwh = 0xffffffff, + .spi = 0xffffffff +};
extern int ichspi_lock;
@@ -204,34 +210,73 @@ uint32_t fwh_conf; int i; char *idsel = NULL; + int tmp; + int max_decode_fwh_idsel = 0; + int max_decode_fwh_decode = 0; + int contiguous = 1;
- /* Ignore all legacy ranges below 1 MB. */ + /* Ignore all legacy ranges below 1 MB. + * We currently only support flashing the chip which responds to + * IDSEL=0. To support IDSEL!=0, flashbase and decode size calculations + * have to be adjusted. + */ /* FWH_SEL1 */ fwh_conf = pci_read_long(dev, 0xd0); - for (i = 7; i >= 0; i--) + for (i = 7; i >= 0; i--) { + tmp = (fwh_conf >> (i * 4)) & 0xf; printf_debug("\n0x%08x/0x%08x FWH IDSEL: 0x%x", (0x1ff8 + i) * 0x80000, (0x1ff0 + i) * 0x80000, - (fwh_conf >> (i * 4)) & 0xf); + tmp); + if ((tmp == 0) && contiguous) { + max_decode_fwh_idsel = (8 - i) * 0x80000; + } else { + contiguous = 0; + } + } /* FWH_SEL2 */ fwh_conf = pci_read_word(dev, 0xd4); - for (i = 3; i >= 0; i--) + for (i = 3; i >= 0; i--) { + tmp = (fwh_conf >> (i * 4)) & 0xf; printf_debug("\n0x%08x/0x%08x FWH IDSEL: 0x%x", (0xff4 + i) * 0x100000, (0xff0 + i) * 0x100000, - (fwh_conf >> (i * 4)) & 0xf); + tmp); + if ((tmp == 0) && contiguous) { + max_decode_fwh_idsel = (8 - i) * 0x100000; + } else { + contiguous = 0; + } + } + contiguous = 1; /* FWH_DEC_EN1 */ fwh_conf = pci_read_word(dev, 0xd8); - for (i = 7; i >= 0; i--) + for (i = 7; i >= 0; i--) { + tmp = (fwh_conf >> (i + 0x8)) & 0x1; printf_debug("\n0x%08x/0x%08x FWH decode %sabled", (0x1ff8 + i) * 0x80000, (0x1ff0 + i) * 0x80000, - (fwh_conf >> (i + 0x8)) & 0x1 ? "en" : "dis"); - for (i = 3; i >= 0; i--) + tmp ? "en" : "dis"); + if ((tmp == 0) && contiguous) { + max_decode_fwh_decode = (8 - i) * 0x80000; + } else { + contiguous = 0; + } + } + for (i = 3; i >= 0; i--) { + tmp = (fwh_conf >> i) & 0x1; printf_debug("\n0x%08x/0x%08x FWH decode %sabled", (0xff4 + i) * 0x100000, (0xff0 + i) * 0x100000, - (fwh_conf >> i) & 0x1 ? "en" : "dis"); + tmp ? "en" : "dis"); + if ((tmp == 0) && contiguous) { + max_decode_fwh_decode = (8 - i) * 0x100000; + } else { + contiguous = 0; + } + } + max_rom_decode.fwh = min(max_decode_fwh_idsel, max_decode_fwh_decode); + printf_debug("\nMaximum FWH chip size: 0x%x bytes", max_rom_decode.fwh);
if (programmer_param) idsel = strstr(programmer_param, "fwh_idsel="); @@ -244,6 +289,7 @@ printf("\nSetting IDSEL=0x%x for top 16 MB", fwh_conf); pci_write_long(dev, 0xd0, fwh_conf); pci_write_word(dev, 0xd4, fwh_conf); + /* FIXME: Decode settings are not changed. */ }
return enable_flash_ich(dev, name, 0xdc); @@ -536,6 +582,9 @@ reg8 |= BIOS_ROM_POSITIVE_DECODE; pci_write_byte(dev, DECODE_CONTROL_REG2, reg8);
+ /* No idea which buses this limit applies to. */ + //max_rom_decode.lpc = 16 * 1024 * 1024; + return 0; }
Index: flashrom-rom_decode_check/flashrom.c =================================================================== --- flashrom-rom_decode_check/flashrom.c (Revision 753) +++ flashrom-rom_decode_check/flashrom.c (Arbeitskopie) @@ -401,7 +401,9 @@ struct flashchip *probe_flash(struct flashchip *first_flash, int force) { struct flashchip *flash; - unsigned long base = 0, size; + unsigned long base = 0; + unsigned int size; + enum chipbustype buses_common; char *tmp;
for (flash = first_flash; flash && flash->name; flash++) { @@ -413,7 +415,8 @@ 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 +427,30 @@ }
size = flash->total_size * 1024; + if ((buses_common & CHIP_BUSTYPE_PARALLEL) && + (max_rom_decode.parallel < size)) + printf_debug("Chip size %u is bigger than supported " + "size %u of chipset/board/programmer, " + "probe/read/erase/write may fail. ", size, + max_rom_decode.parallel); + if ((buses_common & CHIP_BUSTYPE_LPC) && + (max_rom_decode.lpc < size)) + printf_debug("Chip size %u is bigger than supported " + "size %u of chipset/board/programmer, " + "probe/read/erase/write may fail. ", size, + max_rom_decode.lpc); + if ((buses_common & CHIP_BUSTYPE_FWH) && + (max_rom_decode.fwh < size)) + printf_debug("Chip size %u is bigger than supported " + "size %u of chipset/board/programmer, " + "probe/read/erase/write may fail. ", size, + max_rom_decode.fwh); + if ((buses_common & CHIP_BUSTYPE_SPI) && + (max_rom_decode.spi < size)) + printf_debug("Chip size %u is bigger than supported " + "size %u of chipset/board/programmer, " + "probe/read/erase/write may fail. ", size, + max_rom_decode.spi);
base = flashbase ? flashbase : (0xffffffff - size + 1); flash->virtual_memory = (chipaddr)programmer_map_flash_region("flash chip", base, size); @@ -977,6 +1004,8 @@ size = flash->total_size * 1024; buf = (uint8_t *) calloc(size, sizeof(char));
+ // FIXME: Check for decode size again? + if (erase_it) { if (flash->tested & TEST_BAD_ERASE) { fprintf(stderr, "Erase is not working on this chip. "); Index: flashrom-rom_decode_check/board_enable.c =================================================================== --- flashrom-rom_decode_check/board_enable.c (Revision 753) +++ flashrom-rom_decode_check/board_enable.c (Arbeitskopie) @@ -804,16 +804,24 @@ }
/** - * Suited for: - * - Shuttle AK38N: VIA KT333CF + VIA VT8235 + ITE IT8705F - * - Elitegroup K7VTA3: VIA Apollo KT266/A/333 + VIA VT8235 + ITE IT8705F + * Suited for: Elitegroup K7VTA3: VIA Apollo KT266/A/333 + VIA VT8235 + ITE IT8705F */ -static int it8705f_write_enable_2e(const char *name) +static int elitegroup_k7vta3(const char *name) { + max_rom_decode.parallel = 256 * 1024; return it8705f_write_enable(0x2e, name); }
/** + * Suited for: Shuttle AK38N: VIA KT333CF + VIA VT8235 + ITE IT8705F + */ +static int shuttle_ak38n(const char *name) +{ + max_rom_decode.parallel = 256 * 1024; + return it8705f_write_enable(0x2e, name); +} + +/** * Find the runtime registers of an SMSC Super I/O, after verifying its * chip ID. * @@ -1079,7 +1087,7 @@ {0x10DE, 0x0030, 0x1043, 0x818a, 0x8086, 0x100E, 0x1043, 0x80EE, NULL, NULL, "ASUS", "P5ND2-SLI Deluxe", board_asus_p5nd2_sli}, {0x1106, 0x3149, 0x1565, 0x3206, 0x1106, 0x3344, 0x1565, 0x1202, NULL, NULL, "Biostar", "P4M80-M4", it8705_rom_write_enable}, {0x8086, 0x3590, 0x1028, 0x016c, 0x1000, 0x0030, 0x1028, 0x016c, NULL, NULL, "Dell", "PowerEdge 1850", ich5_gpio23_raise}, - {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, NULL, NULL, "Elitegroup", "K7VTA3", it8705f_write_enable_2e}, + {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, NULL, NULL, "Elitegroup", "K7VTA3", elitegroup_k7vta3}, {0x1106, 0x3177, 0x1106, 0x3177, 0x1106, 0x3059, 0x1695, 0x3005, NULL, NULL, "EPoX", "EP-8K5A2", board_epox_ep_8k5a2}, {0x10EC, 0x8139, 0x1695, 0x9001, 0x11C1, 0x5811, 0x1695, 0x9015, NULL, NULL, "EPoX", "EP-8RDA3+", board_epox_ep_8rda3plus}, {0x8086, 0x7110, 0, 0, 0x8086, 0x7190, 0, 0, "epox", "ep-bx3", "EPoX", "EP-BX3", board_epox_ep_bx3}, @@ -1105,7 +1113,7 @@ {0x1106, 0x0571, 0x1462, 0x7120, 0, 0, 0, 0, "msi", "kt4v", "MSI", "MS-6712 (KT4V)", board_msi_kt4v}, {0x8086, 0x2658, 0x1462, 0x7046, 0x1106, 0x3044, 0x1462, 0x046d, NULL, NULL, "MSI", "MS-7046", ich6_gpio19_raise}, {0x10de, 0x005e, 0, 0, 0, 0, 0, 0, "msi", "k8n-neo3", "MSI", "MS-7135 (K8N Neo3)", w83627thf_gpio4_4_raise_4e}, - {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, NULL, NULL, "Shuttle", "AK38N", it8705f_write_enable_2e}, + {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, NULL, NULL, "Shuttle", "AK38N", shuttle_ak38n}, {0x10DE, 0x0050, 0x1297, 0x5036, 0x1412, 0x1724, 0x1297, 0x5036, NULL, NULL, "Shuttle", "FN25", board_shuttle_fn25}, {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x3058, 0x15DD, 0x7609, NULL, NULL, "Soyo", "SY-7VCA", board_soyo_sy_7vca}, {0x8086, 0x1076, 0x8086, 0x1176, 0x1106, 0x3059, 0x10f1, 0x2498, NULL, NULL, "Tyan", "S2498 (Tomcat K7M)", board_asus_a7v8x_mx},
On Fri, Oct 23, 2009 at 03:33:33PM +0200, Carl-Daniel Hailfinger wrote:
OK, completely rewritten attempt. I'm reusing Uwe's changelog.
Most of it looks good, but there are some changeѕ required.
- The checks have to be done later in the code, after the chip has been detected, so that we only check the sizes for the chip we actually find, not for all the chips we probe for. I moved the checks and simplified them a bit (I hope).
- Use printf instead of printf_debug so that users will see the error without having to use -V.
- Abort if the chip is bigger than the supported ROM decode size. Continuing will result in a non-bootable system in almost all cases. Adding a --force option later is fine with me, but I think the default should be to abort.
Attached is an updated patch with the above changes. I tested it on the Shuttle AK38N (all operations), output looks like this:
$ flashrom v0.9.1-r753 No coreboot table found. Found chipset "VIA VT8235", enabling flash write... OK. This chipset supports the following protocols: Non-SPI. Disabling flash write protection for board "Shuttle AK38N"... OK. Calibrating delay loop... OK. Found chip "SST SST39SF040" (512 KB, Parallel) at physical address 0xfff80000. Chipset/board/programmer only supports a max. size of 256 KB. ABORTING.
I also tested that with a 256KB chip all operations still work fine.
Additionally I tested a 512KB chip on ASUS P4B266 (FWH) with a (simulated) max. decode size of 256KB and 512KB to ensure that non-parallel chips also work OK with the code.
The updated patch is
Acked-by: Uwe Hermann uwe@hermann-uwe.de
Feel free to commit.
@@ -977,6 +1004,8 @@ size = flash->total_size * 1024; buf = (uint8_t *) calloc(size, sizeof(char));
- // FIXME: Check for decode size again?
- if (erase_it) { if (flash->tested & TEST_BAD_ERASE) { fprintf(stderr, "Erase is not working on this chip. ");
Not sure about this one. Why would an additional check be needed? According to my tests there's no need for additional checks.
Uwe.
On 28.10.2009 03:59, Uwe Hermann wrote:
Most of it looks good, but there are some changeѕ required.
- The checks have to be done later in the code, after the chip has been detected, so that we only check the sizes for the chip we actually find, not for all the chips we probe for. I moved the checks and simplified them a bit (I hope).
This breaks on Ron's setup where the chip is too big to be detected. That's why I wanted to get the warning during probe time.
Index: flashrom.c
--- flashrom.c (revision 753) +++ flashrom.c (working copy) @@ -449,6 +452,25 @@ flash->vendor, flash->name, flash->total_size, flashbuses_to_text(flash->bustype), base);
- if ((buses_common & CHIP_BUSTYPE_PARALLEL) &&
(max_rom_decode.parallel < flash->total_size * 1024))
tmpsize = max_rom_decode.parallel;
- if ((buses_common & CHIP_BUSTYPE_LPC) &&
(max_rom_decode.lpc < flash->total_size * 1024))
tmpsize = max_rom_decode.lpc;
- if ((buses_common & CHIP_BUSTYPE_FWH) &&
(max_rom_decode.fwh < flash->total_size * 1024))
tmpsize = max_rom_decode.fwh;
- if ((buses_common & CHIP_BUSTYPE_SPI) &&
(max_rom_decode.spi < flash->total_size * 1024))
tmpsize = max_rom_decode.spi;
- if (tmpsize != 0xffffffff) {
printf("Chipset/board/programmer only supports "
"a max. size of %u KB. ABORTING.\n", tmpsize / 1024);
programmer_shutdown();
exit(1);
- }
I had this code in an earlier version, but decided to change it because 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. My patch was missing the bus-specific error messages, so I can't blame you for refactoring.
Would it be OK for you if I moved the size checking to a separate function size_supported(buses_common, size, loglevel) which can be called during probe (with printf_debug level) and before any read/write/erase action (with printf_error level)? That way, we avoid cluttering the main loop, get free checking during probe, and can abort before any action happens.
- Use printf instead of printf_debug so that users will see the error without having to use -V.
OK. On a related note, we really need printf_warn/printf_notice/...
- Abort if the chip is bigger than the supported ROM decode size. Continuing will result in a non-bootable system in almost all cases. Adding a --force option later is fine with me, but I think the default should be to abort.
Yes.
Attached is an updated patch with the above changes. I tested it on the Shuttle AK38N (all operations), output looks like this:
$ flashrom v0.9.1-r753 No coreboot table found. Found chipset "VIA VT8235", enabling flash write... OK. This chipset supports the following protocols: Non-SPI. Disabling flash write protection for board "Shuttle AK38N"... OK. Calibrating delay loop... OK. Found chip "SST SST39SF040" (512 KB, Parallel) at physical address 0xfff80000. Chipset/board/programmer only supports a max. size of 256 KB. ABORTING.
I also tested that with a 256KB chip all operations still work fine.
Additionally I tested a 512KB chip on ASUS P4B266 (FWH) with a (simulated) max. decode size of 256KB and 512KB to ensure that non-parallel chips also work OK with the code.
The updated patch is
Acked-by: Uwe Hermann uwe@hermann-uwe.de
Feel free to commit.
Thanks. I hope to clarify one or two things in an additional round, then commit.
Index: chipset_enable.c
--- chipset_enable.c (revision 753) +++ chipset_enable.c (working copy) @@ -536,6 +582,9 @@ reg8 |= BIOS_ROM_POSITIVE_DECODE; pci_write_byte(dev, DECODE_CONTROL_REG2, reg8);
- /* No idea which buses this limit applies to. */
- //max_rom_decode.lpc = 16 * 1024 * 1024;
- return 0;
}
This limit was originally added by you, but I commented out because I was not sure if this was a LPC limit or a parallel limit or a FWH limit. Since you are the original author, can you shed some light on this?
@@ -977,6 +1004,8 @@ size = flash->total_size * 1024; buf = (uint8_t *) calloc(size, sizeof(char));
- // FIXME: Check for decode size again?
- if (erase_it) { if (flash->tested & TEST_BAD_ERASE) { fprintf(stderr, "Erase is not working on this chip. ");
Not sure about this one. Why would an additional check be needed? According to my tests there's no need for additional checks.
The idea behind this was to have a warning during probe (which does fail for some chips) and abort before the first real read/write/erase action. That way, a user can find out why probe might not have worked, and will be stopped before he/she gets incorrect results.
What do you think? If you want me to post an updated patch for easier review, just say so.
Regards, Carl-Daniel
OK, here's the current megapatch. Will split later, right now I just want to get this out for review.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-rom_decode_check/flash.h =================================================================== --- flashrom-rom_decode_check/flash.h (Revision 753) +++ flashrom-rom_decode_check/flash.h (Arbeitskopie) @@ -352,9 +352,17 @@ void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask); int board_flash_enable(const char *vendor, const char *part);
+struct decode_sizes { + uint32_t parallel; + uint32_t lpc; + uint32_t fwh; + uint32_t spi; +}; + /* chipset_enable.c */ extern enum chipbustype buses_supported; int chipset_flash_enable(void); +extern struct decode_sizes max_rom_decode;
extern unsigned long flashbase;
Index: flashrom-rom_decode_check/chipset_enable.c =================================================================== --- flashrom-rom_decode_check/chipset_enable.c (Revision 753) +++ flashrom-rom_decode_check/chipset_enable.c (Arbeitskopie) @@ -41,6 +41,12 @@ */
enum chipbustype buses_supported = CHIP_BUSTYPE_NONSPI; +struct decode_sizes max_rom_decode = { + .parallel = 0xffffffff, + .lpc = 0xffffffff, + .fwh = 0xffffffff, + .spi = 0xffffffff +};
extern int ichspi_lock;
@@ -204,34 +210,73 @@ uint32_t fwh_conf; int i; char *idsel = NULL; + int tmp; + int max_decode_fwh_idsel = 0; + int max_decode_fwh_decode = 0; + int contiguous = 1;
- /* Ignore all legacy ranges below 1 MB. */ + /* Ignore all legacy ranges below 1 MB. + * We currently only support flashing the chip which responds to + * IDSEL=0. To support IDSEL!=0, flashbase and decode size calculations + * have to be adjusted. + */ /* FWH_SEL1 */ fwh_conf = pci_read_long(dev, 0xd0); - for (i = 7; i >= 0; i--) + for (i = 7; i >= 0; i--) { + tmp = (fwh_conf >> (i * 4)) & 0xf; printf_debug("\n0x%08x/0x%08x FWH IDSEL: 0x%x", (0x1ff8 + i) * 0x80000, (0x1ff0 + i) * 0x80000, - (fwh_conf >> (i * 4)) & 0xf); + tmp); + if ((tmp == 0) && contiguous) { + max_decode_fwh_idsel = (8 - i) * 0x80000; + } else { + contiguous = 0; + } + } /* FWH_SEL2 */ fwh_conf = pci_read_word(dev, 0xd4); - for (i = 3; i >= 0; i--) + for (i = 3; i >= 0; i--) { + tmp = (fwh_conf >> (i * 4)) & 0xf; printf_debug("\n0x%08x/0x%08x FWH IDSEL: 0x%x", (0xff4 + i) * 0x100000, (0xff0 + i) * 0x100000, - (fwh_conf >> (i * 4)) & 0xf); + tmp); + if ((tmp == 0) && contiguous) { + max_decode_fwh_idsel = (8 - i) * 0x100000; + } else { + contiguous = 0; + } + } + contiguous = 1; /* FWH_DEC_EN1 */ fwh_conf = pci_read_word(dev, 0xd8); - for (i = 7; i >= 0; i--) + for (i = 7; i >= 0; i--) { + tmp = (fwh_conf >> (i + 0x8)) & 0x1; printf_debug("\n0x%08x/0x%08x FWH decode %sabled", (0x1ff8 + i) * 0x80000, (0x1ff0 + i) * 0x80000, - (fwh_conf >> (i + 0x8)) & 0x1 ? "en" : "dis"); - for (i = 3; i >= 0; i--) + tmp ? "en" : "dis"); + if ((tmp == 0) && contiguous) { + max_decode_fwh_decode = (8 - i) * 0x80000; + } else { + contiguous = 0; + } + } + for (i = 3; i >= 0; i--) { + tmp = (fwh_conf >> i) & 0x1; printf_debug("\n0x%08x/0x%08x FWH decode %sabled", (0xff4 + i) * 0x100000, (0xff0 + i) * 0x100000, - (fwh_conf >> i) & 0x1 ? "en" : "dis"); + tmp ? "en" : "dis"); + if ((tmp == 0) && contiguous) { + max_decode_fwh_decode = (8 - i) * 0x100000; + } else { + contiguous = 0; + } + } + max_rom_decode.fwh = min(max_decode_fwh_idsel, max_decode_fwh_decode); + printf_debug("\nMaximum FWH chip size: 0x%x bytes", max_rom_decode.fwh);
if (programmer_param) idsel = strstr(programmer_param, "fwh_idsel="); @@ -244,8 +289,13 @@ printf("\nSetting IDSEL=0x%x for top 16 MB", fwh_conf); pci_write_long(dev, 0xd0, fwh_conf); pci_write_word(dev, 0xd4, fwh_conf); + /* FIXME: Decode settings are not changed. */ }
+ /* If we're called by enable_flash_ich_dc, it will override + * buses_supported anyway. + */ + buses_supported = CHIP_BUSTYPE_FWH; return enable_flash_ich(dev, name, 0xdc); }
@@ -258,6 +308,7 @@ { uint32_t mmio_base;
+ /* Do we really need no write enable? */ mmio_base = (pci_read_long(dev, 0xbc)) << 8; printf_debug("MMIO base at = 0x%x\n", mmio_base); spibar = physmap("VT8237S MMIO registers", mmio_base, 0x70); @@ -312,8 +363,7 @@ */
if (ich_generation == 7 && bbs == ICH_STRAP_LPC) { - /* Not sure if it speaks LPC as well. */ - buses_supported = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH; + buses_supported = CHIP_BUSTYPE_FWH; /* No further SPI initialization required */ return ret; } @@ -325,16 +375,14 @@ spibar_offset = 0x3020; break; case 8: - /* Not sure if it speaks LPC as well. */ - buses_supported = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI; + buses_supported = CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI; spi_controller = SPI_CONTROLLER_ICH9; spibar_offset = 0x3020; break; case 9: case 10: default: /* Future version might behave the same */ - /* Not sure if it speaks LPC as well. */ - buses_supported = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI; + buses_supported = CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI; spi_controller = SPI_CONTROLLER_ICH9; spibar_offset = 0x3800; break; @@ -515,14 +563,22 @@
#define DECODE_CONTROL_REG2 0x5b /* F0 index 0x5b */ #define ROM_AT_LOGIC_CONTROL_REG 0x52 /* F0 index 0x52 */ +#define CS5530_RESET_CONTROL_REG 0x44 /* F0 index 0x44 */ +#define CS5530_USB_SHADOW_REG 0x43 /* F0 index 0x43 */
#define LOWER_ROM_ADDRESS_RANGE (1 << 0) #define ROM_WRITE_ENABLE (1 << 1) #define UPPER_ROM_ADDRESS_RANGE (1 << 2) #define BIOS_ROM_POSITIVE_DECODE (1 << 5) +#define CS5530_ISA_MASTER (1 << 7) +#define CS5530_ENABLE_SA2320 (1 << 2) +#define CS5530_ENABLE_SA20 (1 << 6)
+ buses_supported = CHIP_BUSTYPE_PARALLEL; /* Decode 0x000E0000-0x000FFFFF (128 KB), not just 64 KB, and * decode 0xFF000000-0xFFFFFFFF (16 MB), not just 256 KB. + * FIXME: Should we really touch the low mapping below 1 MB? Flashrom + * ignores that region completely. * Make the configured ROM areas writable. */ reg8 = pci_read_byte(dev, ROM_AT_LOGIC_CONTROL_REG); @@ -536,6 +592,24 @@ reg8 |= BIOS_ROM_POSITIVE_DECODE; pci_write_byte(dev, DECODE_CONTROL_REG2, reg8);
+ reg8 = pci_read_byte(dev, CS5530_RESET_CONTROL_REG); + if (reg8 & CS5530_ISA_MASTER) { + /* We have A0-A23 available. */ + max_rom_decode.parallel = 16 * 1024 * 1024; + } else { + reg8 = pci_read_byte(dev, CS5530_USB_SHADOW_REG); + if (reg8 & CS5530_ENABLE_SA2320) { + /* We have A0-19, A20-A23 available. */ + max_rom_decode.parallel = 16 * 1024 * 1024; + } else if (reg8 & CS5530_ENABLE_SA20) { + /* We have A0-19, A20 available. */ + max_rom_decode.parallel = 2 * 1024 * 1024; + } else { + /* A20 and above are not active. */ + max_rom_decode.parallel = 1024 * 1024; + } + } + return 0; }
Index: flashrom-rom_decode_check/flashrom.c =================================================================== --- flashrom-rom_decode_check/flashrom.c (Revision 753) +++ flashrom-rom_decode_check/flashrom.c (Arbeitskopie) @@ -299,6 +299,15 @@ 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,63 @@ return ret; }
+int check_max_decode(enum chipbustype buses, unsigned int size, int warn) +{ + int limitexceeded = 0; + if ((buses & CHIP_BUSTYPE_PARALLEL) && + (max_rom_decode.parallel < size)) { + limitexceeded++; + printf_debug("Chip size %u is bigger than supported " + "size %u of chipset/board/programmer " + "for Parallel interface, " + "probe/read/erase/write may fail. ", size, + max_rom_decode.parallel); + } + if ((buses & CHIP_BUSTYPE_LPC) && + (max_rom_decode.lpc < size)) { + limitexceeded++; + printf_debug("Chip size %u is bigger than supported " + "size %u of chipset/board/programmer " + "for LPC interface, " + "probe/read/erase/write may fail. ", size, + max_rom_decode.lpc); + } + if ((buses & CHIP_BUSTYPE_FWH) && + (max_rom_decode.fwh < size)) { + limitexceeded++; + printf_debug("Chip size %u is bigger than supported " + "size %u of chipset/board/programmer " + "for FWH interface, " + "probe/read/erase/write may fail. ", size, + max_rom_decode.fwh); + } + if ((buses & CHIP_BUSTYPE_SPI) && + (max_rom_decode.spi < size)) { + limitexceeded++; + printf_debug("Chip size %u is bigger than supported " + "size %u of chipset/board/programmer " + "for SPI interface, " + "probe/read/erase/write may fail. ", size, + max_rom_decode.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; + unsigned int size; + enum chipbustype buses_common; char *tmp;
for (flash = first_flash; flash && flash->name; flash++) { @@ -413,7 +475,8 @@ 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 +487,7 @@ }
size = flash->total_size * 1024; + check_max_decode(buses_common, size, 0);
base = flashbase ? flashbase : (0xffffffff - size + 1); flash->virtual_memory = (chipaddr)programmer_map_flash_region("flash chip", base, size); @@ -975,6 +1039,14 @@ verify_it = 1;
size = flash->total_size * 1024; + if (check_max_decode((buses_supported & flash->bustype), size, 1) && + (!force)) { + fprintf(stderr, "This chip is too big for this programmer. " + "Details are given in verbose mode. You can override " + "this check with --force."); + programmer_shutdown(); + return 1; + } buf = (uint8_t *) calloc(size, sizeof(char));
if (erase_it) { Index: flashrom-rom_decode_check/board_enable.c =================================================================== --- flashrom-rom_decode_check/board_enable.c (Revision 753) +++ flashrom-rom_decode_check/board_enable.c (Arbeitskopie) @@ -804,16 +804,24 @@ }
/** - * Suited for: - * - Shuttle AK38N: VIA KT333CF + VIA VT8235 + ITE IT8705F - * - Elitegroup K7VTA3: VIA Apollo KT266/A/333 + VIA VT8235 + ITE IT8705F + * Suited for: Elitegroup K7VTA3: VIA Apollo KT266/A/333 + VIA VT8235 + ITE IT8705F */ -static int it8705f_write_enable_2e(const char *name) +static int elitegroup_k7vta3(const char *name) { + max_rom_decode.parallel = 256 * 1024; return it8705f_write_enable(0x2e, name); }
/** + * Suited for: Shuttle AK38N: VIA KT333CF + VIA VT8235 + ITE IT8705F + */ +static int shuttle_ak38n(const char *name) +{ + max_rom_decode.parallel = 256 * 1024; + return it8705f_write_enable(0x2e, name); +} + +/** * Find the runtime registers of an SMSC Super I/O, after verifying its * chip ID. * @@ -1079,7 +1087,7 @@ {0x10DE, 0x0030, 0x1043, 0x818a, 0x8086, 0x100E, 0x1043, 0x80EE, NULL, NULL, "ASUS", "P5ND2-SLI Deluxe", board_asus_p5nd2_sli}, {0x1106, 0x3149, 0x1565, 0x3206, 0x1106, 0x3344, 0x1565, 0x1202, NULL, NULL, "Biostar", "P4M80-M4", it8705_rom_write_enable}, {0x8086, 0x3590, 0x1028, 0x016c, 0x1000, 0x0030, 0x1028, 0x016c, NULL, NULL, "Dell", "PowerEdge 1850", ich5_gpio23_raise}, - {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, NULL, NULL, "Elitegroup", "K7VTA3", it8705f_write_enable_2e}, + {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, NULL, NULL, "Elitegroup", "K7VTA3", elitegroup_k7vta3}, {0x1106, 0x3177, 0x1106, 0x3177, 0x1106, 0x3059, 0x1695, 0x3005, NULL, NULL, "EPoX", "EP-8K5A2", board_epox_ep_8k5a2}, {0x10EC, 0x8139, 0x1695, 0x9001, 0x11C1, 0x5811, 0x1695, 0x9015, NULL, NULL, "EPoX", "EP-8RDA3+", board_epox_ep_8rda3plus}, {0x8086, 0x7110, 0, 0, 0x8086, 0x7190, 0, 0, "epox", "ep-bx3", "EPoX", "EP-BX3", board_epox_ep_bx3}, @@ -1105,7 +1113,7 @@ {0x1106, 0x0571, 0x1462, 0x7120, 0, 0, 0, 0, "msi", "kt4v", "MSI", "MS-6712 (KT4V)", board_msi_kt4v}, {0x8086, 0x2658, 0x1462, 0x7046, 0x1106, 0x3044, 0x1462, 0x046d, NULL, NULL, "MSI", "MS-7046", ich6_gpio19_raise}, {0x10de, 0x005e, 0, 0, 0, 0, 0, 0, "msi", "k8n-neo3", "MSI", "MS-7135 (K8N Neo3)", w83627thf_gpio4_4_raise_4e}, - {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, NULL, NULL, "Shuttle", "AK38N", it8705f_write_enable_2e}, + {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, NULL, NULL, "Shuttle", "AK38N", shuttle_ak38n}, {0x10DE, 0x0050, 0x1297, 0x5036, 0x1412, 0x1724, 0x1297, 0x5036, NULL, NULL, "Shuttle", "FN25", board_shuttle_fn25}, {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x3058, 0x15DD, 0x7609, NULL, NULL, "Soyo", "SY-7VCA", board_soyo_sy_7vca}, {0x8086, 0x1076, 0x8086, 0x1176, 0x1106, 0x3059, 0x10f1, 0x2498, NULL, NULL, "Tyan", "S2498 (Tomcat K7M)", board_asus_a7v8x_mx},