539 lines
14 KiB
C
539 lines
14 KiB
C
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
|
/*
|
|
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <asm/io.h>
|
|
#include <malloc.h>
|
|
#include <errno.h>
|
|
#include <environment.h>
|
|
#include <fdt_support.h>
|
|
#include <linux/libfdt.h>
|
|
#include <amlogic/cpu_id.h>
|
|
#include <cli.h>
|
|
#include <console.h>
|
|
#include <generated/version_autogenerated.h>
|
|
#include <amlogic/aml_v3_burning.h>
|
|
#include <amlogic/aml_v2_burning.h>
|
|
#include <amlogic/board.h>
|
|
#include <asm/arch/secure_apb.h>
|
|
#include <asm/arch/romboot.h>
|
|
#ifdef CONFIG_AML_VPU
|
|
#include <vpu.h>
|
|
#endif
|
|
#include <vpp.h>
|
|
#ifdef CONFIG_RX_RTERM
|
|
#include <amlogic/aml_hdmirx.h>
|
|
#endif
|
|
#ifdef CONFIG_AML_VOUT
|
|
#include <amlogic/media/vout/aml_vout.h>
|
|
#endif
|
|
#ifdef CONFIG_AML_LCD
|
|
#include <amlogic/media/vout/lcd/lcd_vout.h>
|
|
#endif
|
|
#ifdef CONFIG_AML_CVBS
|
|
#include <amlogic/media/vout/aml_cvbs.h>
|
|
#endif
|
|
#ifdef CONFIG_ARMV8_MULTIENTRY
|
|
#include <asm/arch-meson/smp.h>
|
|
#endif
|
|
#include <amlogic/aml_profile.h>
|
|
#include <abuf.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
#define UNUSED(x) (void)(x)
|
|
|
|
#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()) {
|
|
switch (getc()) {
|
|
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:
|
|
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");
|
|
#if defined(CONFIG_MDUMP_COMPRESS) || \
|
|
((defined CONFIG_SUPPORT_BL33Z) && \
|
|
(defined CONFIG_FULL_RAMDUMP))
|
|
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 <u-boot/sha256.h>
|
|
#include <emmc_partitions.h>
|
|
#include <amlogic/aml_efuse.h>
|
|
#include <amlogic/store_wrapper.h>
|
|
#include <asm/arch/bl31_apis.h>
|
|
|
|
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];
|
|
|
|
//run_command("run bcb_cmd", 0);
|
|
|
|
p_env = env_get("active_slot");
|
|
printf("p_env = %s\n", p_env);
|
|
|
|
//extern void aml_u8_printf(void *pBuffer, int nSize);
|
|
|
|
if (IS_FEAT_BOOT_VERIFY()) {
|
|
/* verify partition of fi_a and fip_b */
|
|
printf("\nneed to verify part of a/b\n");
|
|
ret = store_logic_read((const char *)"fip_a", 0,
|
|
FIP_LOAD_SIZE + 0x400, (unsigned char *)FIP_A_LOADADDR);
|
|
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_logic_read((const char *)"fip_b", 0,
|
|
FIP_LOAD_SIZE + 0x400, (unsigned char *)FIP_B_LOADADDR);
|
|
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_logic_read((const char *)"fip_a", 0, FIP_LOAD_SIZE,
|
|
(unsigned char *)FIP_A_LOADADDR);
|
|
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_logic_read((const char *)"fip_b",
|
|
0, FIP_LOAD_SIZE, (unsigned char *)FIP_B_LOADADDR);
|
|
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
|
|
|
|
#ifdef CONFIG_BOARD_LATE_INIT
|
|
int aml_board_late_init_front(void *arg)
|
|
{
|
|
UNUSED(arg);
|
|
printf("init front\n");
|
|
if (env_get_ulong("default_env", 10, 0))
|
|
env_set("defenv_para", "-c0"); //andr factory reset or factory burn
|
|
|
|
run_command("aml_update_env", 0);
|
|
/* ****************************************************
|
|
* 1.setup bootup resource
|
|
* ****************************************************
|
|
*/
|
|
board_init_mem();
|
|
run_command("run bcb_cmd", 0);
|
|
|
|
#if CONFIG_IS_ENABLED(AMLOGIC_BT_USB) || CONFIG_IS_ENABLED(AMLOGIC_WIFI_USB2T)
|
|
printf("run usb wifi_start\n");
|
|
run_command("usb wifi_start", 0);
|
|
#endif
|
|
|
|
#ifndef CONFIG_SYSTEM_RTOS //prue rtos not need dtb
|
|
PUSH_TIME_TE("load dtb", BL33_LOAD_DTB_s);
|
|
if (run_command("run common_dtb_load", 0)) {
|
|
printf("Fail in load dtb with cmd[%s], try _aml_dtb\n", env_get("common_dtb_load"));
|
|
//load dtb here then users can directly use 'fdt' command
|
|
run_command("echo reboot_mode ${reboot_mode}; "
|
|
"imgread dtb _aml_dtb ${dtb_mem_addr}; fi;", 0);
|
|
}
|
|
PUSH_TIME_TE("load dtb", BL33_LOAD_DTB_e);
|
|
run_command("if fdt addr ${dtb_mem_addr}; then else echo no dtb at ${dtb_mem_addr};fi;", 0);
|
|
/* load unifykey */
|
|
run_command("keyman init 0x1234", 0);
|
|
#endif//#ifndef CONFIG_SYSTEM_RTOS //prue rtos not need dtb
|
|
|
|
/* reset vout init state */
|
|
run_command("setenv vout_init disable", 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if !defined(SYSCTRL_SEC_STICKY_REG2) && defined(P_PREG_STICKY_REG2)
|
|
#define SYSCTRL_SEC_STICKY_REG2 P_PREG_STICKY_REG2
|
|
#endif//#if !defined(SYSCTRL_SEC_STICKY_REG2) && defined(P_PREG_STICKY_REG2)
|
|
int aml_board_late_init_tail(void *arg)
|
|
{
|
|
unsigned char chipid[16];
|
|
char con_str[128], env_str[128];
|
|
int con_len = 0;
|
|
PUSH_TIME_TE("tail init", BL33_TAIL_INIT_s);
|
|
UNUSED(arg);
|
|
printf("init tail\n");
|
|
run_command("amlsecurecheck", 0);
|
|
run_command("update_tries", 0);
|
|
|
|
//Need save outputmode/connector_type to flash if changed after display drv init
|
|
if (env_get("outputmode"))
|
|
con_len = sprintf(con_str, "outputmode");
|
|
if (env_get("connector0_type"))
|
|
con_len += sprintf(con_str + con_len, " connector0_type");
|
|
else if (env_get("connector_type"))
|
|
con_len += sprintf(con_str + con_len, " connector_type");
|
|
if (env_get("connector1_type"))
|
|
con_len += sprintf(con_str + con_len, " connector1_type");
|
|
if (env_get("connector2_type"))
|
|
con_len += sprintf(con_str + con_len, " connector2_type");
|
|
if (con_len) {
|
|
sprintf(env_str, "printenv %s", con_str);
|
|
run_command(env_str, 0);
|
|
sprintf(env_str, "update_env_part -p -f %s", con_str);
|
|
run_command(env_str, 0);
|
|
}
|
|
|
|
memset(chipid, 0, 16);
|
|
env_set("cpu_id", "1234567890");
|
|
if (get_chip_id(chipid, 16) != -1) {
|
|
char chipid_str[32];
|
|
char chipid_env[32];
|
|
int i, j;
|
|
char buf_tmp[4];
|
|
|
|
memset(chipid_str, 0, 32);
|
|
memset(chipid_env, 0, 32);
|
|
|
|
char *buff = &chipid_str[0];
|
|
char *buff2 = &chipid_env[0];
|
|
|
|
for (i = 0, j = 0; i < 12; ++i) {
|
|
sprintf(&buf_tmp[0], "%02x", chipid[15 - i]);
|
|
if (strcmp(buf_tmp, "00") != 0) {
|
|
sprintf(buff + j, "%02x", chipid[15 - i]);
|
|
j = j + 2;
|
|
}
|
|
}
|
|
|
|
for (i = 0, j = 0; i < 12; ++i) {
|
|
sprintf(buff2 + j, "%02x", chipid[15 - i]);
|
|
j = j + 2;
|
|
}
|
|
|
|
env_set("cpuid_env", chipid_env);
|
|
env_set("cpu_id", chipid_str);
|
|
printf("buff: %s\n", buff);
|
|
}
|
|
|
|
//auto enter usb mode after board_late_init if 'adnl.exe setvar burnsteps 0x1b8ec003'
|
|
#if defined(CONFIG_AML_V3_FACTORY_BURN) && defined(CONFIG_AML_V3_USB_TOOl)
|
|
if (readl(SYSCTRL_SEC_STICKY_REG2) == 0x1b8ec003)
|
|
aml_v3_factory_usb_burning(0, gd->bd);
|
|
#endif//#if defined(CONFIG_AML_V3_FACTORY_BURN) && defined(CONFIG_AML_V3_USB_TOOl)
|
|
#ifdef CONFIG_AML_FACTORY_BURN_LOCAL_UPGRADE //try auto upgrade from ext-sdcard
|
|
aml_try_factory_sdcard_burning(0, gd->bd);
|
|
#endif//#ifdef CONFIG_AML_FACTORY_BURN_LOCAL_UPGRADE
|
|
PUSH_TIME_TE("tail init", BL33_TAIL_INIT_e);
|
|
|
|
return 0;
|
|
}
|
|
#endif//#ifdef CONFIG_BOARD_LATE_INIT
|
|
|
|
void aml_board_display_env_handler(void)
|
|
{
|
|
char *bootup_display;
|
|
char *write_boot;
|
|
#ifdef CONFIG_AML_LCD
|
|
char lcd_init_str[8];
|
|
#endif
|
|
|
|
write_boot = env_get("write_boot");
|
|
run_command("get_rebootmode", 0);
|
|
printf("reboot_mode: %s\n", env_get("reboot_mode"));
|
|
run_command("run check_display", 0);
|
|
bootup_display = env_get("bootup_display");
|
|
if (!bootup_display)
|
|
return;
|
|
if (write_boot && !strcmp(write_boot, "1")) {
|
|
printf("write_boot is %s, set display to off\n", write_boot);
|
|
env_set("bootup_display", "off");
|
|
return;
|
|
}
|
|
printf("bootup_display: %s\n", bootup_display);
|
|
#ifdef CONFIG_AML_LCD
|
|
if (strcmp(bootup_display, "on") == 0)
|
|
snprintf(lcd_init_str, 8, "%d", LCD_INIT_LEVEL_NORMAL);
|
|
else if (strcmp(bootup_display, "preboot") == 0)
|
|
snprintf(lcd_init_str, 8, "%d", LCD_INIT_LEVEL_PREBOOT);
|
|
else
|
|
snprintf(lcd_init_str, 8, "%d", LCD_INIT_LEVEL_PWR_OFF);
|
|
|
|
env_set("lcd_init_level", lcd_init_str);
|
|
//printf("lcd_init_level: %s\n", env_get("lcd_init_level"));
|
|
#endif
|
|
}
|
|
|
|
static int board_get_bootid(void)
|
|
{
|
|
const cpu_id_t cpuid = get_cpu_id();
|
|
const int familyId = cpuid.family_id;
|
|
int boot_id = 0;
|
|
|
|
#ifdef SYSCTRL_SEC_STATUS_REG2
|
|
if (MESON_CPU_MAJOR_ID_SC2 <= familyId && MESON_CPU_MAJOR_ID_C2 != familyId &&
|
|
familyId != MESON_CPU_MAJOR_ID_T5W) {
|
|
boot_id = readl(SYSCTRL_SEC_STATUS_REG2);
|
|
boot_id = (boot_id >> 4) & 0xf;
|
|
}
|
|
#endif// #ifdef SYSCTRL_SEC_STATUS_REG2
|
|
|
|
#if defined(P_AO_SEC_GP_CFG0)
|
|
if ((familyId <= MESON_CPU_MAJOR_ID_T5D &&
|
|
familyId != MESON_CPU_MAJOR_ID_SC2) ||
|
|
familyId == MESON_CPU_MAJOR_ID_TXHD2 ||
|
|
familyId == MESON_CPU_MAJOR_ID_T5W) {
|
|
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";
|
|
}
|
|
|
|
env_set("boot_source", source);
|
|
printf("%s, boot_source: %s\n", __func__, source);
|
|
}
|
|
|
|
#ifdef CONFIG_AML_DEFENV
|
|
const char * const _aml_env_reserv_array[] = {
|
|
"lock",
|
|
"upgrade_step",
|
|
"bootloader_version",
|
|
"hdmimode",
|
|
"dts_to_gpt",
|
|
"fastboot_step",
|
|
"reboot_status",
|
|
"expect_index",
|
|
"recovery_check_part",
|
|
"defenv_para", //set in board_late_init
|
|
"sw_version", //linux swupdate version
|
|
"rollback_reason",
|
|
#ifndef CONFIG_CMD_CAR_PARAMS
|
|
"outputmode",
|
|
"connector_type",
|
|
#endif
|
|
NULL//Keep NULL be last to tell END
|
|
};
|
|
|
|
const char * const _aml_env_reserv_array1[] = {
|
|
"lock",
|
|
"upgrade_step",
|
|
"bootloader_version",
|
|
"dts_to_gpt",
|
|
"fastboot_step",
|
|
"reboot_status",
|
|
"expect_index",
|
|
"recovery_check_part",
|
|
"defenv_para", //set in board_late_init
|
|
NULL//Keep NULL be last to tell END
|
|
};
|
|
|
|
#endif//#ifdef CONFIG_AML_DEFENV
|
|
|
|
#ifdef CONFIG_HW_RNG_OLD
|
|
unsigned int rand(void)
|
|
{
|
|
volatile unsigned int val;
|
|
|
|
val = readl(RNG_USR_DATA);
|
|
return val;
|
|
}
|
|
#endif
|
|
|
|
void get_rng_hw(unsigned char *buf, unsigned int size)
|
|
{
|
|
unsigned int *p = (unsigned int *)buf;
|
|
unsigned int cnt, ncnt;
|
|
unsigned int i;
|
|
unsigned int rng;
|
|
|
|
cnt = (size >> 2);
|
|
ncnt = size & 0x3;
|
|
|
|
for (i = 0; i < cnt; i++)
|
|
p[i] = rand();
|
|
|
|
if (ncnt) {
|
|
rng = rand();
|
|
for (i = 0; i < ncnt; i++)
|
|
buf[cnt * 4 + i] = ((rng >> (i * 8)) & 0xff);
|
|
}
|
|
}
|
|
|
|
int board_rng_seed(struct abuf *buf)
|
|
{
|
|
abuf_init(buf);
|
|
abuf_realloc(buf, 128);
|
|
if (buf->data)
|
|
get_rng_hw(buf->data, buf->size);
|
|
|
|
return 0;
|
|
}
|
|
|