X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fopenwrt.git;a=blobdiff_plain;f=package%2Fsystem%2Fmtd%2Fsrc%2Ftrx.c;h=c1296a5f707a3feea138fabf5ba231d4d86f7048;hp=1f5c52914c453786dde689ac3a1a01bead30982a;hb=5dca299fabc466183fdc973871b5f66e6ee4252d;hpb=5889cf70e99fe66bd17a439d8aceabcb5c495437 diff --git a/package/system/mtd/src/trx.c b/package/system/mtd/src/trx.c index 1f5c52914c..c1296a5f70 100644 --- a/package/system/mtd/src/trx.c +++ b/package/system/mtd/src/trx.c @@ -46,6 +46,12 @@ struct trx_header { uint32_t offsets[3]; /* Offsets of partitions from start of header */ }; +#define min(x,y) ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x < _y ? _x : _y; }) + #if __BYTE_ORDER == __BIG_ENDIAN #define STORE32_LE(X) ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24)) #elif __BYTE_ORDER == __LITTLE_ENDIAN @@ -156,7 +162,7 @@ mtd_fixtrx(const char *mtd, size_t offset, size_t data_size) int fd; struct trx_header *trx; char *first_block; - char *buf; + char *buf, *to; ssize_t res; size_t block_offset; @@ -214,11 +220,28 @@ mtd_fixtrx(const char *mtd, size_t offset, size_t data_size) exit(1); } - res = pread(fd, buf, data_size, data_offset); - if (res != data_size) { - perror("pread"); - exit(1); + to = buf; + while (data_size) { + size_t read_block_offset = data_offset & ~(erasesize - 1); + size_t read_chunk; + + read_chunk = erasesize - (data_offset & (erasesize - 1)); + read_chunk = min(read_chunk, data_size); + + /* Read from good blocks only to match CFE behavior */ + if (!mtd_block_is_bad(fd, read_block_offset)) { + res = pread(fd, to, read_chunk, data_offset); + if (res != read_chunk) { + perror("pread"); + exit(1); + } + to += read_chunk; + } + + data_offset += read_chunk; + data_size -= read_chunk; } + data_size = to - buf; trx->len = STORE32_LE(data_size + offsetof(struct trx_header, flag_version)); @@ -244,4 +267,3 @@ mtd_fixtrx(const char *mtd, size_t offset, size_t data_size) return 0; } -