summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2018-07-15 16:51:41 +0200
committerRafał Miłecki <rafal@milecki.pl>2018-07-17 07:17:37 +0200
commit828eaeee2550c954ea98063e59e09980c1361de2 (patch)
treeb0f7847f1b4ec6e90a1ad99856e15c97867e432d
parent8d4da3c5898ae3b594530b16c6f2ab79a2b7095b (diff)
downloadmtk-20170518-828eaeee2550c954ea98063e59e09980c1361de2.zip
mtk-20170518-828eaeee2550c954ea98063e59e09980c1361de2.tar.gz
mtk-20170518-828eaeee2550c954ea98063e59e09980c1361de2.tar.bz2
mtd: support bad blocks within the mtd_fixtrx()
Reading MTD data with (p)read doesn't return any error when accessing bad block. As the result, with current code, CRC32 covers "data" stored in bad blocks. That behavior doesn't match CFE's one (bootloader simply skips bad blocks) and may result in: 1) Invalid CRC32 2) CFE refusing to boot firmware with a following error: Boot program checksum is invalid Fix that problem by checking every block before reading its content. Signed-off-by: Rafał Miłecki <rafal@milecki.pl> (cherry picked from commit 0f54489f754e7bd34e0430c57a11b6a54740d58e)
-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 ecb4400..5d1538e 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$(if $(SDK),,.1)
+PKG_RELEASE:=22$(if $(SDK),,.1)
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 1f5c529..c1296a5 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;
}
-