/*
- * Copyright (C) 2011-2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright (C) 2011-2015 Lothar Waßmann <LW@KARO-electronics.de>
*
* See file CREDITS for list of people who contributed to this
* project.
fcb = buf;
memset(fcb, 0x00, sizeof(*fcb));
- memset(fcb + 1, 0xff, mtd->erasesize - sizeof(*fcb));
+ memset(fcb + 1, 0xff, SZ_1K - sizeof(*fcb));
strncpy((char *)&fcb->fingerprint, "FCB ", 4);
fcb->version = 1;
fcb->fw1_start_page = fw1_start_block * sectors_per_block;
pr_fcb_val(fcb, fw1_start_page);
- if (fw2_start_block != 0 && fw2_start_block < mtd->size / mtd->erasesize) {
+ if (fw2_start_block != 0 &&
+ fw2_start_block < lldiv(mtd->size, mtd->erasesize)) {
fcb->fw2_start_page = fw2_start_block * sectors_per_block;
pr_fcb_val(fcb, fw2_start_page);
}
return 0;
}
- printf("Erasing FCB block %08x..%08x\n", block * mtd->erasesize,
- block * mtd->erasesize + mtd->erasesize - 1);
if (doit) {
ret = nand_erase(mtd, block * mtd->erasesize, mtd->erasesize);
if (ret) {
(u64)block * mtd->erasesize);
if (doit) {
chip->select_chip(mtd, 0);
- ret = chip->write_page(mtd, chip, buf, 1, page, 0, 1);
+ ret = chip->write_page(mtd, chip, 0, mtd->writesize,
+ buf, 1, page, 0, 0);
if (ret) {
printf("Failed to write FCB to block %u: %d\n", block, ret);
}
nand_erase_options_t erase_opts = { 0, };
size_t actual;
size_t prg_length = max_len - skip * mtd->erasesize;
- int prg_start = start_block * mtd->erasesize;
+ int prg_start = (start_block + skip) * mtd->erasesize;
- erase_opts.offset = (start_block - skip) * mtd->erasesize;
+ erase_opts.offset = start_block * mtd->erasesize;
erase_opts.length = max_len;
erase_opts.quiet = 1;
if (doit) {
actual = size;
ret = nand_write_skip_bad(mtd, prg_start, &actual, NULL,
- prg_length, addr, WITH_DROP_FFS);
+ prg_length, addr, 0);
if (ret) {
printf("Failed to program flash: %d\n", ret);
return ret;
int ret;
const unsigned long fcb_start_block = 0, fcb_end_block = 0;
int erase_size = mtd->erasesize;
- int page_size = mtd->writesize;
void *buf;
+ size_t buf_size;
char *load_addr;
char *file_size;
size_t size = 0;
void *addr = NULL;
struct mx53_fcb *fcb;
- unsigned long mtd_num_blocks = mtd->size / mtd->erasesize;
+ unsigned long mtd_num_blocks = lldiv(mtd->size, mtd->erasesize);
#ifdef CONFIG_ENV_IS_IN_NAND
unsigned long env_start_block = CONFIG_ENV_OFFSET / mtd->erasesize;
unsigned long env_end_block = env_start_block +
unsigned long fw_num_blocks;
int fw1_skip, fw2_skip;
unsigned long extra_blocks = 0;
- size_t max_len1, max_len2;
+ u64 max_len1, max_len2;
struct mtd_device *dev;
struct part_info *part_info;
struct part_info *redund_part_info;
uboot_part, ret);
return ret;
}
- fw1_start_block = part_info->offset / mtd->erasesize;
+ fw1_start_block = lldiv(part_info->offset, mtd->erasesize);
max_len1 = part_info->size;
- /*
- * Skip one block, if the U-Boot image resides in the
- * same partition as the FCB
- */
- if (fw1_start_block == fcb_start_block) {
- fw1_start_block++;
- max_len1 -= mtd->erasesize;
- }
if (size == 0)
- fw_num_blocks = max_len1 / mtd->erasesize;
+ fw_num_blocks = lldiv(max_len1, mtd->erasesize);
} else {
- max_len1 = (fw_num_blocks + extra_blocks) * mtd->erasesize;
+ max_len1 = (u64)(fw_num_blocks + extra_blocks) * mtd->erasesize;
}
if (redund_part) {
redund_part, ret);
return ret;
}
- fw2_start_block = redund_part_info->offset / mtd->erasesize;
+ fw2_start_block = lldiv(redund_part_info->offset, mtd->erasesize);
max_len2 = redund_part_info->size;
if (fw2_start_block == fcb_start_block) {
fw2_start_block++;
max_len2 -= mtd->erasesize;
}
if (size == 0)
- fw_num_blocks = max_len2 / mtd->erasesize;
+ fw_num_blocks = lldiv(max_len2, mtd->erasesize);
} else if (fw2_set) {
- max_len2 = (fw_num_blocks + extra_blocks) * mtd->erasesize;
+ max_len2 = (u64)(fw_num_blocks + extra_blocks) * mtd->erasesize;
} else {
max_len2 = 0;
}
fw1_skip = find_contig_space(fw1_start_block, fw_num_blocks,
- max_len1 / mtd->erasesize);
+ lldiv(max_len1, mtd->erasesize));
if (fw1_skip < 0) {
- printf("Could not find %lu contiguous good blocks for fw image in blocks %lu..%lu\n",
+ printf("Could not find %lu contiguous good blocks for fw image in blocks %lu..%llu\n",
fw_num_blocks, fw1_start_block,
- fw1_start_block + max_len1 / mtd->erasesize - 1);
+ fw1_start_block + lldiv(max_len1, mtd->erasesize) - 1);
if (uboot_part) {
#ifdef CONFIG_ENV_IS_IN_NAND
if (part_info->offset <= CONFIG_ENV_OFFSET + TOTAL_ENV_SIZE) {
fw2_start_block = fw1_end_block + 1;
if (fw2_start_block > 0) {
fw2_skip = find_contig_space(fw2_start_block, fw_num_blocks,
- max_len2 / mtd->erasesize);
+ lldiv(max_len2, mtd->erasesize));
if (fw2_skip < 0) {
- printf("Could not find %lu contiguous good blocks for redundant fw image in blocks %lu..%lu\n",
+ printf("Could not find %lu contiguous good blocks for redundant fw image in blocks %lu..%llu\n",
fw_num_blocks, fw2_start_block,
- fw2_start_block + max_len2 / mtd->erasesize - 1);
+ fw2_start_block + lldiv(max_len2, mtd->erasesize) - 1);
if (redund_part) {
printf("Increase the size of the '%s' partition or use a different partition\n",
redund_part);
fail_if_overlap(fcb, env, "FCB", "Environment");
fail_if_overlap(fw1, env, "FW1", "Environment");
#endif
- fail_if_overlap(fw1, fcb, "FW1", "FCB");
if (fw2_set) {
- fail_if_overlap(fw2, fcb, "FW2", "FCB");
+ fail_if_overlap(fcb, fw2, "FCB", "FW2");
#ifdef CONFIG_ENV_IS_IN_NAND
fail_if_overlap(fw2, env, "FW2", "Environment");
#endif
fw1_start_block += fw1_skip;
fw2_start_block += fw2_skip;
- buf = malloc(erase_size);
+ buf_size = fw_num_blocks * erase_size;
+ buf = memalign(erase_size, buf_size);
if (buf == NULL) {
printf("Failed to allocate buffer\n");
return -ENOMEM;
}
+ /* copy U-Boot image to buffer */
+ memcpy(buf, addr, size);
+ memset(buf + size, 0xff, buf_size - size);
+
fcb = create_fcb(buf, fw1_start_block,
fw2_start_block, fw_num_blocks);
if (IS_ERR(fcb)) {
printf("Failed to initialize FCB: %ld\n", PTR_ERR(fcb));
- free(buf);
- return PTR_ERR(fcb);
+ ret = PTR_ERR(fcb);
+ goto out;
}
- ret = write_fcb(buf, fcb_start_block);
- free(buf);
- if (ret) {
- printf("Failed to write FCB to block %lu\n", fcb_start_block);
- return ret;
- }
+ if (fw1_start_block == fcb_start_block) {
+ printf("Programming FCB + U-Boot image from %p to block %lu @ %08llx\n",
+ buf, fw1_start_block, (u64)fw1_start_block * mtd->erasesize);
+ ret = tx53_prog_uboot(buf, fw1_start_block, fw1_skip, size,
+ max_len1);
+ } else {
+ printf("Programming U-Boot image from %p to block %lu @ %08llx\n",
+ buf, fw1_start_block, (u64)fw1_start_block * mtd->erasesize);
+ ret = tx53_prog_uboot(buf, fw1_start_block, fw1_skip, size,
+ max_len1);
+ if (ret)
+ goto out;
- if (size & (page_size - 1)) {
- memset(addr + size, 0xff, size & (page_size - 1));
- size = ALIGN(size, page_size);
- }
+ memset(buf + sizeof(*fcb), 0xff,
+ mtd->writesize - sizeof(*fcb));
- printf("Programming U-Boot image from %p to block %lu @ %08llx\n",
- addr, fw1_start_block, (u64)fw1_start_block * mtd->erasesize);
- ret = tx53_prog_uboot(addr, fw1_start_block, fw1_skip, size,
- max_len1);
+ ret = write_fcb(buf, fcb_start_block);
+ if (ret) {
+ printf("Failed to write FCB to block %lu\n", fcb_start_block);
+ return ret;
+ }
+ memset(buf, 0xff, SZ_1K);
+ }
if (ret || fw2_start_block == 0)
- return ret;
+ goto out;
printf("Programming redundant U-Boot image to block %lu @ %08llx\n",
fw2_start_block, (u64)fw2_start_block * mtd->erasesize);
- ret = tx53_prog_uboot(addr, fw2_start_block, fw2_skip, size,
+ ret = tx53_prog_uboot(buf, fw2_start_block, fw2_skip, size,
max_len2);
+out:
+ free(buf);
return ret;
}