]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - board/karo/tx53/flash.c
karo: tx53: romupdate: fix calculation of starting block in tx53_prog_uboot()
[karo-tx-uboot.git] / board / karo / tx53 / flash.c
index d6463cf1057c300f59c430fd91bdf59b866227a7..19bb9b6dc783b6d9344d4cefa7823af67339b379 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -103,7 +103,7 @@ static struct mx53_fcb *create_fcb(void *buf, int fw1_start_block,
        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;
@@ -111,7 +111,8 @@ static struct mx53_fcb *create_fcb(void *buf, int fw1_start_block,
        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);
        }
@@ -158,8 +159,6 @@ static int write_fcb(void *buf, int block)
                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) {
@@ -233,7 +232,7 @@ static int tx53_prog_uboot(void *addr, int start_block, int skip,
        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;
@@ -259,14 +258,14 @@ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
        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 +
@@ -279,7 +278,7 @@ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
        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;
@@ -403,20 +402,12 @@ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
                                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) {
@@ -427,26 +418,26 @@ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
                                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) {
@@ -473,11 +464,11 @@ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
                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);
@@ -498,9 +489,8 @@ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
        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
@@ -509,43 +499,57 @@ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
        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;
 }