510 lines
14 KiB
C
510 lines
14 KiB
C
/*
|
||
* (C) Copyright 2017 <wangwei@allwinnertech.com>
|
||
*
|
||
* SPDX-License-Identifier: GPL-2.0+
|
||
*/
|
||
#include <common.h>
|
||
#include <securestorage.h>
|
||
#include <sunxi_board.h>
|
||
#include <version.h>
|
||
#include <sys_config.h>
|
||
#include <boot_gui.h>
|
||
#include <sys_partition.h>
|
||
#include <sunxi_verify_boot_info.h>
|
||
#include <libxbc.h>
|
||
#include <fs.h>
|
||
#include <fdt_support.h>
|
||
DECLARE_GLOBAL_DATA_PTR;
|
||
|
||
#ifdef CONFIG_SUNXI_USER_KEY
|
||
char *IGNORE_ENV_VARIABLE[] = {
|
||
"console", "root", "init", "loglevel",
|
||
"partitions", "vmalloc", "earlyprintk", "ion_reserve",
|
||
"enforcing", "cma", "initcall_debug", "gpt",
|
||
};
|
||
#define NAME_SIZE 32
|
||
int USER_DATA_NUM;
|
||
char USER_DATA_NAME[32][NAME_SIZE] = { { '\0' } };
|
||
|
||
void check_user_data(void)
|
||
{
|
||
char *command_p = NULL;
|
||
char temp_name[32] = { '\0' };
|
||
int i, j;
|
||
|
||
if ((get_boot_storage_type() == STORAGE_SD) ||
|
||
(get_boot_storage_type() == STORAGE_EMMC) ||
|
||
(get_boot_storage_type() == STORAGE_EMMC0)) {
|
||
command_p = env_get("setargs_mmc");
|
||
} else {
|
||
command_p = env_get("setargs_nand");
|
||
}
|
||
//printf("cmd line = %s\n", command_p);
|
||
if (!command_p) {
|
||
printf("cann't get the boot_base from the env\n");
|
||
return;
|
||
}
|
||
|
||
while (*command_p != '\0' && *command_p != ' ') { //过滤第一个环境变酿
|
||
command_p++;
|
||
}
|
||
command_p++;
|
||
while (*command_p == ' ') { //过滤多余的空枿
|
||
command_p++;
|
||
}
|
||
while (*command_p != '\0' && *command_p != ' ') { //过滤第二个环境变酿
|
||
command_p++;
|
||
}
|
||
command_p++;
|
||
while (*command_p == ' ') {
|
||
command_p++;
|
||
}
|
||
|
||
USER_DATA_NUM = 0;
|
||
while (*command_p != '\0') {
|
||
i = 0;
|
||
while (*command_p != '=') {
|
||
temp_name[i++] = *command_p;
|
||
command_p++;
|
||
}
|
||
temp_name[i] = '\0';
|
||
if (i != 0) {
|
||
for (j = 0; j < sizeof(IGNORE_ENV_VARIABLE) /
|
||
sizeof(IGNORE_ENV_VARIABLE[0]);
|
||
j++) {
|
||
if (!strcmp(IGNORE_ENV_VARIABLE[j],
|
||
temp_name)) { //查词典库,排除系统的环境变量,得到用户的数据
|
||
break;
|
||
}
|
||
}
|
||
if (j >= sizeof(IGNORE_ENV_VARIABLE) /
|
||
sizeof(IGNORE_ENV_VARIABLE[0])) {
|
||
if (!strcmp(temp_name,
|
||
"mac_addr")) { //处理mac_addr和mac不相等的情况(特殊情况)
|
||
strcpy(USER_DATA_NAME[USER_DATA_NUM],
|
||
"mac");
|
||
} else {
|
||
strcpy(USER_DATA_NAME[USER_DATA_NUM],
|
||
temp_name);
|
||
}
|
||
USER_DATA_NUM++;
|
||
}
|
||
}
|
||
while (*command_p != '\0' && *command_p != ' ') { //下一个变酿
|
||
command_p++;
|
||
}
|
||
while (*command_p == ' ') {
|
||
command_p++;
|
||
}
|
||
}
|
||
/*
|
||
printf("USER_DATA_NUM = %d\n", USER_DATA_NUM);
|
||
for (i = 0; i < USER_DATA_NUM; i++) {
|
||
printf("user data = %s\n", USER_DATA_NAME[i]);
|
||
}
|
||
*/
|
||
}
|
||
|
||
static int get_key_from_private(int partno, char *filename, char *data_buf, int *len)
|
||
{
|
||
char part_info[16] = { 0 }; /* format: "partno:0" */
|
||
char file_info[64] = { 0 };
|
||
loff_t len_read;
|
||
|
||
if (partno < 0)
|
||
return -1;
|
||
|
||
strcpy(file_info, filename);
|
||
|
||
/* get data from file */
|
||
sprintf(part_info, "0:%x", partno);
|
||
memset(data_buf, 0, *len);
|
||
|
||
if (fs_set_blk_dev("sunxi_flash", part_info, FS_TYPE_FAT))
|
||
return 1;
|
||
if (fs_read(filename, (ulong)data_buf, 0, 0, &len_read) < 0)
|
||
return -1;
|
||
data_buf[*len] = 0;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*ret:0:not found, 1:found*/
|
||
int sunxi_bootargs_load_key(const char *name, int *data_len, char *buffer,
|
||
int buffer_size)
|
||
{
|
||
static int partno = -1;
|
||
const char *file_path = "ULI/factory";
|
||
int ret;
|
||
int found = 0;
|
||
int sec_inited = !sunxi_secure_storage_init();
|
||
|
||
char fetch_name[64] = { 0 };
|
||
char fetch_data[64] = { 0 };
|
||
char full_name[64] = { 0 };
|
||
|
||
/* check private partition info */
|
||
if (partno == -2) {
|
||
/*already know private non exist*/
|
||
} else if (partno == -1) {
|
||
partno = sunxi_partition_get_partno_byname("private");
|
||
if (partno >= 0) {
|
||
sprintf(buffer, "fatls sunxi_flash 0:%x %s", partno,
|
||
file_path);
|
||
printf("List file under %s\n", file_path);
|
||
if (run_command(buffer, 0)) {
|
||
partno = -2;
|
||
}
|
||
}
|
||
}
|
||
|
||
found = 0;
|
||
memset(buffer, 0, 512);
|
||
if (sec_inited) {
|
||
ret = sunxi_secure_object_read(name, buffer, 512, data_len);
|
||
if (!ret && *data_len < 512) {
|
||
found = 1;
|
||
}
|
||
}
|
||
|
||
if (!found) {
|
||
*data_len = 512;
|
||
|
||
if (partno >= 0) {
|
||
sprintf(fetch_name, "%s_filename", name);
|
||
ret = script_parser_fetch("/soc/serial_feature",
|
||
fetch_name, (int *)fetch_data,
|
||
sizeof(fetch_data) / 4);
|
||
if ((ret < 0) || (strlen(fetch_data) == 0))
|
||
sprintf(full_name, "%s/%s.txt", file_path,
|
||
name);
|
||
else
|
||
sprintf(full_name, "%s", fetch_data);
|
||
|
||
ret = get_key_from_private(partno, full_name, buffer,
|
||
data_len);
|
||
if (!ret)
|
||
found = 2;
|
||
}
|
||
}
|
||
|
||
if (found) {
|
||
env_set(name, buffer);
|
||
pr_msg("update %s = %s, source:%s\n", name, buffer,
|
||
found == 2 ? "private" : "secure");
|
||
memset(buffer, 0, 512);
|
||
}
|
||
return found;
|
||
}
|
||
|
||
int update_user_data(void)
|
||
{
|
||
if (get_boot_work_mode() != WORK_MODE_BOOT) {
|
||
return 0;
|
||
}
|
||
|
||
check_user_data(); //从env中检测用户的环境变量
|
||
|
||
int data_len;
|
||
int k;
|
||
char buffer[512];
|
||
int updata_data_num = 0;
|
||
|
||
for (k = 0; k < USER_DATA_NUM; k++) {
|
||
if (sunxi_bootargs_load_key(USER_DATA_NAME[k], &data_len,
|
||
buffer, sizeof(buffer))) {
|
||
updata_data_num++;
|
||
strcpy(USER_DATA_NAME[k], "\0");
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
#endif
|
||
|
||
void update_bootargs(void)
|
||
{
|
||
int dram_clk = 0;
|
||
char *str;
|
||
char cmdline[2048] = { 0 };
|
||
char tmpbuf[128] = { 0 };
|
||
char *verifiedbootstate_info = env_get("verifiedbootstate");
|
||
str = env_get("bootargs");
|
||
__attribute__((unused)) char disp_reserve[80];
|
||
strncpy(cmdline, str, sizeof(cmdline) - 1);
|
||
|
||
if ((!strcmp(env_get("bootcmd"), "run setargs_mmc boot_normal")) ||
|
||
!strcmp(env_get("bootcmd"), "run setargs_nand boot_normal")) {
|
||
if (gd->chargemode == 0) {
|
||
pr_msg("in boot normal mode,pass normal para to cmdline\n");
|
||
strncat(cmdline, " androidboot.mode=normal",
|
||
sizeof(cmdline) - strlen(cmdline) - 1);
|
||
} else {
|
||
pr_msg("in charger mode, pass charger para to cmdline\n");
|
||
strncat(cmdline, " androidboot.mode=charger",
|
||
sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
}
|
||
#ifdef CONFIG_SUNXI_SERIAL
|
||
//serial info
|
||
str = env_get("snum");
|
||
sprintf(tmpbuf, " androidboot.serialno=%s", str);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
#endif
|
||
#ifdef CONFIG_SUNXI_MAC
|
||
str = env_get("mac");
|
||
if (str && !strstr(cmdline, " mac_addr=")) {
|
||
sprintf(tmpbuf, " mac_addr=%s", str);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
|
||
str = env_get("wifi_mac");
|
||
if (str && !strstr(cmdline, " wifi_mac=")) {
|
||
sprintf(tmpbuf, " wifi_mac=%s", str);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
|
||
str = env_get("bt_mac");
|
||
if (str && !strstr(cmdline, " bt_mac=")) {
|
||
sprintf(tmpbuf, " bt_mac=%s", str);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
#endif
|
||
//harware info
|
||
sprintf(tmpbuf, " androidboot.hardware=%s", CONFIG_SYS_CONFIG_NAME);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
/*boot type*/
|
||
sprintf(tmpbuf, " boot_type=%d", get_boot_storage_type_ext());
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
sprintf(tmpbuf, " androidboot.boot_type=%d", get_boot_storage_type_ext());
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
/*Only 64bit kernel "secure_os_exist" exists
|
||
* 64bit normal cpu no need OP-TEE service
|
||
*secure_os_exist= 0 ---> secure os no exist
|
||
*secure_os_exist= 1 ---> secure os exist
|
||
* */
|
||
if (sunxi_probe_secure_monitor()) {
|
||
sprintf(tmpbuf, " androidboot.secure_os_exist=%d", sunxi_probe_secure_os());
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
|
||
#ifdef CONFIG_SUNXI_ANDROID_BOOT
|
||
str = env_get("android_trust_chain");
|
||
if (str) {
|
||
sprintf(tmpbuf, " androidboot.trustchain=%s", str);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}else{
|
||
sprintf(tmpbuf, " androidboot.trustchain=false");
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
|
||
str = env_get("android_drmkey");
|
||
if (str) {
|
||
sprintf(tmpbuf, " androidboot.drmkey=%s", str);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
} else {
|
||
sprintf(tmpbuf, " androidboot.drmkey=false");
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
#endif
|
||
|
||
/*dram_clk*/
|
||
script_parser_fetch("soc/dram_para", "dram_clk", (int *)&dram_clk, 1);
|
||
#ifdef CONFIG_ARCH_SUN8IW15P1
|
||
sprintf(tmpbuf, " dram_clk=%d", dram_clk);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
#endif
|
||
/* gpt support */
|
||
sprintf(tmpbuf, " gpt=1");
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
|
||
if (gd->securemode) {
|
||
/* verified boot state info */
|
||
sprintf(tmpbuf, " androidboot.verifiedbootstate=%s",
|
||
verifiedbootstate_info);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
|
||
sprintf(tmpbuf, " uboot_message=%s(%s-%s)", PLAIN_VERSION, U_BOOT_DMI_DATE, U_BOOT_TIME);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
#ifdef CONFIG_SPINOR_LOGICAL_OFFSET
|
||
#if defined (CONFIG_ENABLE_MTD_CMDLINE_PARTS_BY_ENV)
|
||
char *mtdpart = env_get("sunxi_mtdparts");
|
||
char *tmpaddr;
|
||
char *desbuff =NULL;
|
||
char part_buff[218] = {0};
|
||
char device_name[16] = {0};
|
||
|
||
if(mtdpart != NULL) {
|
||
tmpaddr = strchr(mtdpart,':');
|
||
strncpy(device_name, mtdpart, (tmpaddr + 1 - mtdpart));
|
||
strcpy(part_buff, (tmpaddr+1));
|
||
desbuff = tmpbuf;
|
||
sprintf(desbuff, "%s mtdparts=%s%dK(uboot),%s", tmpbuf, device_name,
|
||
(sunxi_flashmap_logical_offset(FLASHMAP_SPI_NOR, LINUX_LOGIC_OFFSET) * 512 / 1024), part_buff);
|
||
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
#else
|
||
/*spi-nor logical offset */
|
||
sprintf(tmpbuf, " mbr_offset=%d", (sunxi_flashmap_logical_offset(FLASHMAP_SPI_NOR, LINUX_LOGIC_OFFSET)* 512));
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
#endif
|
||
#endif /*CONFIG_SPINOR_LOGICAL_OFFSET*/
|
||
|
||
#if defined(CONFIG_BOOT_GUI) || defined(CONFIG_SUNXI_SPINOR_BMP) || defined(CONFIG_SUNXI_SPINOR_JPEG)
|
||
#ifdef CONFIG_BOOT_GUI
|
||
save_disp_cmdline();
|
||
#endif
|
||
if (env_get("disp_reserve")) {
|
||
snprintf(disp_reserve, 80, " disp_reserve=%s",
|
||
env_get("disp_reserve"));
|
||
strncat(cmdline, disp_reserve,
|
||
sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_SUNXI_POWER
|
||
str = env_get("bootreason");
|
||
if (str) {
|
||
snprintf(tmpbuf, 128, " bootreason=%s", str);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_SUNXI_DM_VERITY
|
||
char dm_mod[256] = {0};
|
||
str = env_get("dm_mod");
|
||
if (str) {
|
||
snprintf(dm_mod, 256, " dm-mod.create=%s", str);
|
||
strncat(cmdline, dm_mod, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
#endif
|
||
|
||
str = env_get("aw-ubi-spinand.ubootblks");
|
||
if (str) {
|
||
snprintf(tmpbuf, 128, " aw-ubi-spinand.ubootblks=%s", str);
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
|
||
str = env_get("trace_enable");
|
||
if (str && strcmp(str, "1") == 0) {
|
||
str = env_get("trace_buf_size");
|
||
if (str) {
|
||
snprintf(tmpbuf, 128, " trace_buf_size=%s", str);
|
||
strncat(cmdline, tmpbuf,
|
||
sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
str = env_get("trace_event");
|
||
if (str) {
|
||
snprintf(tmpbuf, 128, " trace_event=%s", str);
|
||
strncat(cmdline, tmpbuf,
|
||
sizeof(cmdline) - strlen(cmdline) - 1);
|
||
}
|
||
}
|
||
uint32_t *dram_para = NULL;
|
||
dram_para = (uint32_t *)uboot_spare_head.boot_data.dram_para;
|
||
|
||
sprintf(tmpbuf, " androidboot.dramfreq=%d",
|
||
(unsigned int)(dram_para[0]));
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
sprintf(tmpbuf, " androidboot.dramsize=%d",
|
||
(unsigned int)(uboot_spare_head.boot_data.dram_scan_size));
|
||
|
||
strncat(cmdline, tmpbuf, sizeof(cmdline) - strlen(cmdline) - 1);
|
||
|
||
env_set("bootargs", cmdline);
|
||
pr_msg("android.hardware = %s\n", CONFIG_SYS_CONFIG_NAME);
|
||
#ifdef CONFIG_SUNXI_VERIFY_BOOT_INFO_INSTALL
|
||
sunxi_keymaster_verify_boot_params_install();
|
||
#endif
|
||
|
||
}
|
||
|
||
void update_vendorbootconfig_and_bootgargs(void)
|
||
{
|
||
|
||
ulong bootconfig_startaddr = env_get_hex("bootconfig_addr", 0x00);
|
||
ulong bootconfig_size = env_get_hex("bootconfig_size", 0x00);
|
||
ulong ramdisk_addr = env_get_hex("ramdisk_start", 0x00);
|
||
ulong ramdisk_size = env_get_hex("ramdisk_size", 0x00);
|
||
ulong bootconfig_addr = ramdisk_addr + ramdisk_size - bootconfig_size;
|
||
int ret = 0;
|
||
|
||
if (bootconfig_startaddr) {
|
||
if (ramdisk_addr) {
|
||
ret = android_image_cmdline_to_vendorbootconfig(
|
||
&bootconfig_addr, &bootconfig_size);
|
||
|
||
if (ret) {
|
||
ramdisk_size = ramdisk_size + ret;
|
||
env_set_hex("ramdisk_size", ramdisk_size);
|
||
fdt_initrd(
|
||
working_fdt, (ulong)ramdisk_addr,
|
||
(ulong)(ramdisk_addr + ramdisk_size));
|
||
env_set_hex("ramdisk_sum",
|
||
sunxi_generate_checksum(
|
||
(void *)ramdisk_addr,
|
||
ramdisk_size, 8, STAMP_VALUE));
|
||
}
|
||
} else {
|
||
pr_err("get ramdisk addr Failed\n");
|
||
}
|
||
} else {
|
||
pr_msg("no bootconfig addr Failed\n");
|
||
}
|
||
}
|
||
int android_image_cmdline_to_vendorbootconfig(
|
||
unsigned long *bootconfig_startaddr, unsigned long *bootconfig_size)
|
||
{
|
||
char *str = env_get("bootargs");
|
||
struct key_value_set getkey[128];
|
||
ulong addlen = 0;
|
||
u32 count = 0;
|
||
char temp[128] = { 0 };
|
||
char cmdline[2048] = { 0 };
|
||
u32 i = 0, len;
|
||
|
||
if (*bootconfig_size == 0) {
|
||
pr_err("err: bootconfig_size=0\n");
|
||
return -1;
|
||
}
|
||
pr_msg("bootargs=%s\n", str);
|
||
memset(getkey, 0x00, ARRAY_SIZE(getkey) * sizeof(struct key_value_set));
|
||
count = sunxi_cmdline_parse(str, getkey, ARRAY_SIZE(getkey));
|
||
pr_msg("count:%d", count);
|
||
for (i = 0; i < count + 1; i++) {
|
||
memset(temp, 0x00, 128);
|
||
strncat(temp, getkey[i].key, getkey[i].key_len);
|
||
strncat(temp, "=", 1);
|
||
strncat(temp, getkey[i].value, getkey[i].value_len);
|
||
|
||
if (strncmp(temp, "androidboot.", strlen("androidboot."))) {
|
||
strcat(temp, " ");
|
||
strncat(cmdline, temp,
|
||
sizeof(cmdline) - strlen(cmdline) - 1);
|
||
|
||
} else {
|
||
len = getkey[i].key_len + getkey[i].value_len + 1;
|
||
temp[len] = 0x0a;
|
||
len = len + 1;
|
||
int ret = addBootConfigParameters(temp, len,
|
||
*bootconfig_startaddr,
|
||
*bootconfig_size);
|
||
if (ret <= 0) {
|
||
pr_err("Failed to apply boot config params:%s\n",
|
||
temp);
|
||
ret = 0;
|
||
} else {
|
||
*bootconfig_size += ret;
|
||
addlen += ret;
|
||
pr_msg("line:%d addr:0x%lx size:0x%lx=\n",
|
||
__LINE__, *bootconfig_startaddr,
|
||
*bootconfig_size);
|
||
}
|
||
}
|
||
}
|
||
env_set("bootargs", cmdline);
|
||
return addlen;
|
||
}
|