/* SPDX-License-Identifier: GPL-2.0+ * (C) Copyright 2018-2020 * Allwinner Technology Co., Ltd. * wangwei * * Some init for sunxi platform. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include DECLARE_GLOBAL_DATA_PTR; /*define ir or key mode value*/ #define EFEX_VALUE (0x81) #define SPRITE_RECOVERY_VALUE (0X82) #define BOOT_RECOVERY_VALUE (0x83) #define BOOT_FACTORY_VALUE (0x84) #define PARTITION_SETS_MAX_SIZE 1024 #define PARTITION_NAME_MAX_SIZE 16 #define ROOT_PART_NAME_MAX_SIZE (PARTITION_NAME_MAX_SIZE + 5) #define DEV_PART_NAME_MAX_SIZE (PARTITION_NAME_MAX_SIZE + sizeof("/dev/")) #ifdef CONFIG_DRAM_VER_1 int update_fdt_dram_para(void *dtb_base) { /*fix dram para*/ int nodeoffset = 0; uint32_t *dram_para = NULL; dram_para = (uint32_t *)uboot_spare_head.boot_data.dram_para; pr_msg("(weak)update dtb dram start\n"); nodeoffset = fdt_path_offset(dtb_base, "/dram"); if (nodeoffset < 0) { pr_err("## error: %s : %s\n", __func__, fdt_strerror(nodeoffset)); return -1; } fdt_setprop_u32(dtb_base, nodeoffset, "dram_clk", dram_para[0]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_type", dram_para[1]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_zq", dram_para[2]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_odt_en", dram_para[3]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_para1", dram_para[4]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_para2", dram_para[5]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_mr0", dram_para[6]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_mr1", dram_para[7]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_mr2", dram_para[8]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_mr3", dram_para[9]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr0", dram_para[10]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr1", dram_para[11]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr2", dram_para[12]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr3", dram_para[13]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr4", dram_para[14]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr5", dram_para[15]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr6", dram_para[16]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr7", dram_para[17]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr8", dram_para[18]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr9", dram_para[19]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr10", dram_para[20]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr11", dram_para[21]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr12", dram_para[22]); fdt_setprop_u32(dtb_base, nodeoffset, "dram_tpr13", dram_para[23]); gd->bd->bi_dram[0].size = (phys_size_t)uboot_spare_head.boot_data.dram_scan_size * 1024 * 1024; pr_msg("update dtb dram end\n"); return 0; } #else #error "platform not support" #endif static int fdt_enable_node(char *name, int onoff) { int nodeoffset = 0; int ret = 0; nodeoffset = fdt_path_offset(working_fdt, name); ret = fdt_set_node_status(working_fdt, nodeoffset, onoff ? FDT_STATUS_OKAY: FDT_STATUS_DISABLED, 0); if (ret < 0) { printf("disable nand error: %s\n", fdt_strerror(ret)); } return ret; } void sunxi_dump(void *addr, unsigned int size) { #if 1 print_buffer((ulong)addr, addr, 4, ALIGN(size, 16)/4, 4); #else int i, j; char *buf = (char *)addr; for (j = 0; j < size; j += 16) { for (i = 0; (i < 16 && i < size); i++) { printf("%02x ", buf[j + i] & 0xff); } printf("\n"); } printf("\n"); #endif return; } /* * name : sunxi_str_replace * fucntion: replace a word in string which separated by a space * note : sunxi_str_replace("abc def gh", "def", "replace") get "abc replace gh" */ static int sunxi_str_replace(char *dest_buf, char *goal, char *replace) { char tmp[128]; char tmp_str[16]; int goal_len, rep_len, dest_len; int i, j, k; if( (goal == NULL) || (dest_buf == NULL)) return -1; memset(tmp, 0, 128); strcpy(tmp, dest_buf); goal_len = strlen(goal); dest_len = strlen(dest_buf); if(replace != NULL) rep_len = strlen(replace); else rep_len = 0; j = 0; for(i=0;tmp[i];) { k = 0; while(((tmp[i] != ' ') && (tmp[i] != 0) )|| (tmp[i+1] == ' ')) { tmp_str[k++] = tmp[i]; i ++; if(i >= dest_len) break; } i ++; tmp_str[k] = 0; if(!strcmp(tmp_str, goal)) { if(rep_len) { strcpy(dest_buf + j, replace); if(tmp[j + goal_len]) { memcpy(dest_buf + j + rep_len, tmp + j + goal_len, dest_len - j - goal_len); dest_buf[dest_len - goal_len + rep_len] = 0; } } else { if(tmp[j + goal_len]) { memcpy(dest_buf + j, tmp + j + goal_len, dest_len - j - goal_len); dest_buf[dest_len - goal_len + rep_len] = 0; } } return 0; } j = i; } return 0; } static int write_recovery_msg_to_misc(char *recovery_msg) { u32 misc_offset = 0; char misc_args[2048]; static struct bootloader_message *misc_message; int ret; memset(misc_args, 0x0, 2048); misc_message = (struct bootloader_message *)misc_args; misc_offset = sunxi_partition_get_offset_byname("misc"); if (!misc_offset) { printf("no misc partition\n"); return 0; } ret = sunxi_flash_read(misc_offset, 2048 / 512, misc_args); if (!ret) { printf("error: read misc partition\n"); return 0; } if (!strcmp("ir-or-key-recovery", (const char *)recovery_msg)) { strcpy(misc_message->command, "boot-recovery"); } else if (!strcmp("ir-factory", (const char *)recovery_msg)) { strcpy(misc_message->command, "boot-recovery"); strcpy(misc_message->recovery, "recovery\n--wipe_data\n--locale=zh_CN\n"); } else if (!strcmp("ir-efex", (const char *)recovery_msg)) { strcpy(misc_message->command, "efex"); } else if (!strcmp("sysrecovery", (const char *)recovery_msg)) { strcpy(misc_message->command, "sysrecovery"); /* strcpy(misc_message->recovery, "sysrecovery"); */ } else if (!strcmp("erase_misc", (const char *)recovery_msg)) { memset(misc_args, 0x0, 2048); } sunxi_flash_write(misc_offset, 2048 / 512, misc_args); return 0; } #ifdef CONFIG_RECOVERY_KEY #define RECOVERY_KEY_EFEX_MODE (0x0) #define RECOVERY_KEY_ONEKEY_SPRITE_RECOVERY_MODE (0x1) #define RECOVERY_KEY_RECOVERY_MODE (0x2) #define RECOVERY_KEY_FACTORY_MODE (0x3) #define RECOVERY_KEY_EFEX_VALUE (0x81) #define RECOVERY_KEY_SPRITE_RECOVERY_VALUE (0X82) #define RECOVERY_KEY_BOOT_RECOVERY_VALUE (0x83) #define RECOVERY_KEY_BOOT_FACTORY_VALUE (0x84) #define KEY_PRESS_MODE_DISABLE (0X0) #define KEY_PRESS_MODE_ENABLE (0x1) #define KEY_BOOT_RECOVERY "/soc/key_boot_recovery" #ifdef RECOVERY_KEY_DEBUG #define key_info(fmt...) tick_printf(fmt) #else #define key_info(fmt...) #endif int check_recovery_key(void) { user_gpio_set_t gpio_recovery; __u32 gpio_hd; int ret; int gpio_value = 0; int used = 0; int mode = 0; int press_mode = 0; int press_time = 0; if (get_boot_work_mode() == WORK_MODE_BOOT) { /*check physical gpio pin*/ ret = script_parser_fetch(KEY_BOOT_RECOVERY, "recovery_key_used", (int *)&used, sizeof(int) / 4); if (ret || !used) { key_info("[key recovery] no use\n"); return 0; } ret = fdt_get_one_gpio(KEY_BOOT_RECOVERY, "recovery_key", &gpio_recovery); if (ret) { key_info("[key recovery] can't find recovery_key config.\n"); return 0; } gpio_recovery.mul_sel = 0; /*forced to input*/ gpio_hd = sunxi_gpio_request(&gpio_recovery, 1); if (!gpio_hd) { pr_error("[key recovery] gpio request fail!\n"); return 0; /*gpio request fail,just return.*/ } int time; gpio_value = 0; for (time = 0; time < 5; time++) { gpio_value += gpio_read_one_pin_value(gpio_hd, 0); mdelay(1); } if (gpio_value) { key_info("[key recovery] no key press.\n"); return 0; /*no recovery key was pressed, just return.*/ } key_info("[key recovery] find the key\n"); script_parser_fetch(KEY_BOOT_RECOVERY, "press_mode_enable", (int *)&press_mode, sizeof(int) / 4); if (press_mode == KEY_PRESS_MODE_DISABLE) { script_parser_fetch(KEY_BOOT_RECOVERY, "key_work_mode", (int *)&mode, sizeof(int) / 4); key_info("[key recovery] do not use prese mode, \ key_work_mode = %d\n", mode); } else if (press_mode == KEY_PRESS_MODE_ENABLE) { script_parser_fetch(KEY_BOOT_RECOVERY, "key_press_time", (int *)&press_time, sizeof(int) / 4); key_info("[key recovery] use prese mode, \ and key_press_time = %d ms\n", press_time); gpio_value = 0; for (time = press_time; time > 0; time -= 100) { mdelay(100); /*detect key value per 100ms*/ gpio_value += gpio_read_one_pin_value(gpio_hd, 0); /*key was loosed during press time,will not detect key value any more*/ if (gpio_value) break; } /*key was lossed during press time, so use short_press_mode*/ if (gpio_value) { script_parser_fetch(KEY_BOOT_RECOVERY, "short_press_mode", (int *)&mode, sizeof(int) / 4); key_info("[key recovery] key short press, short_press_mode = %d\n", mode); } else { /*key was always pressed in key_press_time, so use long_press_mode*/ script_parser_fetch(KEY_BOOT_RECOVERY, "long_press_mode", (int *)&mode, sizeof(int) / 4); key_info("[key recovery] key long press, long_press_mode = %d\n", mode); } } switch (mode) { case RECOVERY_KEY_EFEX_MODE: gd->key_pressd_value = RECOVERY_KEY_EFEX_VALUE; break; case RECOVERY_KEY_ONEKEY_SPRITE_RECOVERY_MODE: gd->key_pressd_value = RECOVERY_KEY_SPRITE_RECOVERY_VALUE; break; case RECOVERY_KEY_RECOVERY_MODE: gd->key_pressd_value = RECOVERY_KEY_BOOT_RECOVERY_VALUE; break; case RECOVERY_KEY_FACTORY_MODE: gd->key_pressd_value = RECOVERY_KEY_BOOT_FACTORY_VALUE; break; default: gd->key_pressd_value = RECOVERY_KEY_BOOT_RECOVERY_VALUE; break; } } return 0; } #endif void sunxi_respond_ir_key_action(void) { int key_value; #ifdef CONFIG_IR_BOOT_RECOVERY int ir_time_out = get_timer_masked(); while (get_timer_masked() - ir_time_out < 200) { if (gd->ir_detect_status != IR_DETECT_NULL) break; } ir_disable(); #endif key_value = gd->key_pressd_value; /* //ir factory or key factory */ if (key_value == 0) { return; } else if (key_value == BOOT_FACTORY_VALUE) { printf("[boot factory] set misc : boot factory and wipe data\n"); write_recovery_msg_to_misc("ir-factory"); } else if (key_value == EFEX_VALUE) { /* //ir efex or key efex */ printf("[boot efex] set misc : boot efex\n"); write_recovery_msg_to_misc("ir-efex"); } else if (key_value == SPRITE_RECOVERY_VALUE) { /* //ir sprite recovery */ printf("[ir sysrecovery] set misc : boot recovery and sysrecovery \n"); write_recovery_msg_to_misc("sysrecovery"); } else if (key_value == BOOT_RECOVERY_VALUE) { /* //ir recovery or key recovery */ printf("[boot recovery] set misc : boot recovery\n"); write_recovery_msg_to_misc("ir-or-key-recovery"); } } static int sunxi_get_bootcmd_from_rtc(void) { u8 bootmode_flag = 0; bootmode_flag = rtc_get_bootmode_flag(); /*clear rtc*/ rtc_set_bootmode_flag(0); switch (bootmode_flag) { case SUNXI_EFEX_CMD_FLAG: return SUNXI_EFEX_CMD_FLAG; case SUNXI_BOOT_RECOVERY_FLAG: return SUNXI_BOOT_RECOVERY_FLAG; case SUNXI_FASTBOOT_FLAG: return SUNXI_FASTBOOT_FLAG; case SUNXI_UBOOT_FLAG: return SUNXI_UBOOT_FLAG; default: return 0; break; } } static int sunxi_get_bootcmd_from_adckey(void) { typedef struct adc_key_info { char *key_type; u32 key_flag; } _adc_key_info; int key_high, key_low; int keyvalue, i; char key_mode[16] = {0}; _adc_key_info key_info_table[] = { {"recovery", SUNXI_BOOT_RECOVERY_FLAG}, {"fastboot", SUNXI_FASTBOOT_FLAG}, {"fel", SUNXI_EFEX_CMD_FLAG}, }; keyvalue = uboot_spare_head.boot_data.key_input; pr_msg("key %d\n", keyvalue); if (keyvalue) { for (i = 0; i < sizeof(key_info_table)/sizeof(key_info_table[0]); i++) { sprintf(key_mode, "/soc/%s_key", key_info_table[i].key_type); script_parser_fetch(key_mode, "key_max", &key_high, 0); script_parser_fetch(key_mode, "key_min", &key_low, 0); if (key_high || key_low) { pr_notice("%s key high %d, low %d\n", key_info_table[i].key_type, key_high, key_low); if ((keyvalue >= key_low) && (keyvalue <= key_high)) { pr_notice("key found, android %s\n", key_info_table[i].key_type); return key_info_table[i].key_flag; } } } } return 0; } static int sunxi_get_bootcmd_from_misc(void) { u32 misc_offset = 0; char misc_args[2048]; char misc_fill[2048]; struct bootloader_message *misc_message; int misc_mode; misc_message = (struct bootloader_message *)misc_args; memset(misc_args, 0x0, 2048); memset(misc_fill, 0xff, 2048); misc_offset = sunxi_partition_get_offset_byname("misc"); if (!misc_offset) { pr_msg("no misc partition is found\n"); return 0; } else { pr_msg("misc partition found\n"); sunxi_flash_read(misc_offset, 2048 / 512, misc_args); } if (strstr((const char *)misc_message->command, "efex")) { misc_mode = SUNXI_EFEX_CMD_FLAG; /*"sysrecovery" must judge before "recovery" !!!*/ } else if (strstr((const char *)misc_message->command, "sysrecovery")) { misc_mode = SUNXI_SYS_RECOVERY_FLAG; } else if (strstr((const char *)misc_message->command, "recovery")) { misc_mode = SUNXI_BOOT_RECOVERY_FLAG; } else if (strstr((const char *)misc_message->command, "bootloader")) { misc_mode = SUNXI_FASTBOOT_FLAG; } else if (strstr((const char *)misc_message->command, "uboot")) { misc_mode = SUNXI_UBOOT_FLAG; } else { misc_mode = 0; } if ((misc_mode) || *(misc_message->recovery)) print_buffer((ulong)misc_args, misc_args, 4, 0x50, 4); if (strstr((const char *)misc_message->recovery, "update_package") == NULL) { memset(misc_message->command, 0x0, sizeof(misc_message->command)); sunxi_flash_write(misc_offset, 2048 / 512, misc_args); } return misc_mode; } int sunxi_set_bootcmd(char *bootcmd) { int i, bootmode[4] = {0}; bootmode[1] = sunxi_get_bootcmd_from_adckey(); bootmode[2] = sunxi_get_bootcmd_from_rtc(); bootmode[3] = sunxi_get_bootcmd_from_misc(); for (i = 1; i < sizeof(bootmode)/sizeof(bootmode[0]); i++) { if (bootmode[i]) { bootmode[0] = bootmode[i]; tick_printf("bootmode[%d]:0x%x\n", i, bootmode[i]); break; } } switch (bootmode[0]) { case SUNXI_EFEX_CMD_FLAG: sunxi_board_run_fel(); break; case SUNXI_SYS_RECOVERY_FLAG: set_boot_work_mode(WORK_MODE_SPRITE_RECOVERY); env_set("sysrecovery", "sprite_test"); strncpy(bootcmd, "run sysrecovery", sizeof("run sysrecovery")); case SUNXI_BOOT_RECOVERY_FLAG: sunxi_str_replace(bootcmd, "boot_normal", "boot_recovery"); break; case SUNXI_FASTBOOT_FLAG: sunxi_str_replace(bootcmd, "boot_normal", "boot_fastboot"); break; case SUNXI_UBOOT_FLAG: sunxi_set_uboot_shell(1); break; default: break; } return 0; } int sunxi_update_bootcmd(void) { char boot_commond[128]; int storage_type = get_boot_storage_type(); memset(boot_commond, 0x0, 128); strncpy(boot_commond, env_get("bootcmd"), sizeof(boot_commond)-1); debug("base bootcmd=%s\n", boot_commond); if ((storage_type == STORAGE_SD) || (storage_type == STORAGE_EMMC) || storage_type == STORAGE_EMMC3) { sunxi_str_replace(boot_commond, "setargs_nand", "setargs_mmc"); debug("bootcmd set setargs_mmc\n"); } else if (storage_type == STORAGE_NOR) { sunxi_str_replace(boot_commond, "setargs_nand", "setargs_nor"); } else if (storage_type == STORAGE_NAND) { debug("bootcmd set setargs_nand\n"); } sunxi_set_bootcmd(boot_commond); env_set("bootcmd", boot_commond); debug("to be run cmd=%s\n", boot_commond); tick_printf("update bootcmd\n"); return 0; } int sunxi_update_fdt_para_for_kernel(void) { uint storage_type = 0; int ret = 0; #ifdef CONFIG_SUNXI_SDMMC struct mmc *mmc = NULL; int dev_num = 0; #endif storage_type = get_boot_storage_type_ext(); #ifdef CONFIG_SUNXI_SDMMC /* update sdhc dbt para */ if (storage_type == STORAGE_EMMC || storage_type == STORAGE_EMMC3) { dev_num = (storage_type == STORAGE_EMMC) ? 2 : 3; mmc = find_mmc_device(dev_num); if (mmc == NULL) { printf("can't find valid mmc %d\n", dev_num); return -1; } if (mmc->cfg->sample_mode == AUTO_SAMPLE_MODE) { mmc_update_config_for_sdly(mmc); } } #endif /* creat udc dbt para when in charger_mode */ if (gd->chargemode == 1) { fdt_find_and_setprop(working_fdt, "/soc/udc-controller", "charger_mode", NULL, 0, 1); } /* fix nand&sdmmc */ switch (storage_type) { case STORAGE_NAND: #ifdef CONFIG_SUNXI_UBIFS if (nand_use_ubi() == 0) #endif { fdt_enable_node("nand0", 1); fdt_enable_node("spi0", 0); } break; case STORAGE_SPI_NAND: #ifdef CONFIG_SUNXI_UBIFS if (nand_use_ubi() == 0) #endif { fdt_enable_node("spinand", 1); fdt_enable_node("spi0", 0); } break; case STORAGE_EMMC: fdt_enable_node("mmc2", 1); break; case STORAGE_EMMC3: fdt_enable_node("mmc3", 1); break; case STORAGE_SD: fdt_enable_node("mmc0", 1); { uint32_t dragonboard_test = 0; script_parser_fetch("/soc/target", "dragonboard_test", (int *)&dragonboard_test, 0); if (dragonboard_test == 1) { fdt_enable_node("mmc2", 1); #ifdef CONFIG_SUNXI_SDMMC mmc_update_config_for_dragonboard(2); #ifdef CONFIG_MMC3_SUPPORT mmc_update_config_for_dragonboard(3); #endif #endif } } break; case STORAGE_NOR: fdt_enable_node("/soc/spi", 1); break; default: break; } #if defined(CONFIG_SUNXI_DRM_SUPPORT) ulong drm_base = 0, drm_size = 0; if (gd->securemode == SUNXI_SECURE_MODE_WITH_SECUREOS) { if (!smc_tee_probe_drm_configure(&drm_base, &drm_size)) { pr_msg("drm_base=0x%lx\n", drm_base); pr_msg("drm_size=0x%lx\n", drm_size); ret = fdt_add_mem_rsv(working_fdt, drm_base, drm_size); if (ret) pr_err("##add mem rsv error: %s : %s\n", __func__, fdt_strerror(ret)); } } #endif /* fix dram para */ ret = update_fdt_dram_para(working_fdt); if (ret < 0) { return -1; } tick_printf("update dts\n"); return 0; } int sunxi_update_partinfo(void) { int index, ret; char partition_sets[PARTITION_SETS_MAX_SIZE]; char part_name[PARTITION_NAME_MAX_SIZE]; char root_part_name[ROOT_PART_NAME_MAX_SIZE]; char *root_partition; char blkoops_part_name[DEV_PART_NAME_MAX_SIZE]; char *blkoops_partition; char *partition_index = partition_sets; int offset = 0; int temp_offset = 0; int storage_type = get_boot_storage_type(); struct blk_desc *desc; disk_partition_t info = { 0 }; memset(root_part_name, 0, ROOT_PART_NAME_MAX_SIZE); root_partition = env_get("root_partition"); if (root_partition) printf("root_partition is %s\n", root_partition); memset(blkoops_part_name, 0, DEV_PART_NAME_MAX_SIZE); blkoops_partition = env_get("blkoops_partition"); if (blkoops_partition) printf("blkoops_partition is %s\n", blkoops_partition); memset(partition_sets, 0, PARTITION_SETS_MAX_SIZE); desc = blk_get_devnum_by_typename("sunxi_flash", 0); if (desc == NULL) return -ENODEV; for (index = 1;; index++) { ret = part_get_info(desc, index, &info); debug("%s: try part %d, ret = %d\n", __func__, index, ret); if (ret < 0) break; memset(part_name, 0, PARTITION_NAME_MAX_SIZE); if (storage_type == STORAGE_NAND) { sprintf(part_name, "nand0p%d", index); } else if (storage_type == STORAGE_NOR) { sprintf(part_name, "mtdblock%d", index); } else { sprintf(part_name, "mmcblk0p%d", index); } temp_offset = strlen((char*)info.name) + strlen(part_name) + 2; if (temp_offset >= PARTITION_SETS_MAX_SIZE) { printf("partition_sets is too long, please reduces " "partition name\n"); break; } sprintf(partition_index, "%s@%s:", info.name, part_name); if (root_partition && strncmp(root_partition, (char *)info.name, sizeof(info.name)) == 0) sprintf(root_part_name, "/dev/%s", part_name); if (blkoops_partition && strncmp(blkoops_partition, (char *)info.name, sizeof(info.name)) == 0) sprintf(blkoops_part_name, "/dev/%s", part_name); offset += temp_offset; partition_index = partition_sets + offset; } partition_sets[offset - 1] = '\0'; partition_sets[PARTITION_SETS_MAX_SIZE - 1] = '\0'; env_set("partitions", partition_sets); if (*root_part_name != 0) { printf("set root to %s\n", root_part_name); if (storage_type == STORAGE_NAND) env_set("nand_root", root_part_name); else if (storage_type == STORAGE_NOR) env_set("nor_root", root_part_name); else env_set("mmc_root", root_part_name); } if (*blkoops_part_name != 0) { printf("set blkoops_blkdev to %s\n", blkoops_part_name); env_set("blkoops_blkdev", blkoops_part_name); } tick_printf("update part info\n"); return 0; } int sunxi_force_rotpk(void) { return ((uboot_spare_head.boot_data.func_mask & UBOOT_FUNC_MASK_BIT_FORCE_ROTPK) == UBOOT_FUNC_MASK_BIT_FORCE_ROTPK); } int sunxi_update_rotpk_info(void) { char rotpk_status[16] = ""; int ret; ret = sunxi_efuse_get_rotpk_status(); if (ret >= 0) { sprintf(rotpk_status, "%d", ret); env_set("rotpk_status", rotpk_status); } if (sunxi_force_rotpk()) { if (ret < 1) { pr_err("rotpk required but not burned\n"); return -1; } } return 0; }