am 22d79a5c: make offsets in firmware update header not point to bad blocks
Merge commit '22d79a5c5eab9c1e86ff2af210bb072689e2d630' into eclair-plus-aosp * commit '22d79a5c5eab9c1e86ff2af210bb072689e2d630': make offsets in firmware update header not point to bad blocks
This commit is contained in:
12
bootloader.c
12
bootloader.c
@@ -198,7 +198,7 @@ int write_update_for_bootloader(
|
|||||||
header.version = UPDATE_VERSION;
|
header.version = UPDATE_VERSION;
|
||||||
header.size = header_size;
|
header.size = header_size;
|
||||||
|
|
||||||
header.image_offset = mtd_erase_blocks(write, 0);
|
off_t image_start_pos = mtd_erase_blocks(write, 0);
|
||||||
header.image_length = update_length;
|
header.image_length = update_length;
|
||||||
if ((int) header.image_offset == -1 ||
|
if ((int) header.image_offset == -1 ||
|
||||||
mtd_write_data(write, update, update_length) != update_length) {
|
mtd_write_data(write, update, update_length) != update_length) {
|
||||||
@@ -206,6 +206,8 @@ int write_update_for_bootloader(
|
|||||||
mtd_write_close(write);
|
mtd_write_close(write);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
off_t busy_start_pos = mtd_erase_blocks(write, 0);
|
||||||
|
header.image_offset = mtd_find_write_start(write, image_start_pos);
|
||||||
|
|
||||||
header.bitmap_width = bitmap_width;
|
header.bitmap_width = bitmap_width;
|
||||||
header.bitmap_height = bitmap_height;
|
header.bitmap_height = bitmap_height;
|
||||||
@@ -213,7 +215,6 @@ int write_update_for_bootloader(
|
|||||||
|
|
||||||
int bitmap_length = (bitmap_bpp + 7) / 8 * bitmap_width * bitmap_height;
|
int bitmap_length = (bitmap_bpp + 7) / 8 * bitmap_width * bitmap_height;
|
||||||
|
|
||||||
header.busy_bitmap_offset = mtd_erase_blocks(write, 0);
|
|
||||||
header.busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0;
|
header.busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0;
|
||||||
if ((int) header.busy_bitmap_offset == -1 ||
|
if ((int) header.busy_bitmap_offset == -1 ||
|
||||||
mtd_write_data(write, busy_bitmap, bitmap_length) != bitmap_length) {
|
mtd_write_data(write, busy_bitmap, bitmap_length) != bitmap_length) {
|
||||||
@@ -221,8 +222,9 @@ int write_update_for_bootloader(
|
|||||||
mtd_write_close(write);
|
mtd_write_close(write);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
off_t fail_start_pos = mtd_erase_blocks(write, 0);
|
||||||
|
header.busy_bitmap_offset = mtd_find_write_start(write, busy_start_pos);
|
||||||
|
|
||||||
header.fail_bitmap_offset = mtd_erase_blocks(write, 0);
|
|
||||||
header.fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0;
|
header.fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0;
|
||||||
if ((int) header.fail_bitmap_offset == -1 ||
|
if ((int) header.fail_bitmap_offset == -1 ||
|
||||||
mtd_write_data(write, fail_bitmap, bitmap_length) != bitmap_length) {
|
mtd_write_data(write, fail_bitmap, bitmap_length) != bitmap_length) {
|
||||||
@@ -230,6 +232,8 @@ int write_update_for_bootloader(
|
|||||||
mtd_write_close(write);
|
mtd_write_close(write);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
mtd_erase_blocks(write, 0);
|
||||||
|
header.fail_bitmap_offset = mtd_find_write_start(write, fail_start_pos);
|
||||||
|
|
||||||
/* Write the header last, after all the blocks it refers to, so that
|
/* Write the header last, after all the blocks it refers to, so that
|
||||||
* when the magic number is installed everything is valid.
|
* when the magic number is installed everything is valid.
|
||||||
@@ -252,7 +256,7 @@ int write_update_for_bootloader(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mtd_erase_blocks(write, 0) != (off_t) header.image_offset) {
|
if (mtd_erase_blocks(write, 0) != image_start_pos) {
|
||||||
LOGE("Misalignment rewriting %s\n(%s)\n", CACHE_NAME, strerror(errno));
|
LOGE("Misalignment rewriting %s\n(%s)\n", CACHE_NAME, strerror(errno));
|
||||||
mtd_write_close(write);
|
mtd_write_close(write);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ struct MtdWriteContext {
|
|||||||
char *buffer;
|
char *buffer;
|
||||||
size_t stored;
|
size_t stored;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
off_t* bad_block_offsets;
|
||||||
|
int bad_block_alloc;
|
||||||
|
int bad_block_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -366,6 +370,10 @@ MtdWriteContext *mtd_write_partition(const MtdPartition *partition)
|
|||||||
MtdWriteContext *ctx = (MtdWriteContext*) malloc(sizeof(MtdWriteContext));
|
MtdWriteContext *ctx = (MtdWriteContext*) malloc(sizeof(MtdWriteContext));
|
||||||
if (ctx == NULL) return NULL;
|
if (ctx == NULL) return NULL;
|
||||||
|
|
||||||
|
ctx->bad_block_offsets = NULL;
|
||||||
|
ctx->bad_block_alloc = 0;
|
||||||
|
ctx->bad_block_count = 0;
|
||||||
|
|
||||||
ctx->buffer = malloc(partition->erase_size);
|
ctx->buffer = malloc(partition->erase_size);
|
||||||
if (ctx->buffer == NULL) {
|
if (ctx->buffer == NULL) {
|
||||||
free(ctx);
|
free(ctx);
|
||||||
@@ -386,8 +394,20 @@ MtdWriteContext *mtd_write_partition(const MtdPartition *partition)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_block(const MtdPartition *partition, int fd, const char *data)
|
static void add_bad_block_offset(MtdWriteContext *ctx, off_t pos) {
|
||||||
|
if (ctx->bad_block_count + 1 > ctx->bad_block_alloc) {
|
||||||
|
ctx->bad_block_alloc = (ctx->bad_block_alloc*2) + 1;
|
||||||
|
ctx->bad_block_offsets = realloc(ctx->bad_block_offsets,
|
||||||
|
ctx->bad_block_alloc * sizeof(off_t));
|
||||||
|
}
|
||||||
|
ctx->bad_block_offsets[ctx->bad_block_count++] = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_block(MtdWriteContext *ctx, const char *data)
|
||||||
{
|
{
|
||||||
|
const MtdPartition *partition = ctx->partition;
|
||||||
|
int fd = ctx->fd;
|
||||||
|
|
||||||
off_t pos = lseek(fd, 0, SEEK_CUR);
|
off_t pos = lseek(fd, 0, SEEK_CUR);
|
||||||
if (pos == (off_t) -1) return 1;
|
if (pos == (off_t) -1) return 1;
|
||||||
|
|
||||||
@@ -395,6 +415,7 @@ static int write_block(const MtdPartition *partition, int fd, const char *data)
|
|||||||
while (pos + size <= (int) partition->size) {
|
while (pos + size <= (int) partition->size) {
|
||||||
loff_t bpos = pos;
|
loff_t bpos = pos;
|
||||||
if (ioctl(fd, MEMGETBADBLOCK, &bpos) > 0) {
|
if (ioctl(fd, MEMGETBADBLOCK, &bpos) > 0) {
|
||||||
|
add_bad_block_offset(ctx, pos);
|
||||||
fprintf(stderr, "mtd: not writing bad block at 0x%08lx\n", pos);
|
fprintf(stderr, "mtd: not writing bad block at 0x%08lx\n", pos);
|
||||||
pos += partition->erase_size;
|
pos += partition->erase_size;
|
||||||
continue; // Don't try to erase known factory-bad blocks.
|
continue; // Don't try to erase known factory-bad blocks.
|
||||||
@@ -436,6 +457,7 @@ static int write_block(const MtdPartition *partition, int fd, const char *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try to erase it once more as we give up on this block
|
// Try to erase it once more as we give up on this block
|
||||||
|
add_bad_block_offset(ctx, pos);
|
||||||
fprintf(stderr, "mtd: skipping write block at 0x%08lx\n", pos);
|
fprintf(stderr, "mtd: skipping write block at 0x%08lx\n", pos);
|
||||||
ioctl(fd, MEMERASE, &erase_info);
|
ioctl(fd, MEMERASE, &erase_info);
|
||||||
pos += partition->erase_size;
|
pos += partition->erase_size;
|
||||||
@@ -461,13 +483,13 @@ ssize_t mtd_write_data(MtdWriteContext *ctx, const char *data, size_t len)
|
|||||||
|
|
||||||
// If a complete block was accumulated, write it
|
// If a complete block was accumulated, write it
|
||||||
if (ctx->stored == ctx->partition->erase_size) {
|
if (ctx->stored == ctx->partition->erase_size) {
|
||||||
if (write_block(ctx->partition, ctx->fd, ctx->buffer)) return -1;
|
if (write_block(ctx, ctx->buffer)) return -1;
|
||||||
ctx->stored = 0;
|
ctx->stored = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write complete blocks directly from the user's buffer
|
// Write complete blocks directly from the user's buffer
|
||||||
while (ctx->stored == 0 && len - wrote >= ctx->partition->erase_size) {
|
while (ctx->stored == 0 && len - wrote >= ctx->partition->erase_size) {
|
||||||
if (write_block(ctx->partition, ctx->fd, data + wrote)) return -1;
|
if (write_block(ctx, data + wrote)) return -1;
|
||||||
wrote += ctx->partition->erase_size;
|
wrote += ctx->partition->erase_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -481,7 +503,7 @@ off_t mtd_erase_blocks(MtdWriteContext *ctx, int blocks)
|
|||||||
if (ctx->stored > 0) {
|
if (ctx->stored > 0) {
|
||||||
size_t zero = ctx->partition->erase_size - ctx->stored;
|
size_t zero = ctx->partition->erase_size - ctx->stored;
|
||||||
memset(ctx->buffer + ctx->stored, 0, zero);
|
memset(ctx->buffer + ctx->stored, 0, zero);
|
||||||
if (write_block(ctx->partition, ctx->fd, ctx->buffer)) return -1;
|
if (write_block(ctx, ctx->buffer)) return -1;
|
||||||
ctx->stored = 0;
|
ctx->stored = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,7 +544,23 @@ int mtd_write_close(MtdWriteContext *ctx)
|
|||||||
// Make sure any pending data gets written
|
// Make sure any pending data gets written
|
||||||
if (mtd_erase_blocks(ctx, 0) == (off_t) -1) r = -1;
|
if (mtd_erase_blocks(ctx, 0) == (off_t) -1) r = -1;
|
||||||
if (close(ctx->fd)) r = -1;
|
if (close(ctx->fd)) r = -1;
|
||||||
|
free(ctx->bad_block_offsets);
|
||||||
free(ctx->buffer);
|
free(ctx->buffer);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the offset of the first good block at or after pos (which
|
||||||
|
* might be pos itself).
|
||||||
|
*/
|
||||||
|
off_t mtd_find_write_start(MtdWriteContext *ctx, off_t pos) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ctx->bad_block_count; ++i) {
|
||||||
|
if (ctx->bad_block_offsets[i] == pos) {
|
||||||
|
pos += ctx->partition->erase_size;
|
||||||
|
} else if (ctx->bad_block_offsets[i] > pos) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ void mtd_read_close(MtdReadContext *);
|
|||||||
MtdWriteContext *mtd_write_partition(const MtdPartition *);
|
MtdWriteContext *mtd_write_partition(const MtdPartition *);
|
||||||
ssize_t mtd_write_data(MtdWriteContext *, const char *data, size_t data_len);
|
ssize_t mtd_write_data(MtdWriteContext *, const char *data, size_t data_len);
|
||||||
off_t mtd_erase_blocks(MtdWriteContext *, int blocks); /* 0 ok, -1 for all */
|
off_t mtd_erase_blocks(MtdWriteContext *, int blocks); /* 0 ok, -1 for all */
|
||||||
|
off_t mtd_find_write_start(MtdWriteContext *ctx, off_t pos);
|
||||||
int mtd_write_close(MtdWriteContext *);
|
int mtd_write_close(MtdWriteContext *);
|
||||||
|
|
||||||
#endif // MTDUTILS_H_
|
#endif // MTDUTILS_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user