// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_MISC_INIT_R #define _AML_MISC_INTERRUPT_KEY 0x09 static int _aml_interrupt_key_pressed; static int ctrli(void) { if (1/*gd->have_console*/) { if (tstc()) { int c = getc(); switch (c) { case _AML_MISC_INTERRUPT_KEY:/* ^I - Control I */ _aml_interrupt_key_pressed = 1; printf("Detect Ctrl I...\t\nInput yes to force stopped anyway:\t"); return 1; default: printf("Detect 0x%x\n", c); break; } } } return 0; } static int aml_misc_confirm_yesno(const int tm/*timeout in ms*/) { int i; unsigned long ts; char str_input[5]; _aml_interrupt_key_pressed = 0; if (!ctrli()) {//not detect ctrl-I when bootup return 0; } ts = get_timer(0); for (i = 0; i < sizeof(str_input);) { int c = 0; while (!tstc()) { if (get_timer(ts) >= tm) { printf("Input timeout\n"); return 0; } } c = getc(); if (i == 0 && c == _AML_MISC_INTERRUPT_KEY) {//drop first duplicated ctrlI printf("Wait YES/y input\n"); continue; } putc(c); str_input[i++] = c; if (c == '\r') break; } putc('\n'); if (strncmp(str_input, "y\r", 2) == 0 || strncmp(str_input, "Y\r", 2) == 0 || strncmp(str_input, "yes\r", 4) == 0 || strncmp(str_input, "YES\r", 4) == 0) return 1; return 0; } int misc_init_r(void) { printf("board common misc_init\n"); #ifdef CONFIG_MDUMP_COMPRESS extern void ramdump_init(void); ramdump_init(); #endif if (!aml_misc_confirm_yesno(5000)) return 0; cli_init(); cli_loop(); panic("No CLI available"); return 0; } #endif // #ifdef CONFIG_MISC_INIT_R #ifdef CONFIG_AB_UPDATE #include #include #include #include #include int ab_mode(void) { printf("\nchoice A/B upgrade\n"); /******************************************************************** * 1. read partition of fip_a and fip_b ddr then verify two partition; * 2. read env form "active_slot" to choice boot from which partition. ********************************************************************/ char *p_env = NULL; unsigned int ret = 0; unsigned char buff[32]; //extern void aml_u8_printf(void *pBuffer, int nSize); run_command("run bcb_cmd", 0); p_env = getenv("active_slot"); printf("p_env = %s\n", p_env); if (IS_FEAT_BOOT_VERIFY()) { /* verify partition of fi_a and fip_b */ printf("\nneed to verify part of a/b\n"); ret = store_read_ops((unsigned char *)"fip_a", (unsigned char *)FIP_A_LOADADDR, 0, FIP_LOAD_SIZE + 0x400); if (ret) goto exit; printf("\nread pass form part of a/b\n"); ret = aml_sec_boot_check(AML_D_P_IMG_DECRYPT, FIP_A_LOADADDR, FIP_LOAD_SIZE + 0x400, GXB_IMG_DEC_ALL); if (ret) { printf("\nfip_a : Sig Check %d\n", ret); goto exit; } ret = store_read_ops((unsigned char *)"fip_b", (unsigned char *)FIP_B_LOADADDR, 0, FIP_LOAD_SIZE + 0x400); if (ret) goto exit; ret = aml_sec_boot_check(AML_D_P_IMG_DECRYPT, FIP_B_LOADADDR, FIP_LOAD_SIZE + 0x400, GXB_IMG_DEC_ALL); if (ret) { printf("\nfip_b : Sig Check %d\n", ret); goto exit; } printf("\nfip_a and fip_b verify pass\n"); } else { /* calculate SHA digest for fip_a and fip_b */ ret = store_read_ops((unsigned char *)"fip_a", (unsigned char *)FIP_A_LOADADDR, 0, FIP_LOAD_SIZE); if (ret) goto exit; sha256_csum_wd((unsigned char *)(FIP_A_LOADADDR), (FIP_LOAD_SIZE - 32), (unsigned char *)buff, 0); #ifdef DEBUG printf("fip a buff sha is :\n"); aml_u8_printf((void *)buff, 0x20); printf("fip a origin sha is :\n"); aml_u8_printf((void *)(FIP_A_LOADADDR + FIP_LOAD_SIZE - 32), 0x20); #endif if (memcmp(buff, (void *)(FIP_A_LOADADDR + FIP_LOAD_SIZE - 32), 32)) { printf("FIP_A SHA NOT OK\n"); goto exit; } ret = store_read_ops((unsigned char *)"fip_b", (unsigned char *)FIP_B_LOADADDR, 0, FIP_LOAD_SIZE); if (ret) goto exit; sha256_csum_wd((unsigned char *)(FIP_B_LOADADDR), (FIP_LOAD_SIZE - 32), (unsigned char *)buff, 0); #ifdef DEBUG printf("fip b buff sha is :\n"); aml_u8_printf((void *)buff, 0x20); printf("fip b origin sha is :\n"); aml_u8_printf((void *)(FIP_B_LOADADDR + FIP_LOAD_SIZE - 32), 0x20); #endif if (memcmp(buff, (void *)(FIP_B_LOADADDR + FIP_LOAD_SIZE - 32), 32)) { printf("FIP_B SHA NOT OK\n"); goto exit; } } if (strcmp(p_env, "_a") == 0) { printf("\nchoice fip A upgrade\n"); if (IS_FEAT_BOOT_VERIFY()) memmove((unsigned char *)CONFIG_SYS_TEXT_BASE, (unsigned char *)FIP_A_LOADADDR + 0x200, FIP_LOAD_SIZE); else memmove((unsigned char *)CONFIG_SYS_TEXT_BASE, (unsigned char *)FIP_A_LOADADDR, FIP_LOAD_SIZE); } else if (strcmp(p_env, "_b") == 0) { printf("\nset fip B upgrade\n"); if (IS_FEAT_BOOT_VERIFY()) memmove((unsigned char *)CONFIG_SYS_TEXT_BASE, (unsigned char *)FIP_B_LOADADDR + 0x200, FIP_LOAD_SIZE); else memmove((unsigned char *)CONFIG_SYS_TEXT_BASE, (unsigned char *)FIP_B_LOADADDR, FIP_LOAD_SIZE); } else { printf("Error (Need debug): active_slot(%s) is not ab mode\n", p_env); goto exit; } unsigned long bl33_entry = CONFIG_SYS_TEXT_BASE; /* run bl33 directly */ typedef unsigned long (*FUNC_TPL)(void); printf("bl33 entry: 0x%lx\n", bl33_entry); FUNC_TPL func_tpl = (FUNC_TPL)bl33_entry; func_tpl(); exit: return 0; } #endif static int board_get_bootid(void) { int boot_id = 0; #if defined(P_AO_SEC_GP_CFG0) boot_id = readl(P_AO_SEC_GP_CFG0) & 0xf; #endif// #if defined(P_AO_SEC_GP_CFG0) return boot_id; } void board_set_boot_source(void) { const char *source; switch (board_get_bootid()) { case BOOT_ID_EMMC: source = "emmc"; break; case BOOT_ID_NAND: source = "nand"; break; case BOOT_ID_SPI: source = "spi"; break; case BOOT_ID_SDCARD: source = "sd"; break; case BOOT_ID_USB: source = "usb"; break; default: source = "unknown"; } setenv("boot_source", source); printf("%s, boot_source: %s\n", __func__, source); }