Author: hailfinger Date: Mon Mar 8 01:42:32 2010 New Revision: 927 URL: http://flashrom.org/trac/coreboot/changeset/927
Log: Write granularity is chip specific. The following write granularities exist according to my datasheet survey: - 1 bit. Each bit can be cleared individually. - 1 byte. A byte can be written once. Further writes to an already written byte cause the contents to be either undefined or to stay unchanged. - 128 bytes. If less than 128 bytes are written, the rest will be erased. Each write to a 128-byte region will trigger an automatic erase before anything is written. Very uncommon behaviour. - 256 bytes. If less than 256 bytes are written, the contents of the unwritten bytes are undefined.
Note that chips with default 256-byte writes, which keep the original contents for unwritten bytes, have a granularity of 1 byte.
Handle 1-bit, 1-byte and 256-byte write granularity.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net Acked-by: Sean Nelson audiohacked@gmail.com Acked-by: David Hendricks dhendrix@google.com
Modified: trunk/flash.h trunk/flashrom.c
Modified: trunk/flash.h ============================================================================== --- trunk/flash.h Sun Mar 7 23:29:28 2010 (r926) +++ trunk/flash.h Mon Mar 8 01:42:32 2010 (r927) @@ -512,6 +512,11 @@ int dediprog_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
/* flashrom.c */ +enum write_granularity { + write_gran_1bit, + write_gran_1byte, + write_gran_256bytes, +}; extern enum chipbustype buses_supported; struct decode_sizes { uint32_t parallel; @@ -538,6 +543,7 @@ char *extract_param(char **haystack, char *needle, char *delim); int check_erased_range(struct flashchip *flash, int start, int len); int verify_range(struct flashchip *flash, uint8_t *cmpbuf, int start, int len, char *message); +int need_erase(uint8_t *have, uint8_t *want, int len, enum write_granularity gran); char *strcat_realloc(char *dest, const char *src); void print_version(void); int selfcheck(void);
Modified: trunk/flashrom.c ============================================================================== --- trunk/flashrom.c Sun Mar 7 23:29:28 2010 (r926) +++ trunk/flashrom.c Mon Mar 8 01:42:32 2010 (r927) @@ -620,6 +620,67 @@ return ret; }
+/** + * 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 + * byte cause the contents to be either undefined or to stay unchanged. + * - 128 bytes. If less than 128 bytes are written, the rest will be + * erased. Each write to a 128-byte region will trigger an automatic erase + * before anything is written. Very uncommon behaviour and unsupported by + * this function. + * - 256 bytes. If less than 256 bytes are written, the contents of the + * unwritten bytes are undefined. + * + * @have buffer with current content + * @want buffer with desired content + * @len length of the verified area + * @gran write granularity (enum, not count) + * @return 0 if no erase is needed, 1 otherwise + */ +int need_erase(uint8_t *have, uint8_t *want, int len, enum write_granularity gran) +{ + int result = 0; + int i, j, limit; + + switch (gran) { + case write_gran_1bit: + for (i = 0; i < len; i++) + if ((have[i] & want[i]) != want[i]) { + result = 1; + break; + } + break; + case write_gran_1byte: + for (i = 0; i < len; i++) + if ((have[i] != want[i]) && (have[i] != 0xff)) { + result = 1; + break; + } + break; + case write_gran_256bytes: + for (j = 0; j < len / 256; j++) { + limit = min (256, len - j * 256); + /* Are have and want identical? */ + if (!memcmp(have + j * 256, want + j * 256, limit)) + continue; + /* have needs to be in erased state. */ + for (i = 0; i < limit; i++) + if (have[i] != 0xff) { + result = 1; + break; + } + if (result) + break; + } + break; + } + return result; +} + /* This function generates various test patterns useful for testing controller * and chip communication as well as chip behaviour. *