summaryrefslogtreecommitdiffstats
path: root/common/imx-bbu-nand-fcb.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/imx-bbu-nand-fcb.c')
-rw-r--r--common/imx-bbu-nand-fcb.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index 5535a92..15ddf5d 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -555,6 +555,40 @@ static int imx_bbu_firmware_start_block(struct mtd_info *mtd, int num)
return 4 + num * imx_bbu_firmware_max_blocks(mtd);
}
+/**
+ * imx_bbu_firmware_fcb_start_page - get start page for a firmware slot
+ * @mtd: The mtd device
+ * @num: The slot number (0 or 1)
+ *
+ * This returns the start page for a firmware slot, to be written into the
+ * Firmwaren_startingPage field in the FCB.
+ */
+static int imx_bbu_firmware_fcb_start_page(struct mtd_info *mtd, int num)
+{
+ int block, blocksleft;
+ int pages_per_block = mtd->erasesize / mtd->writesize;
+
+ block = imx_bbu_firmware_start_block(mtd, num);
+
+ blocksleft = imx_bbu_firmware_max_blocks(mtd);
+
+ /*
+ * The ROM only checks for a bad block when advancing the read position,
+ * but not if the initial block is good, hence we cannot directly point
+ * to the first firmware block, but must instead point to the first *good*
+ * firmware block.
+ */
+ while (mtd_peb_is_bad(mtd, block)) {
+ block++;
+ blocksleft--;
+ if (!blocksleft)
+ break;
+ }
+
+ return block * pages_per_block;
+}
+
+
static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned num, void *buf,
size_t len)
{
@@ -1073,9 +1107,8 @@ static void read_firmware_all(struct mtd_info *mtd, struct fcb_block *fcb, void
int *used_refresh, int *unused_refresh, int *used)
{
void *primary = NULL, *secondary = NULL;
- int pages_per_block = mtd->erasesize / mtd->writesize;
- int fw0 = imx_bbu_firmware_start_block(mtd, 0) * pages_per_block;
- int fw1 = imx_bbu_firmware_start_block(mtd, 1) * pages_per_block;
+ int fw0 = imx_bbu_firmware_fcb_start_page(mtd, 0);
+ int fw1 = imx_bbu_firmware_fcb_start_page(mtd, 1);
int first, ret, primary_refresh = 0, secondary_refresh = 0;
*used_refresh = 0;
@@ -1157,7 +1190,6 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
unsigned fw_size, partition_size;
enum filetype filetype;
unsigned num_blocks_fw;
- int pages_per_block;
int used = 0;
int fw_orig_len;
int used_refresh = 0, unused_refresh = 0;
@@ -1180,7 +1212,6 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
mtd = bcb_cdev->mtd;
partition_size = mtd->size;
- pages_per_block = mtd->erasesize / mtd->writesize;
for (i = 0; i < 4; i++) {
read_fcb(mtd, i, &fcb);
@@ -1263,8 +1294,8 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
free(fcb);
fcb = xzalloc(sizeof(*fcb));
- fcb->Firmware1_startingPage = imx_bbu_firmware_start_block(mtd, !used) * pages_per_block;
- fcb->Firmware2_startingPage = imx_bbu_firmware_start_block(mtd, used) * pages_per_block;
+ fcb->Firmware1_startingPage = imx_bbu_firmware_fcb_start_page(mtd, !used);
+ fcb->Firmware2_startingPage = imx_bbu_firmware_fcb_start_page(mtd, used);
fcb->PagesInFirmware1 = fw_size / mtd->writesize;
fcb->PagesInFirmware2 = fcb->PagesInFirmware1;