summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2015-06-12 07:48:51 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2015-06-12 08:29:48 +0200
commit6ab66787fc15a286b6142b09f9d7c2654dee78a9 (patch)
treefed54be45583525834a535f13e19b6a96f1be590
parent4e880df3470eb099c9934e6b37af87ab47255c52 (diff)
downloadbarebox-6ab66787fc15a286b6142b09f9d7c2654dee78a9.tar.gz
barebox-6ab66787fc15a286b6142b09f9d7c2654dee78a9.tar.xz
imx-bbu-nand-fcb: Split space for firmware in two equal regions
We used to write the second firmware right after the first firmware. However, splitting the available space into two equal regions has advantages: When we update barebox the next time the generated FCB/DBBT blocks will be the same as with the last update, so in case of power failure it is more likely that we have valid data in one of the FCB/DBBT areas. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--common/imx-bbu-nand-fcb.c48
1 files changed, 33 insertions, 15 deletions
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index c4f49b551a..22031f5b7f 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -300,7 +300,8 @@ static int imx_bbu_erase(struct mtd_info *mtd)
return 0;
}
-static int imx_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, size_t len)
+static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned block,
+ unsigned num_blocks, void *buf, size_t len)
{
uint64_t offset = block * mtd->erasesize;
int ret;
@@ -309,6 +310,9 @@ static int imx_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, si
while (len > 0) {
int now = min(len, mtd->erasesize);
+ if (!num_blocks)
+ return -ENOSPC;
+
pr_debug("writing %p at 0x%08llx, left 0x%08x\n",
buf, offset, len);
@@ -327,6 +331,7 @@ static int imx_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, si
len -= now;
buf += now;
block++;
+ num_blocks--;
}
return block;
@@ -359,16 +364,17 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
container_of(handler, struct imx_nand_fcb_bbu_handler, handler);
struct cdev *bcb_cdev;
struct mtd_info *mtd;
- int ret, block_fw1, block_fw2, block_last;
+ int ret, block_fw1, block_fw2;
struct fcb_block *fcb;
struct dbbt_block *dbbt;
void *fcb_raw_page, *dbbt_page, *dbbt_data_page;
void *ecc;
int written;
void *fw;
- unsigned fw_size;
+ unsigned fw_size, partition_size;
int i;
enum filetype filetype;
+ unsigned num_blocks_fcb_dbbt, num_blocks, num_blocks_fw;
filetype = file_detect_type(data->image, data->len);
@@ -378,10 +384,6 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
file_type_to_string(filetype)))
return -EINVAL;
- ret = bbu_confirm(data);
- if (ret)
- return ret;
-
bcb_cdev = cdev_by_name(handler->devicefile);
if (!bcb_cdev) {
pr_err("%s: No FCB device!\n", __func__);
@@ -389,6 +391,7 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
}
mtd = bcb_cdev->mtd;
+ partition_size = mtd->size;
fcb_raw_page = xzalloc(mtd->writesize + mtd->oobsize);
@@ -408,24 +411,39 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
fw = xzalloc(fw_size);
memcpy(fw, data->image, data->len);
- block_fw1 = 4;
+ num_blocks_fcb_dbbt = 4;
+ num_blocks = partition_size / mtd->erasesize;
+ num_blocks_fw = (num_blocks - num_blocks_fcb_dbbt) / 2;
+
+ block_fw1 = num_blocks_fcb_dbbt;
+ block_fw2 = num_blocks_fcb_dbbt + num_blocks_fw;
+
+ pr_info("writing first firmware to block %d (ofs 0x%08x)\n",
+ block_fw1, block_fw1 * mtd->erasesize);
+ pr_info("writing second firmware to block %d (ofs 0x%08x)\n",
+ block_fw2, block_fw2 * mtd->erasesize);
+ pr_info("maximum size per firmware: 0x%08x bytes\n",
+ num_blocks_fw * mtd->erasesize);
+
+ if (num_blocks_fw * mtd->erasesize < fw_size)
+ return -ENOSPC;
+
+ ret = bbu_confirm(data);
+ if (ret)
+ goto out;
ret = imx_bbu_erase(mtd);
if (ret)
goto out;
- ret = imx_bbu_write_firmware(mtd, block_fw1, fw, fw_size);
+ ret = imx_bbu_write_firmware(mtd, block_fw1, num_blocks_fw, fw, fw_size);
if (ret < 0)
goto out;
- block_fw2 = ret;
-
- ret = imx_bbu_write_firmware(mtd, block_fw2, fw, fw_size);
+ ret = imx_bbu_write_firmware(mtd, block_fw2, num_blocks_fw, fw, fw_size);
if (ret < 0)
goto out;
- block_last = ret;
-
fcb->Firmware1_startingPage = block_fw1 * mtd->erasesize / mtd->writesize;
fcb->Firmware2_startingPage = block_fw2 * mtd->erasesize / mtd->writesize;
fcb->PagesInFirmware1 = ALIGN(data->len, mtd->writesize) / mtd->writesize;
@@ -451,7 +469,7 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
dbbt->FingerPrint = 0x54424244;
dbbt->Version = 0x01000000;
- ret = dbbt_data_create(mtd, dbbt_data_page, block_last);
+ ret = dbbt_data_create(mtd, dbbt_data_page, block_fw2 + num_blocks_fw);
if (ret < 0)
goto out;