2010/10/21 Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
New version. This one should address most review comments.
With -p nic3com:
Erase: $ sudo ./flashrom -p nic3com -V -E flashrom v0.9.3-r1216 on Linux 2.6.35-ARCH (i686), built with libpci 3.1.7, GCC 4.5.1, little endian flashrom is free software, get the source code at http://www.flashrom.org
Calibrating delay loop... OS timer resolution is 1 usecs, 1936M loops per second, 10 myus = 10 us, 100 myus = 97 us, 1000 myus = 972 us, 10000 myus = 11516 us, 4 myus = 5 us, OK. Initializing nic3com programmer Found "3COM 3C905C: EtherLink 10/100 PCI (TX)" (10b7:9200, BDF 01:01.0). Requested BAR is IO // snip Found chip "Atmel AT49BV512" (64 KB, Parallel) at physical address 0xffff0000. //snip === This flash part has status UNTESTED for operations: PROBE READ ERASE WRITE The test status of this chip may have been updated in the latest development version of flashrom. If you are running the latest development version, please email a report to flashrom@flashrom.org if any of the above operations work correctly for you with this flash part. Please include the flashrom output with the additional -V option for all operations you tested (-V, -Vr, -Vw, -VE), and mention which mainboard or programmer you tested. Please mention your board in the subject line. Thanks for your help! Erasing and writing flash chip... Looking at blockwise erase function 0... trying... 0x000000-0x00ffff:E
Done.
If anyone feels adventurous, I would love to see logs on Intel/VIA chipsets with SPI (preferably locked down chipsets or with r1193 reverted).
On Intel hardware (abusing the wide concept of "chipset" :)):
Write (yes, I have a backup file): $ sudo ./flashrom -p nicintel_spi -w nicintel_spi.rom -c M25P10.RES -V flashrom v0.9.3-r1216 on Linux 2.6.35-ARCH (i686), built with libpci 3.1.7, GCC 4.5.1, little endian flashrom is free software, get the source code at http://www.flashrom.org
Calibrating delay loop... OS timer resolution is 1 usecs, 1907M loops per second, 10 myus = 10 us, 100 myus = 96 us, 1000 myus = 1014 us, 10000 myus = 10801 us, 4 myus = 4 us, OK. Initializing nicintel_spi programmer Found "Intel 82541PI Gigabit Ethernet Controller" (8086:107c, BDF 01:03.0). Requested BAR is MEM, 32bit, not prefetchable Probing for ST M25P10.RES, 128 KB: probe_spi_res1: id 0x10 Chip status register is 00 Found chip "ST M25P10.RES" (128 KB, SPI) at physical address 0xfffe0000. === This flash part has status UNTESTED for operations: PROBE READ ERASE WRITE The test status of this chip may have been updated in the latest development version of flashrom. If you are running the latest development version, please email a report to flashrom@flashrom.org if any of the above operations work correctly for you with this flash part. Please include the flashrom output with the additional -V option for all operations you tested (-V, -Vr, -Vw, -VE), and mention which mainboard or programmer you tested. Please mention your board in the subject line. Thanks for your help! Reading old flash chip contents... Erasing and writing flash chip... Looking at blockwise erase function 0... trying... 0x000000-0x007fff:S, 0x008000-0x00ffff:EW, 0x010000-0x017fff:EW, 0x018000-0x01ffff:S
Done. Verifying flash... VERIFY FAILED at 0x00008000! Expected=0xc6, Read=0x15, failed byte count from 0x00000000-0x0001ffff: 0x872f Your flash chip is in an unknown state. Get help on IRC at irc.freenode.net (channel #flashrom) or mail flashrom@flashrom.org with FAILED: your board name in the subject line! ------------------------------------------------------------------------------- DO NOT REBOOT OR POWEROFF!
Erase: $ sudo ./flashrom -p nicintel_spi -E -c M25P10.RES -V flashrom v0.9.3-r1216 on Linux 2.6.35-ARCH (i686), built with libpci 3.1.7, GCC 4.5.1, little endian flashrom is free software, get the source code at http://www.flashrom.org
Calibrating delay loop... OS timer resolution is 1 usecs, 1833M loops per second, 10 myus = 9 us, 100 myus = 92 us, 1000 myus = 917 us, 10000 myus = 11106 us, 4 myus = 4 us, OK. Initializing nicintel_spi programmer Found "Intel 82541PI Gigabit Ethernet Controller" (8086:107c, BDF 01:03.0). Requested BAR is MEM, 32bit, not prefetchable Probing for ST M25P10.RES, 128 KB: probe_spi_res1: id 0x10 Chip status register is 00 Found chip "ST M25P10.RES" (128 KB, SPI) at physical address 0xfffe0000. === This flash part has status UNTESTED for operations: PROBE READ ERASE WRITE The test status of this chip may have been updated in the latest development version of flashrom. If you are running the latest development version, please email a report to flashrom@flashrom.org if any of the above operations work correctly for you with this flash part. Please include the flashrom output with the additional -V option for all operations you tested (-V, -Vr, -Vw, -VE), and mention which mainboard or programmer you tested. Please mention your board in the subject line. Thanks for your help! Erasing and writing flash chip... Looking at blockwise erase function 0... trying... 0x000000-0x007fff:E, 0x008000-0x00ffff:E, 0x010000-0x017fff:E, 0x018000-0x01ffff:E
Done.
Tests on boards which need a board enable and where you can lock down
the whole chip or parts of it would be appreciated as well.
Mainboard that needs a board enable:
Erase: $ sudo ./flashrom -V -E flashrom v0.9.3-r1216 on Linux 2.6.35-ARCH (i686), built with libpci 3.1.7, GCC 4.5.1, little endian flashrom is free software, get the source code at http://www.flashrom.org
Calibrating delay loop... OS timer resolution is 1 usecs, 1945M loops per second, 10 myus = 10 us, 100 myus = 98 us, 1000 myus = 973 us, 10000 myus = 13546 us, 4 myus = 4 us, OK. Initializing internal programmer No coreboot table found. sh: dmidecode: command not found dmidecode execution unsucessfull - continuing without DMI info Found chipset "Intel ICH5/ICH5R", enabling flash write... chipset PCI ID is 8086:24d0, BIOS Lock Enable: disabled, BIOS Write Enable: enabled, BIOS_CNTL is 0x1 OK. This chipset supports the following protocols: FWH. Disabling flash write protection for board "ASRock P4i65GV"... Intel ICH LPC Bridge: Raising GPIO23. OK. // snip Found chip "PMC Pm49FL004" (512 KB, LPC,FWH) at physical address 0xfff80000. // snip === This flash part has status UNTESTED for operations: WRITE The test status of this chip may have been updated in the latest development version of flashrom. If you are running the latest development version, please email a report to flashrom@flashrom.org if any of the above operations work correctly for you with this flash part. Please include the flashrom output with the additional -V option for all operations you tested (-V, -Vr, -Vw, -VE), and mention which mainboard or programmer you tested. Please mention your board in the subject line. Thanks for your help! Erasing and writing flash chip... Looking at blockwise erase function 0... trying... 0x000000-0x000fff:E, 0x001000-0x001fff:E, 0x002000-0x002fff:E, 0x003000-0x003fff:E, 0x004000-0x004fff:E, 0x005000-0x005fff:E, 0x006000-0x006fff:E, 0x007000-0x007fff:E, 0x008000-0x008fff:E, 0x009000-0x009fff:E, 0x00a000-0x00afff:E, 0x00b000-0x00bfff:E, 0x00c000-0x00cfff:E, 0x00d000-0x00dfff:E, 0x00e000-0x00efff:E, 0x00f000-0x00ffff:E, 0x010000-0x010fff:E, 0x011000-0x011fff:E, 0x012000-0x012fff:E, 0x013000-0x013fff:E, 0x014000-0x014fff:E, 0x015000-0x015fff:E, 0x016000-0x016fff:E, 0x017000-0x017fff:E, 0x018000-0x018fff:E, 0x019000-0x019fff:E, 0x01a000-0x01afff:E, 0x01b000-0x01bfff:E, 0x01c000-0x01cfff:E, 0x01d000-0x01dfff:E, 0x01e000-0x01efff:E, 0x01f000-0x01ffff:E, 0x020000-0x020fff:E, 0x021000-0x021fff:E, 0x022000-0x022fff:E, 0x023000-0x023fff:E, 0x024000-0x024fff:E, 0x025000-0x025fff:E, 0x026000-0x026fff:E, 0x027000-0x027fff:E, 0x028000-0x028fff:E, 0x029000-0x029fff:E, 0x02a000-0x02afff:E, 0x02b000-0x02bfff:E, 0x02c000-0x02cfff:E, 0x02d000-0x02dfff:E, 0x02e000-0x02efff:E, 0x02f000-0x02ffff:E, 0x030000-0x030fff:E, 0x031000-0x031fff:E, 0x032000-0x032fff:E, 0x033000-0x033fff:E, 0x034000-0x034fff:E, 0x035000-0x035fff:E, 0x036000-0x036fff:E, 0x037000-0x037fff:E, 0x038000-0x038fff:E, 0x039000-0x039fff:E, 0x03a000-0x03afff:E, 0x03b000-0x03bfff:E, 0x03c000-0x03cfff:E, 0x03d000-0x03dfff:E, 0x03e000-0x03efff:E, 0x03f000-0x03ffff:E, 0x040000-0x040fff:E, 0x041000-0x041fff:E, 0x042000-0x042fff:E, 0x043000-0x043fff:E, 0x044000-0x044fff:E, 0x045000-0x045fff:E, 0x046000-0x046fff:E, 0x047000-0x047fff:E, 0x048000-0x048fff:E, 0x049000-0x049fff:E, 0x04a000-0x04afff:E, 0x04b000-0x04bfff:E, 0x04c000-0x04cfff:E, 0x04d000-0x04dfff:E, 0x04e000-0x04efff:E, 0x04f000-0x04ffff:E, 0x050000-0x050fff:E, 0x051000-0x051fff:E, 0x052000-0x052fff:E, 0x053000-0x053fff:E, 0x054000-0x054fff:E, 0x055000-0x055fff:E, 0x056000-0x056fff:E, 0x057000-0x057fff:E, 0x058000-0x058fff:E, 0x059000-0x059fff:E, 0x05a000-0x05afff:E, 0x05b000-0x05bfff:E, 0x05c000-0x05cfff:E, 0x05d000-0x05dfff:E, 0x05e000-0x05efff:E, 0x05f000-0x05ffff:E, 0x060000-0x060fff:E, 0x061000-0x061fff:E, 0x062000-0x062fff:E, 0x063000-0x063fff:E, 0x064000-0x064fff:E, 0x065000-0x065fff:E, 0x066000-0x066fff:E, 0x067000-0x067fff:E, 0x068000-0x068fff:E, 0x069000-0x069fff:E, 0x06a000-0x06afff:E, 0x06b000-0x06bfff:E, 0x06c000-0x06cfff:E, 0x06d000-0x06dfff:E, 0x06e000-0x06efff:E, 0x06f000-0x06ffff:E, 0x070000-0x070fff:E, 0x071000-0x071fff:E, 0x072000-0x072fff:E, 0x073000-0x073fff:E, 0x074000-0x074fff:E, 0x075000-0x075fff:E, 0x076000-0x076fff:E, 0x077000-0x077fff:E, 0x078000-0x078fff:E, 0x079000-0x079fff:E, 0x07a000-0x07afff:E, 0x07b000-0x07bfff:E, 0x07c000-0x07cfff:E, 0x07d000-0x07dfff:E, 0x07e000-0x07efff:E, 0x07f000-0x07ffff:E
Done.
Write: $ sudo ./flashrom -V -w ~/asrock_p4i65gv_512KB.rom flashrom v0.9.3-r1216 on Linux 2.6.35-ARCH (i686), built with libpci 3.1.7, GCC 4.5.1, little endian flashrom is free software, get the source code at http://www.flashrom.org
Calibrating delay loop... OS timer resolution is 1 usecs, 1886M loops per second, 10 myus = 9 us, 100 myus = 95 us, 1000 myus = 1032 us, 10000 myus = 9180 us, 4 myus = 4 us, OK. Initializing internal programmer No coreboot table found. sh: dmidecode: command not found dmidecode execution unsucessfull - continuing without DMI info Found chipset "Intel ICH5/ICH5R", enabling flash write... chipset PCI ID is 8086:24d0, BIOS Lock Enable: disabled, BIOS Write Enable: enabled, BIOS_CNTL is 0x1 OK. This chipset supports the following protocols: FWH. Disabling flash write protection for board "ASRock P4i65GV"... Intel ICH LPC Bridge: Raising GPIO23. OK. // snip Found chip "PMC Pm49FL004" (512 KB, LPC,FWH) at physical address 0xfff80000. // snip === This flash part has status UNTESTED for operations: WRITE The test status of this chip may have been updated in the latest development version of flashrom. If you are running the latest development version, please email a report to flashrom@flashrom.org if any of the above operations work correctly for you with this flash part. Please include the flashrom output with the additional -V option for all operations you tested (-V, -Vr, -Vw, -VE), and mention which mainboard or programmer you tested. Please mention your board in the subject line. Thanks for your help! Flash image seems to be a legacy BIOS. Disabling checks. Reading old flash chip contents... Erasing and writing flash chip... Looking at blockwise erase function 0... trying... 0x000000-0x000fff:EW, 0x001000-0x001fff:EW, 0x002000-0x002fff:EW, 0x003000-0x003fff:EW, 0x004000-0x004fff:EW, 0x005000-0x005fff:EW, 0x006000-0x006fff:EW, 0x007000-0x007fff:EW, 0x008000-0x008fff:EW, 0x009000-0x009fff:EW, 0x00a000-0x00afff:EW, 0x00b000-0x00bfff:EW, 0x00c000-0x00cfff:EW, 0x00d000-0x00dfff:EW, 0x00e000-0x00efff:EW, 0x00f000-0x00ffff:EW, 0x010000-0x010fff:EW, 0x011000-0x011fff:EW, 0x012000-0x012fff:W, 0x013000-0x013fff:W, 0x014000-0x014fff:W, 0x015000-0x015fff:W, 0x016000-0x016fff:W, 0x017000-0x017fff:W, 0x018000-0x018fff:W, 0x019000-0x019fff:W, 0x01a000-0x01afff:W, 0x01b000-0x01bfff:W, 0x01c000-0x01cfff:W, 0x01d000-0x01dfff:W, 0x01e000-0x01efff:W, 0x01f000-0x01ffff:W, 0x020000-0x020fff:W, 0x021000-0x021fff:W, 0x022000-0x022fff:W, 0x023000-0x023fff:W, 0x024000-0x024fff:W, 0x025000-0x025fff:W, 0x026000-0x026fff:W, 0x027000-0x027fff:W, 0x028000-0x028fff:W, 0x029000-0x029fff:W, 0x02a000-0x02afff:W, 0x02b000-0x02bfff:W, 0x02c000-0x02cfff:W, 0x02d000-0x02dfff:W, 0x02e000-0x02efff:W, 0x02f000-0x02ffff:W, 0x030000-0x030fff:W, 0x031000-0x031fff:W, 0x032000-0x032fff:W, 0x033000-0x033fff:W, 0x034000-0x034fff:W, 0x035000-0x035fff:W, 0x036000-0x036fff:W, 0x037000-0x037fff:W, 0x038000-0x038fff:W, 0x039000-0x039fff:W, 0x03a000-0x03afff:W, 0x03b000-0x03bfff:W, 0x03c000-0x03cfff:W, 0x03d000-0x03dfff:W, 0x03e000-0x03efff:W, 0x03f000-0x03ffff:W, 0x040000-0x040fff:W, 0x041000-0x041fff:W, 0x042000-0x042fff:W, 0x043000-0x043fff:W, 0x044000-0x044fff:W, 0x045000-0x045fff:W, 0x046000-0x046fff:W, 0x047000-0x047fff:W, 0x048000-0x048fff:W, 0x049000-0x049fff:W, 0x04a000-0x04afff:W, 0x04b000-0x04bfff:W, 0x04c000-0x04cfff:W, 0x04d000-0x04dfff:W, 0x04e000-0x04efff:W, 0x04f000-0x04ffff:W, 0x050000-0x050fff:W, 0x051000-0x051fff:W, 0x052000-0x052fff:W, 0x053000-0x053fff:W, 0x054000-0x054fff:W, 0x055000-0x055fff:W, 0x056000-0x056fff:W, 0x057000-0x057fff:W, 0x058000-0x058fff:W, 0x059000-0x059fff:W, 0x05a000-0x05afff:W, 0x05b000-0x05bfff:W, 0x05c000-0x05cfff:W, 0x05d000-0x05dfff:W, 0x05e000-0x05efff:W, 0x05f000-0x05ffff:W, 0x060000-0x060fff:W, 0x061000-0x061fff:W, 0x062000-0x062fff:W, 0x063000-0x063fff:W, 0x064000-0x064fff:W, 0x065000-0x065fff:W, 0x066000-0x066fff:W, 0x067000-0x067fff:W, 0x068000-0x068fff:W, 0x069000-0x069fff:W, 0x06a000-0x06afff:W, 0x06b000-0x06bfff:W, 0x06c000-0x06cfff:W, 0x06d000-0x06dfff:W, 0x06e000-0x06efff:W, 0x06f000-0x06ffff:W, 0x070000-0x070fff:W, 0x071000-0x071fff:W, 0x072000-0x072fff:W, 0x073000-0x073fff:W, 0x074000-0x074fff:W, 0x075000-0x075fff:W, 0x076000-0x076fff:W, 0x077000-0x077fff:W, 0x078000-0x078fff:W, 0x079000-0x079fff:W, 0x07a000-0x07afff:W, 0x07b000-0x07bfff:W, 0x07c000-0x07cfff:W, 0x07d000-0x07dfff:W, 0x07e000-0x07efff:W, 0x07f000-0x07ffff:EW
Done. Verifying flash... VERIFIED.
If you're going to review this, make sure you keep a stack of bananas (quickly mobilized carbohydrates for your brain), a bucket of ice (to prevent brain overheating) and a bottle of aspirin handy. If any code is unclear, please tell me and I'll try to add comments to improve readability.
This code has been tested. Testing erase (and checking with a separate readback that erase actually worked) and write (same test with separate readback) would be highly appreciated. Verbose logs are even more appreciated.
I think the code is ready for merge if you trust write/erase to never fail. The error cases still need to be tested. Should we reread the whole chip if write/erase failed to make sure our current view of the chip contents is not stale?
This patch makes flashrom use real partial writes. If you write an image full of 0xff, flashrom will erase and detect that no write is needed. If you write an image which differs only in some parts from the current flash contents, flashrom will detect that and not touch unchanged areas.
Fix a long-standing bug in need_erase() for 256 byte granularity as well.
Nice side benefit: Detailed progress printing. S means skipped E means erased W means written
Thanks for Andrew Morgan for testing countless iterations of this patch. Thanks to Richard A. Smith for testing on Dediprog. Thanks to David Hendricks for the review.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-partial_write_rolling_erase_write/flashrom.c
--- flashrom-partial_write_rolling_erase_write/flashrom.c (Revision 1215) +++ flashrom-partial_write_rolling_erase_write/flashrom.c (Arbeitskopie) @@ -793,6 +793,7 @@
- Check if the buffer @have can be programmed to the content of @want
without
- erasing. This is only possible if all chunks of size @gran are either
kept
- as-is or changed from an all-ones state to any other state.
- The following write granularities (enum @gran) are known:
- 1 bit. Each bit can be cleared individually.
- 1 byte. A byte can be written once. Further writes to an already
written @@ -803,10 +804,12 @@
- this function.
- 256 bytes. If less than 256 bytes are written, the contents of the
- unwritten bytes are undefined.
- Warning: This function assumes that @have and @want point to naturally
- aligned regions.
- @have buffer with current content
- @want buffer with desired content
- @len length of the verified area
- @len length of the checked area
- @gran write granularity (enum, not count)
- @return 0 if no erase is needed, 1 otherwise
*/ @@ -838,7 +841,7 @@ continue; /* have needs to be in erased state. */ for (i = 0; i < limit; i++)
if (have[i] != 0xff) {
if (have[j * 256 + i] != 0xff) { result = 1; break; }
@@ -846,10 +849,85 @@ break; } break;
default:
msg_cerr("%s: Unsupported granularity! Please report a bug
at "
"flashrom@flashrom.org\n", __func__); } return result;
}
+/**
- Check if the buffer @have needs to be programmed to get the content of
@want.
- If yes, return 1 and fill in first_start with the start address of the
- write operation and first_len with the length of the first
to-be-written
- chunk. If not, return 0 and leave first_start and first_len undefined.
- Warning: This function assumes that @have and @want point to naturally
- aligned regions.
- @have buffer with current content
- @want buffer with desired content
- @len length of the checked area
- @gran write granularity (enum, not count)
- @first_start offset of the first byte which needs to be written
(passed in
value is discarded, new value is written when
get_next_write
returns)
- @return length of the first contiguous area which needs to be
written
0 if no write is needed
- FIXME: This function needs a parameter which tells it about coalescing
- in relation to the max write length of the programmer and the max write
- length of the chip.
- */
+static int get_next_write(uint8_t *have, uint8_t *want, int len,
int *first_start, enum write_granularity gran)
+{
int need_write = 0;
int first_len = 0;
int i, limit, stride;
switch (gran) {
case write_gran_1bit:
case write_gran_1byte:
stride = 1;
break;
case write_gran_256bytes:
stride = 256;
break;
default:
msg_cerr("%s: Unsupported granularity! Please report a bug
at "
"flashrom@flashrom.org\n", __func__);
/* Claim that no write was needed. A write with unknown
* granularity is too dangerous to try.
*/
return 0;
}
for (i = 0; i < len / stride; i++) {
limit = min(stride, len - i * stride);
/* Are 'have' and 'want' identical? */
if (memcmp(have + i * stride, want + i * stride, limit)) {
if (!need_write) {
/* First location where have and want
differ. */
need_write = 1;
*first_start = i * stride;
}
} else {
if (need_write) {
/* First location where have and want
* do not differ anymore.
*/
first_len = i * stride - *first_start;
break;
}
}
}
/* Did the loop terminate without setting first_len? */
if (need_write && ! first_len)
first_len = min(i * stride - *first_start, len);
return first_len;
+}
/* This function generates various test patterns useful for testing controller
- and chip communication as well as chip behaviour.
@@ -1203,7 +1281,8 @@ return ret; }
-/* This function shares a lot of its structure with erase_flash(). +/* This function shares a lot of its structure with erase_and_write_flash() and
- walk_eraseregions().
- Even if an error is found, the function will keep going and check the
rest. */ static int selfcheck_eraseblocks(struct flashchip *flash) @@ -1271,10 +1350,68 @@ return ret; }
+static int erase_and_write_block_helper(struct flashchip *flash,
unsigned int start, unsigned int
len,
uint8_t *oldcontents,
uint8_t *newcontents,
int (*erasefn) (struct flashchip
*flash,
unsigned int addr,
unsigned int len))
+{
int starthere = 0;
int lenhere = 0;
int ret = 0;
int skip = 1;
int writecount = 0;
enum write_granularity gran = write_gran_256bytes; /* FIXME */
/* oldcontents and newcontents are opaque to walk_eraseregions, and
* need to be adjusted here to keep the impression of proper
abstraction
*/
oldcontents += start;
newcontents += start;
msg_cdbg(":");
/* FIXME: Assume 256 byte granularity for now to play it safe. */
if (need_erase(oldcontents, newcontents, len, gran)) {
msg_cdbg("E");
ret = erasefn(flash, start, len);
if (ret)
return ret;
/* Erase was successful. Adjust oldcontents. */
memset(oldcontents, 0xff, len);
skip = 0;
}
/* get_next_write() sets starthere to a new value after the call.
*/
while ((lenhere = get_next_write(oldcontents + starthere,
newcontents + starthere,
len - starthere, &starthere,
gran))) {
if (!writecount++)
msg_cdbg("W");
/* Needs the partial write function signature. */
ret = flash->write(flash, newcontents + starthere,
start + starthere, lenhere);
if (ret)
return ret;
starthere += lenhere;
skip = 0;
}
if (skip)
msg_cdbg("S");
return ret;
+}
static int walk_eraseregions(struct flashchip *flash, int erasefunction, int (*do_something) (struct flashchip *flash, unsigned int addr,
unsigned int len))
unsigned int len,
uint8_t *param1,
uint8_t *param2,
int (*erasefn) (
struct flashchip
*flash,
unsigned int addr,
unsigned int len)),
void *param1, void *param2)
{ int i, j; unsigned int start = 0; @@ -1286,21 +1423,34 @@ */ len = eraser.eraseblocks[i].size; for (j = 0; j < eraser.eraseblocks[i].count; j++) {
msg_cdbg("0x%06x-0x%06x, ", start,
/* Print this for every block except the first one.
*/
if (i || j)
msg_cdbg(", ");
msg_cdbg("0x%06x-0x%06x", start, start + len - 1);
if (do_something(flash, start, len))
if (do_something(flash, start, len, param1, param2,
eraser.block_erase)) {
msg_cdbg("\n"); return 1;
} start += len; } }
msg_cdbg("\n"); return 0;
}
-int erase_flash(struct flashchip *flash) +int erase_and_write_flash(struct flashchip *flash, uint8_t *oldcontents, uint8_t *newcontents) { int k, ret = 0, found = 0;
uint8_t *curcontents;
unsigned long size = flash->total_size * 1024;
msg_cinfo("Erasing flash chip... ");
curcontents = (uint8_t *) malloc(size);
/* Copy oldcontents to curcontents to avoid clobbering oldcontents.
*/
memcpy(curcontents, oldcontents, size);
msg_cinfo("Erasing and writing flash chip... "); for (k = 0; k < NUM_ERASEFUNCTIONS; k++) { struct block_eraser eraser = flash->block_erasers[k];
@@ -1324,12 +1474,14 @@ } found = 1; msg_cdbg("trying... ");
ret = walk_eraseregions(flash, k, eraser.block_erase);
ret = walk_eraseregions(flash, k,
&erase_and_write_block_helper, curcontents, newcontents); msg_cdbg("\n"); /* If everything is OK, don't try another erase function. */ if (!ret) break; }
/* Free the scratchpad. */
free(curcontents); if (!found) { msg_cerr("ERROR: flashrom has no erase function for this
flash chip.\n"); return 1; @@ -1338,7 +1490,7 @@ if (ret) { msg_cerr("FAILED!\n"); } else {
msg_cinfo("SUCCESS.\n");
msg_cinfo("Done.\n"); } return ret;
} @@ -1637,6 +1789,19 @@ programmer_shutdown(); return ret; }
oldcontents = (uint8_t *) malloc(size);
/* Assume worst case: All bits are 0. */
memset(oldcontents, 0x00, size);
newcontents = (uint8_t *) malloc(size);
/* Assume best case: All bits should be 1. */
memset(newcontents, 0xff, size);
/* Side effect of the assumptions above: Default write action is
erase
* because newcontents looks like a completely erased chip, and
* oldcontents being completely 0x00 means we have to erase
everything
* before we can write.
*/
if (erase_it) { /* FIXME: Do we really want the scary warning if erase
failed? * After all, after erase the chip is either blank or partially @@ -1644,15 +1809,14 @@ * so if the user wanted erase and reboots afterwards, the user * knows very well that booting won't work. */
if (erase_flash(flash)) {
if (erase_and_write_flash(flash, oldcontents, newcontents))
{ emergency_help_message();
programmer_shutdown();
return 1;
ret = 1; }
programmer_shutdown();
return ret; }
newcontents = (uint8_t *) calloc(size, sizeof(char));
if (write_it || verify_it) { if (read_buf_from_file(newcontents, size, filename)) { programmer_shutdown();
@@ -1665,8 +1829,6 @@ #endif }
oldcontents = (uint8_t *) calloc(size, sizeof(char));
/* Read the whole chip to be able to check whether regions need to
be * erased and to give better diagnostics in case write fails. * The alternative would be to read only the regions which are to be @@ -1686,9 +1848,9 @@ // ////////////////////////////////////////////////////////////
if (write_it) {
if (erase_flash(flash)) {
msg_cerr("Uh oh. Erase failed. Checking if anything
"
"changed.\n");
if (erase_and_write_flash(flash, oldcontents, newcontents))
{
msg_cerr("Uh oh. Erase/write failed. Checking if "
"anything changed.\n"); if (!flash->read(flash, newcontents, 0, size)) { if (!memcmp(oldcontents, newcontents, size))
{ msg_cinfo("Good. It seems nothing was " @@ -1702,26 +1864,6 @@ programmer_shutdown(); return 1; }
msg_cinfo("Writing flash chip... ");
ret = flash->write(flash, newcontents, 0, size);
if (ret) {
msg_cerr("Uh oh. Write failed. Checking if anything
"
"changed.\n");
if (!flash->read(flash, newcontents, 0, size)) {
if (!memcmp(oldcontents, newcontents,
size)) {
msg_cinfo("Good. It seems nothing
was "
"changed.\n");
nonfatal_help_message();
programmer_shutdown();
return 1;
}
}
emergency_help_message();
programmer_shutdown();
return 1;
} else {
msg_cinfo("COMPLETE.\n");
} } if (verify_it) {
flashrom mailing list flashrom@flashrom.org http://www.flashrom.org/mailman/listinfo/flashrom