struct mtd_info *mtd = onenand_ops->mtd;
struct onenand_chip *this = mtd->priv;
int i;
- int page_to_check = 4;
- int ret, retlen = 0;
- ulong blocksize = 1 << this->erase_shift;
- ulong pagesize = 1 << this->page_shift;
- u_char *down_ram_addr;
- ulong uboot_addr;
- u_char verify_buf[0x10];
-
- down_ram_addr = (unsigned char *)CONFIG_SYS_DOWN_ADDR;
- uboot_addr = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
-
- onenand_ops->read(uboot_addr, blocksize, &retlen, down_ram_addr, 0);
- if (retlen != blocksize)
+ int retlen = 0;
+ u32 from = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
+ u32 len = 1 << this->erase_shift;
+ u32 *buf = (u32 *)CONFIG_SYS_DOWN_ADDR;
+
+ /* check first page of bootloader*/
+ onenand_ops->read(from, len, (ssize_t *)&retlen, (u_char *)buf, 0);
+ if (retlen != len)
return 1;
- memset(verify_buf, 0xFF, sizeof(verify_buf));
+ for (i = 0; i < (this->writesize / sizeof(this->writesize)); i++)
+ if (*(buf + i) != 0xffffffff)
+ return 0;
- for (i = 0; i < page_to_check; i++) {
- ret = memcmp(down_ram_addr + pagesize*i, verify_buf,
- sizeof(verify_buf));
- if (ret)
- break;
- }
-
- if (i == page_to_check)
- return 1;
-
- return 0;
+ return 1;
}
int board_check_condition(void)
{
if (check_keypad()) {
- PUTS("manual mode\n");
+ PUTS("check: manual\n");
return 1;
}
if (check_block()) {
- PUTS("bootloader image broken\n");
- return 1;
+ PUTS("check: bootloader broken\n");
+ return 2;
}
return 0;
}
-int board_load_uboot(unsigned char *buf)
+int board_load_bootloader(unsigned char *buf)
{
struct mtd_info *mtd = &onenand_mtd;
struct onenand_chip *this = mtd->priv;
- int offset;
- size_t size;
- size_t ret;
+ u32 ofs, len, retlen;
- offset = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- size = CONFIG_SYS_MONITOR_LEN;
+ ofs = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
+ len = CONFIG_SYS_MONITOR_LEN;
- mtd->read(mtd, offset, size, &ret, buf);
+ mtd->read(mtd, ofs, len, &retlen, buf);
- if (size != ret)
+ if (len != retlen)
return -1;
return 0;
}
+int board_lock_recoveryblock(void)
+{
+ struct mtd_info *mtd = &onenand_mtd;
+ struct onenand_chip *this = mtd->priv;
+ u32 ofs = 0;
+ u32 len = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
+ int ret = 0;
+
+ /* lock-tight the recovery block */
+ if (this->lock_tight != NULL)
+ ret = this->lock_tight(mtd, ofs, len);
+
+ return ret;
+}
+
+void board_update_init(void)
+{
+ struct mtd_info *mtd = &onenand_mtd;
+ struct onenand_chip *this = mtd->priv;
+
+ /* Unlock whole block */
+ this->unlock_all(mtd);
+}
+
+int board_update_image(u32 *buf, u32 len)
+{
+ struct onenand_op *onenand_ops = onenand_get_interface();
+ struct mtd_info *mtd = &onenand_mtd;
+ struct onenand_chip *this = mtd->priv;
+ u32 ofs;
+ u32 ipl_addr = 0;
+ u32 ipl_edge = CONFIG_ONENAND_START_PAGE << this->page_shift;
+ u32 recovery_addr = ipl_edge;
+ u32 recovery_edge = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
+ u32 bootloader_addr = recovery_edge;
+ u32 bootloader_edge = CONFIG_RECOVERY_BOOT_BLOCKS << this->erase_shift;
+ int ret, retlen;
+
+ if (len > bootloader_addr) {
+ if (*(buf + bootloader_addr/sizeof(buf)) == 0xea000012) {
+ /* case: IPL + Recovery + bootloader */
+ PUTS("target: ipl + recovery + bootloader\n");
+ ofs = ipl_addr;
+ /* len = bootloader_edge; */
+ } else {
+ /* case: unknown format */
+ PUTS("target: unknown\n");
+ return 1;
+ }
+ } else {
+ if (*(buf + recovery_addr/sizeof(buf)) == 0xea000012 &&
+ *(buf + recovery_addr/sizeof(buf) - 1) == 0x00000000) {
+ /* case: old image (IPL + bootloader) */
+ PUTS("target: ipl + bootloader (old type)\n");
+ ofs = ipl_addr;
+ /* len = recovery_edge; */
+ } else {
+ /* case: bootloader only */
+ PUTS("target: bootloader\n");
+ ofs = bootloader_addr;
+ /* len = bootloader_edge - recovery_edge; */
+ }
+ }
+
+ /* Erase */
+ ret = onenand_ops->erase(ofs, len, 0);
+ if (ret)
+ return ret;
+
+ /* Write */
+ onenand_ops->write(ofs, len, (ssize_t *)&retlen, (u_char *)buf);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
void board_recovery_init(void)
{
/* set GPIO to enable UART2 */