/* * Copyright (C) 2009 Texas Instruments Incorporated * * Copyright (C) 2011 * Heiko Schocher, DENX Software Engineering, hs@denx.de. * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_DAVINCI_MMC #include #include #endif DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SPL_BUILD static struct davinci_timer *timer = (struct davinci_timer *)DAVINCI_TIMER3_BASE; static unsigned long get_timer_val(void) { unsigned long now = readl(&timer->tim34); return now; } static int timer_running(void) { return readl(&timer->tcr) & (DV_TIMER_TCR_ENAMODE_MASK << DV_TIMER_TCR_ENAMODE34_SHIFT); } static void stop_timer(void) { writel(0x0, &timer->tcr); return; } int checkboard(void) { printf("Board: AIT CAM ENC 4XX\n"); return 0; } int board_init(void) { gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; return 0; } #ifdef CONFIG_DRIVER_TI_EMAC static int cam_enc_4xx_check_network(void) { char *s; s = getenv("ethaddr"); if (!s) return -EINVAL; if (!is_valid_ether_addr((const u8 *)s)) return -EINVAL; s = getenv("ipaddr"); if (!s) return -EINVAL; s = getenv("netmask"); if (!s) return -EINVAL; s = getenv("serverip"); if (!s) return -EINVAL; s = getenv("gatewayip"); if (!s) return -EINVAL; return 0; } int board_eth_init(bd_t *bis) { int ret; ret = cam_enc_4xx_check_network(); if (ret) return ret; davinci_emac_initialize(); return 0; } #endif #ifdef CONFIG_NAND_DAVINCI static int davinci_std_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { struct nand_chip *this = mtd->priv; int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *oob = chip->oob_poi; chip->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); chip->read_buf(mtd, oob, mtd->oobsize); chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, page & this->pagemask); for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; chip->ecc.hwctl(mtd, NAND_ECC_READ); chip->read_buf(mtd, p, eccsize); chip->ecc.hwctl(mtd, NAND_ECC_READSYN); if (chip->ecc.prepad) oob += chip->ecc.prepad; stat = chip->ecc.correct(mtd, p, oob, NULL); if (stat == -1) mtd->ecc_stats.failed++; else mtd->ecc_stats.corrected += stat; oob += eccbytes; if (chip->ecc.postpad) oob += chip->ecc.postpad; } /* Calculate remaining oob bytes */ i = mtd->oobsize - (oob - chip->oob_poi); if (i) chip->read_buf(mtd, oob, i); return 0; } static int davinci_std_write_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { unsigned char davinci_ecc_buf[NAND_MAX_OOBSIZE]; struct nand_chip *this = mtd->priv; int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; int offset = 0; const uint8_t *p = buf; uint8_t *oob = chip->oob_poi; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_WRITE); chip->write_buf(mtd, p, eccsize); /* Calculate ECC without prepad */ chip->ecc.calculate(mtd, p, oob + chip->ecc.prepad); if (chip->ecc.prepad) { offset = (chip->ecc.steps - eccsteps) * chunk; memcpy(&davinci_ecc_buf[offset], oob, chip->ecc.prepad); oob += chip->ecc.prepad; } offset = ((chip->ecc.steps - eccsteps) * chunk) + chip->ecc.prepad; memcpy(&davinci_ecc_buf[offset], oob, eccbytes); oob += eccbytes; if (chip->ecc.postpad) { offset = ((chip->ecc.steps - eccsteps) * chunk) + chip->ecc.prepad + eccbytes; memcpy(&davinci_ecc_buf[offset], oob, chip->ecc.postpad); oob += chip->ecc.postpad; } } /* * Write the sparebytes into the page once * all eccsteps have been covered */ for (i = 0; i < mtd->oobsize; i++) writeb(davinci_ecc_buf[i], this->IO_ADDR_W); /* Calculate remaining oob bytes */ i = mtd->oobsize - (oob - chip->oob_poi); if (i) chip->write_buf(mtd, oob, i); return 0; } static int davinci_std_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page) { int pos, status = 0; const uint8_t *bufpoi = chip->oob_poi; pos = mtd->writesize; chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); chip->write_buf(mtd, bufpoi, mtd->oobsize); chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); status = chip->waitfunc(mtd, chip); return status & NAND_STATUS_FAIL ? -1 : 0; } static int davinci_std_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page) { struct nand_chip *this = mtd->priv; uint8_t *buf = chip->oob_poi; uint8_t *bufpoi = buf; chip->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); chip->read_buf(mtd, bufpoi, mtd->oobsize); return 0; } static void nand_dm365evm_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *this = mtd->priv; unsigned long wbase = (unsigned long) this->IO_ADDR_W; unsigned long rbase = (unsigned long) this->IO_ADDR_R; if (chip == 1) { __set_bit(14, &wbase); __set_bit(14, &rbase); } else { __clear_bit(14, &wbase); __clear_bit(14, &rbase); } this->IO_ADDR_W = (void *)wbase; this->IO_ADDR_R = (void *)rbase; } int board_nand_init(struct nand_chip *nand) { davinci_nand_init(nand); nand->select_chip = nand_dm365evm_select_chip; return 0; } struct nand_ecc_ctrl org_ecc; static int notsaved = 1; static int nand_switch_hw_func(int mode) { struct nand_chip *nand; struct mtd_info *mtd; if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[nand_curr_device].name) { printf("Error: Can't switch hw functions," \ " no devices available\n"); return -1; } mtd = &nand_info[nand_curr_device]; nand = mtd->priv; if (mode == 0) { if (notsaved == 0) { printf("switching to uboot hw functions.\n"); memcpy(&nand->ecc, &org_ecc, sizeof(struct nand_ecc_ctrl)); } } else { /* RBL */ printf("switching to RBL hw functions.\n"); if (notsaved == 1) { memcpy(&org_ecc, &nand->ecc, sizeof(struct nand_ecc_ctrl)); notsaved = 0; } nand->ecc.mode = NAND_ECC_HW_SYNDROME; nand->ecc.prepad = 6; nand->ecc.read_page = davinci_std_read_page_syndrome; nand->ecc.write_page = davinci_std_write_page_syndrome; nand->ecc.read_oob = davinci_std_read_oob_syndrome; nand->ecc.write_oob = davinci_std_write_oob_syndrome; } return mode; } static int hwmode; static int do_switch_ecc(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { if (argc != 2) goto usage; if (strncmp(argv[1], "rbl", 2) == 0) hwmode = nand_switch_hw_func(1); else if (strncmp(argv[1], "uboot", 2) == 0) hwmode = nand_switch_hw_func(0); else goto usage; return 0; usage: printf("Usage: nandrbl %s\n", cmdtp->usage); return 1; } U_BOOT_CMD( nandrbl, 2, 1, do_switch_ecc, "switch between rbl/uboot NAND ECC calculation algorithm", "[rbl/uboot] - Switch between rbl/uboot NAND ECC algorithm" ); #endif /* #ifdef CONFIG_NAND_DAVINCI */ #ifdef CONFIG_DAVINCI_MMC static struct davinci_mmc mmc_sd0 = { .reg_base = (struct davinci_mmc_regs *)DAVINCI_MMC_SD0_BASE, .input_clk = 121500000, .host_caps = MMC_MODE_4BIT, .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, .version = MMC_CTLR_VERSION_2, }; int board_mmc_init(bd_t *bis) { int err; /* Add slot-0 to mmc subsystem */ err = davinci_mmc_init(bis, &mmc_sd0); return err; } #endif int board_late_init(void) { struct davinci_gpio *gpio = davinci_gpio_bank45; /* 24MHz InputClock / 15 prediv -> 1.6 MHz timer running */ while ((get_timer_val() < CONFIG_AIT_TIMER_TIMEOUT) && timer_running()) ; /* 1 sec reached -> stop timer, clear all LED */ stop_timer(); clrbits_le32(&gpio->out_data, CONFIG_CAM_ENC_LED_MASK); return 0; } void reset_phy(void) { char *name = "GENERIC @ 0x00"; /* reset the phy */ miiphy_reset(name, 0x0); } #else /* #ifndef CONFIG_SPL_BUILD */ static void cam_enc_4xx_set_all_led(void) { struct davinci_gpio *gpio = davinci_gpio_bank45; setbits_le32(&gpio->out_data, CONFIG_CAM_ENC_LED_MASK); } /* * TIMER 0 is used for tick */ static struct davinci_timer *timer = (struct davinci_timer *)DAVINCI_TIMER3_BASE; #define TIMER_LOAD_VAL 0xffffffff #define TIM_CLK_DIV 16 static int cam_enc_4xx_timer_init(void) { /* We are using timer34 in unchained 32-bit mode, full speed */ writel(0x0, &timer->tcr); writel(0x0, &timer->tgcr); writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr); writel(0x0, &timer->tim34); writel(TIMER_LOAD_VAL, &timer->prd34); writel(2 << 22, &timer->tcr); return 0; } void board_gpio_init(void) { struct davinci_gpio *gpio; cam_enc_4xx_set_all_led(); cam_enc_4xx_timer_init(); gpio = davinci_gpio_bank01; clrbits_le32(&gpio->dir, ~0xfdfffffe); /* clear LED D14 = GPIO25 */ clrbits_le32(&gpio->out_data, 0x02000000); gpio = davinci_gpio_bank23; clrbits_le32(&gpio->dir, ~0x5ff0afef); /* set GPIO61 to 1 -> intern UART0 as Console */ setbits_le32(&gpio->out_data, 0x20000000); /* * PHY out of reset GIO 50 = 1 * NAND WP off GIO 51 = 1 */ setbits_le32(&gpio->out_data, 0x000c0004); gpio = davinci_gpio_bank45; clrbits_le32(&gpio->dir, ~(0xdb2fffff) | CONFIG_CAM_ENC_LED_MASK); /* * clear LED: * D17 = GPIO86 * D11 = GPIO87 * GPIO88 * GPIO89 * D13 = GPIO90 * GPIO91 */ clrbits_le32(&gpio->out_data, CONFIG_CAM_ENC_LED_MASK); gpio = davinci_gpio_bank67; clrbits_le32(&gpio->dir, ~0x000007ff); } /* * functions for the post memory test. */ int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset) { *vstart = CONFIG_SYS_SDRAM_BASE; *size = PHYS_SDRAM_1_SIZE; *phys_offset = 0; return 0; } void arch_memory_failure_handle(void) { cam_enc_4xx_set_all_led(); puts("mem failure\n"); while (1) ; } #endif #if defined(CONFIG_MENU) #include "menu.h" #define MENU_EXIT -1 #define MENU_EXIT_BOOTCMD -2 #define MENU_STAY 0 #define MENU_MAIN 1 #define MENU_UPDATE 2 #define MENU_NETWORK 3 #define MENU_LOAD 4 static int menu_start; #define FIT_SUBTYPE_UNKNOWN 0 #define FIT_SUBTYPE_UBL_HEADER 1 #define FIT_SUBTYPE_SPL_IMAGE 2 #define FIT_SUBTYPE_UBOOT_IMAGE 3 #define FIT_SUBTYPE_DF_ENV_IMAGE 4 #define FIT_SUBTYPE_RAMDISK_IMAGE 5 struct fit_images_info { u_int8_t type; int subtype; char desc[200]; const void *data; size_t size; }; static struct fit_images_info imgs[10]; struct menu_display { char title[50]; int timeout; /* in sec */ int id; /* MENU_* */ char **menulist; int (*menu_evaluate)(char *choice); }; char *menu_main[] = { "(1) Boot", "(2) Update Software", "(3) Reset to default setting and boot", "(4) Enter U-Boot console", NULL }; char *menu_update[] = { "(1) Network settings", "(2) load image", "(3) back to main", NULL }; char *menu_load[] = { "(1) install image", "(2) cancel", NULL }; char *menu_network[] = { "(1) ipaddr ", "(2) netmask ", "(3) serverip ", "(4) gatewayip", "(5) tftp image name", "(6) back to update software", NULL }; static void ait_menu_print(void *data) { printf("%s\n", (char *)data); return; } static char *menu_handle(struct menu_display *display) { struct menu *m; int i; void *choice = NULL; char key[2]; int ret; char *s; char temp[6][200]; m = menu_create(display->title, display->timeout, 1, ait_menu_print, NULL, NULL); for (i = 0; display->menulist[i]; i++) { sprintf(key, "%d", i + 1); if (display->id == MENU_NETWORK) { switch (i) { case 0: s = getenv("ipaddr"); break; case 1: s = getenv("netmask"); break; case 2: s = getenv("serverip"); break; case 3: s = getenv("gatewayip"); break; case 4: s = getenv("img_file"); break; default: s = NULL; break; } if (s) { sprintf(temp[i], "%s: %s", display->menulist[i], s); ret = menu_item_add(m, key, temp[i]); } else { ret = menu_item_add(m, key, display->menulist[i]); } } else { ret = menu_item_add(m, key, display->menulist[i]); } if (ret != 1) { printf("failed to add item!"); menu_destroy(m); return NULL; } } sprintf(key, "%d", 1); menu_default_set(m, key); if (menu_get_choice(m, &choice) != 1) debug("Problem picking a choice!\n"); menu_destroy(m); return choice; } static int ait_menu_show(struct menu_display *display, int bootdelay) { int end = MENU_STAY; char *choice; if ((menu_start == 0) && (display->id == MENU_MAIN)) display->timeout = bootdelay; else display->timeout = 0; while (end == MENU_STAY) { choice = menu_handle(display); if (choice) end = display->menu_evaluate(choice); if (end == display->id) end = MENU_STAY; if (display->id == MENU_MAIN) { if (menu_start == 0) end = MENU_EXIT_BOOTCMD; else display->timeout = 0; } } return end; } static int ait_writeublheader(void) { char s[20]; unsigned long i; int ret; for (i = CONFIG_SYS_NAND_BLOCK_SIZE; i < CONFIG_SYS_NAND_U_BOOT_OFFS; i += CONFIG_SYS_NAND_BLOCK_SIZE) { sprintf(s, "%lx", i); ret = setenv("header_addr", s); if (ret == 0) ret = run_command("run img_writeheader", 0); if (ret != 0) break; } return ret; } static int ait_menu_install_images(void) { int ret = 0; int count = 0; char s[100]; char *t; /* * possible image types: * FIT_SUBTYPE_UNKNOWN * FIT_SUBTYPE_UBL_HEADER * FIT_SUBTYPE_SPL_IMAGE * FIT_SUBTYPE_UBOOT_IMAGE * FIT_SUBTYPE_DF_ENV_IMAGE * FIT_SUBTYPE_RAMDISK_IMAGE * * use Envvariables: * img_addr_r: image start addr * header_addr: addr where to write to UBL header * img_writeheader: write ubl header to nand * img_writespl: write spl to nand * img_writeuboot: write uboot to nand * img_writedfenv: write default environment to ubi volume * img_volume: which ubi volume should be updated with img_writeramdisk * filesize: size of data for updating ubi volume * img_writeramdisk: write ramdisk to ubi volume */ while (imgs[count].type != IH_TYPE_INVALID) { printf("Installing %s\n", genimg_get_type_name(imgs[count].type)); sprintf(s, "%p", imgs[count].data); setenv("img_addr_r", s); sprintf(s, "%lx", (unsigned long)imgs[count].size); setenv("filesize", s); switch (imgs[count].subtype) { case FIT_SUBTYPE_DF_ENV_IMAGE: ret = run_command("run img_writedfenv", 0); break; case FIT_SUBTYPE_RAMDISK_IMAGE: t = getenv("img_volume"); if (!t) { ret = setenv("img_volume", "rootfs1"); } else { /* switch to other volume */ if (strncmp(t, "rootfs1", 7) == 0) ret = setenv("img_volume", "rootfs2"); else ret = setenv("img_volume", "rootfs1"); } if (ret != 0) break; ret = run_command("run img_writeramdisk", 0); break; case FIT_SUBTYPE_SPL_IMAGE: ret = run_command("run img_writespl", 0); break; case FIT_SUBTYPE_UBL_HEADER: ret = ait_writeublheader(); break; case FIT_SUBTYPE_UBOOT_IMAGE: ret = run_command("run img_writeuboot", 0); break; default: /* not supported type */ break; } count++; } /* now save dvn_* and img_volume env vars to new values */ if (ret == 0) { t = getenv("x_dvn_boot_vers"); if (t) setenv("dvn_boot_vers", t); t = getenv("x_dvn_app_vers"); if (t) setenv("dvn_boot_vers", t); setenv("x_dvn_boot_vers", NULL); setenv("x_dvn_app_vers", NULL); ret = run_command("run savenewvers", 0); } return ret; } static int ait_menu_evaluate_load(char *choice) { if (!choice) return -1; switch (choice[1]) { case '1': /* install image */ ait_menu_install_images(); break; case '2': /* cancel, back to main */ setenv("x_dvn_boot_vers", NULL); setenv("x_dvn_app_vers", NULL); break; } return MENU_MAIN; } struct menu_display ait_load = { .title = "AIT load image", .timeout = 0, .id = MENU_LOAD, .menulist = menu_load, .menu_evaluate = ait_menu_evaluate_load, }; static void ait_menu_read_env(char *name) { char output[CONFIG_SYS_CBSIZE]; char cbuf[CONFIG_SYS_CBSIZE]; int readret; int ret; sprintf(output, "%s old: %s value: ", name, getenv(name)); memset(cbuf, 0, CONFIG_SYS_CBSIZE); readret = cli_readline_into_buffer(output, cbuf, 0); if (readret >= 0) { ret = setenv(name, cbuf); if (ret) { printf("Error setting %s\n", name); return; } } return; } static int ait_menu_evaluate_network(char *choice) { if (!choice) return MENU_MAIN; switch (choice[1]) { case '1': ait_menu_read_env("ipaddr"); break; case '2': ait_menu_read_env("netmask"); break; case '3': ait_menu_read_env("serverip"); break; case '4': ait_menu_read_env("gatewayip"); break; case '5': ait_menu_read_env("img_file"); break; case '6': return MENU_UPDATE; break; } return MENU_STAY; } struct menu_display ait_network = { .title = "AIT network settings", .timeout = 0, .id = MENU_NETWORK, .menulist = menu_network, .menu_evaluate = ait_menu_evaluate_network, }; static int fit_get_subtype(const void *fit, int noffset, char **subtype) { int len; *subtype = (char *)fdt_getprop(fit, noffset, "subtype", &len); if (*subtype == NULL) return -1; return 0; } static int ait_subtype_nr(char *subtype) { int ret = FIT_SUBTYPE_UNKNOWN; if (!strncmp("ublheader", subtype, strlen("ublheader"))) return FIT_SUBTYPE_UBL_HEADER; if (!strncmp("splimage", subtype, strlen("splimage"))) return FIT_SUBTYPE_SPL_IMAGE; if (!strncmp("ubootimage", subtype, strlen("ubootimage"))) return FIT_SUBTYPE_UBOOT_IMAGE; if (!strncmp("dfenvimage", subtype, strlen("dfenvimage"))) return FIT_SUBTYPE_DF_ENV_IMAGE; return ret; } static int ait_menu_check_image(void) { char *s; unsigned long fit_addr; void *addr; int format; char *desc; char *subtype; int images_noffset; int noffset; int ndepth; int count = 0; int ret; int i; int found_uboot = -1; int found_ramdisk = -1; memset(imgs, 0, sizeof(imgs)); s = getenv("fit_addr_r"); fit_addr = s ? (unsigned long)simple_strtol(s, NULL, 16) : \ CONFIG_BOARD_IMG_ADDR_R; addr = (void *)fit_addr; /* check if it is a FIT image */ format = genimg_get_format(addr); if (format != IMAGE_FORMAT_FIT) return -EINVAL; if (!fit_check_format(addr)) return -EINVAL; /* print the FIT description */ ret = fit_get_desc(addr, 0, &desc); printf("FIT description: "); if (ret) printf("unavailable\n"); else printf("%s\n", desc); /* find images */ images_noffset = fdt_path_offset(addr, FIT_IMAGES_PATH); if (images_noffset < 0) { printf("Can't find images parent node '%s' (%s)\n", FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return -EINVAL; } /* Process its subnodes, print out component images details */ for (ndepth = 0, count = 0, noffset = fdt_next_node(addr, images_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(addr, noffset, &ndepth)) { if (ndepth == 1) { /* * Direct child node of the images parent node, * i.e. component image node. */ printf("Image %u (%s)\n", count, fit_get_name(addr, noffset, NULL)); fit_image_print(addr, noffset, ""); fit_image_get_type(addr, noffset, &imgs[count].type); /* Mandatory properties */ ret = fit_get_desc(addr, noffset, &desc); printf("Description: "); if (ret) printf("unavailable\n"); else printf("%s\n", desc); ret = fit_get_subtype(addr, noffset, &subtype); printf("Subtype: "); if (ret) { printf("unavailable\n"); } else { imgs[count].subtype = ait_subtype_nr(subtype); printf("%s %d\n", subtype, imgs[count].subtype); } sprintf(imgs[count].desc, "%s", desc); ret = fit_image_get_data(addr, noffset, &imgs[count].data, &imgs[count].size); printf("Data Size: "); if (ret) printf("unavailable\n"); else genimg_print_size(imgs[count].size); printf("Data @ %p\n", imgs[count].data); count++; } } for (i = 0; i < count; i++) { if (imgs[i].subtype == FIT_SUBTYPE_UBOOT_IMAGE) found_uboot = i; if (imgs[i].type == IH_TYPE_RAMDISK) { found_ramdisk = i; imgs[i].subtype = FIT_SUBTYPE_RAMDISK_IMAGE; } } /* dvn_* env var update, if the FIT descriptors are different */ if (found_uboot >= 0) { s = getenv("dvn_boot_vers"); if (s) { ret = strcmp(s, imgs[found_uboot].desc); if (ret != 0) { setenv("x_dvn_boot_vers", imgs[found_uboot].desc); } else { found_uboot = -1; printf("no new uboot version\n"); } } else { setenv("dvn_boot_vers", imgs[found_uboot].desc); } } if (found_ramdisk >= 0) { s = getenv("dvn_app_vers"); if (s) { ret = strcmp(s, imgs[found_ramdisk].desc); if (ret != 0) { setenv("x_dvn_app_vers", imgs[found_ramdisk].desc); } else { found_ramdisk = -1; printf("no new ramdisk version\n"); } } else { setenv("dvn_app_vers", imgs[found_ramdisk].desc); } } if ((found_uboot == -1) && (found_ramdisk == -1)) return -EINVAL; return 0; } static int ait_menu_evaluate_update(char *choice) { int ret; if (!choice) return MENU_MAIN; switch (choice[1]) { case '1': return ait_menu_show(&ait_network, 0); break; case '2': /* load image */ ret = run_command("run load_img", 0); printf("ret: %d\n", ret); if (ret) return MENU_UPDATE; ret = ait_menu_check_image(); if (ret) return MENU_UPDATE; return ait_menu_show(&ait_load, 0); break; case '3': return MENU_MAIN; break; } return MENU_MAIN; } struct menu_display ait_update = { .title = "AIT Update Software", .timeout = 0, .id = MENU_UPDATE, .menulist = menu_update, .menu_evaluate = ait_menu_evaluate_update, }; static int ait_menu_evaluate_main(char *choice) { if (!choice) return MENU_STAY; menu_start = 1; switch (choice[1]) { case '1': /* run bootcmd */ return MENU_EXIT_BOOTCMD; break; case '2': return ait_menu_show(&ait_update, 0); break; case '3': /* reset to default settings */ setenv("app_reset", "yes"); return MENU_EXIT_BOOTCMD; break; case '4': /* u-boot shell */ return MENU_EXIT; break; } return MENU_EXIT; } struct menu_display ait_main = { .title = "AIT Main", .timeout = CONFIG_BOOTDELAY, .id = MENU_MAIN, .menulist = menu_main, .menu_evaluate = ait_menu_evaluate_main, }; int menu_show(int bootdelay) { int ret; run_command("run saveparms", 0); ret = ait_menu_show(&ait_main, bootdelay); run_command("run restoreparms", 0); if (ret == MENU_EXIT_BOOTCMD) return 0; return MENU_EXIT; } void menu_display_statusline(struct menu *m) { char *s1, *s2; s1 = getenv("x_dvn_boot_vers"); if (!s1) s1 = getenv("dvn_boot_vers"); s2 = getenv("x_dvn_app_vers"); if (!s2) s2 = getenv("dvn_app_vers"); printf("State: dvn_boot_vers: %s dvn_app_vers: %s\n", s1, s2); return; } #endif