aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package/system/mtd/Makefile2
-rw-r--r--package/system/mtd/src/trx.c34
2 files changed, 29 insertions, 7 deletions
diff --git a/package/system/mtd/Makefile b/package/system/mtd/Makefile
index 9ae03a77a9..969e1c711c 100644
--- a/package/system/mtd/Makefile
+++ b/package/system/mtd/Makefile
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=mtd
-PKG_RELEASE:=21
+PKG_RELEASE:=22
PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME)
STAMP_PREPARED := $(STAMP_PREPARED)_$(call confvar,CONFIG_MTD_REDBOOT_PARTS)
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;
}
-