sdk-hwV1.3/lichee/brandy-2.0/u-boot-2018/board/sunxi/sunxi_bootargs.c

510 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (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;
}