| /* |
| * (C) Copyright 2013 Amlogic, Inc |
| * |
| * This file is used to run commands from misc partition |
| * More detail to check the command "run bcb_cmd" usage |
| * |
| * cheng.wang@amlogic.com, |
| * 2015-04-23 @ Shenzhen |
| * |
| */ |
| #include <common.h> |
| #include <command.h> |
| #include <environment.h> |
| #include <malloc.h> |
| #include <asm/byteorder.h> |
| #include <config.h> |
| #include <asm/arch/io.h> |
| #include <partition_table.h> |
| #include <libavb.h> |
| #include <version.h> |
| #include <amlogic/storage.h> |
| #include <asm/arch/secure_apb.h> |
| |
| #ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK |
| |
| #define AB_METADATA_MISC_PARTITION_OFFSET 2048 |
| |
| #define MISCBUF_SIZE 2080 |
| |
| #ifdef CONFIG_G_AB_SYSTEM |
| /* offset definition of slot x */ |
| #define SLOT_PRIORITY_OFFSET 0 |
| #define SLOT_TRIES_REMAINING_OFFSET 8 |
| #define SLOT_SUCCESSFUL_BOOT_OFFSET 16 |
| #define SLOT_STICKY_REG_VALID_OFFSET 24 |
| #define SLOT_MISC_CORRUPTION_OFFSET 25 |
| #define SLOT_NEXT_BOOT_OFFSET 24 |
| #define SLOT_CUR_BOOT_OFFSET 28 |
| #endif |
| |
| /* Magic for the A/B struct when serialized. */ |
| #define AVB_AB_MAGIC "\0AB0" |
| #define AVB_AB_MAGIC_LEN 4 |
| |
| /* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */ |
| #define AVB_AB_MAJOR_VERSION 1 |
| #define AVB_AB_MINOR_VERSION 0 |
| |
| /* Size of AvbABData struct. */ |
| #define AVB_AB_DATA_SIZE 32 |
| |
| /* Maximum values for slot data */ |
| #define AVB_AB_MAX_PRIORITY 15 |
| #define AVB_AB_MAX_TRIES_REMAINING 7 |
| |
| /* Struct used for recording per-slot metadata. |
| * |
| * When serialized, data is stored in network byte-order. |
| */ |
| typedef struct AvbABSlotData { |
| /* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY, |
| * both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY |
| * being the highest. The special value 0 is used to indicate the |
| * slot is unbootable. |
| */ |
| uint8_t priority; |
| |
| /* Number of times left attempting to boot this slot ranging from 0 |
| * to AVB_AB_MAX_TRIES_REMAINING. |
| */ |
| uint8_t tries_remaining; |
| |
| /* Non-zero if this slot has booted successfully, 0 otherwise. */ |
| uint8_t successful_boot; |
| |
| /* Reserved for future use. */ |
| uint8_t reserved[1]; |
| } AvbABSlotData; |
| |
| /* Struct used for recording A/B metadata. |
| * |
| * When serialized, data is stored in network byte-order. |
| */ |
| typedef struct AvbABData { |
| /* Magic number used for identification - see AVB_AB_MAGIC. */ |
| uint8_t magic[AVB_AB_MAGIC_LEN]; |
| |
| /* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */ |
| uint8_t version_major; |
| uint8_t version_minor; |
| |
| /* Padding to ensure |slots| field start eight bytes in. */ |
| uint8_t reserved1[2]; |
| |
| /* Per-slot metadata. */ |
| AvbABSlotData slots[2]; |
| |
| /* Reserved for future use. */ |
| uint8_t reserved2[12]; |
| |
| /* CRC32 of all 28 bytes preceding this field. */ |
| uint32_t crc32; |
| }AvbABData; |
| |
| /*static int clear_misc_partition(char *clearbuf, int size) |
| { |
| char *partition = "misc"; |
| |
| memset(clearbuf, 0, size); |
| if (store_write((unsigned char *)partition, |
| 0, size, (unsigned char *)clearbuf) < 0) { |
| printf("failed to clear %s.\n", partition); |
| return -1; |
| } |
| |
| return 0; |
| }*/ |
| |
| #ifdef CONFIG_G_AB_SYSTEM |
| void boot_info_update(AvbABData *info) |
| { |
| unsigned int sticky_reg0_val; |
| unsigned int sticky_reg1_val; |
| |
| sticky_reg0_val = readl(P_AO_RTI_STICKY_REG0); |
| sticky_reg1_val = readl(P_AO_RTI_STICKY_REG1); |
| |
| info->slots[0].priority = (sticky_reg0_val >> SLOT_PRIORITY_OFFSET) & 0xff; |
| info->slots[0].tries_remaining = (sticky_reg0_val >> SLOT_TRIES_REMAINING_OFFSET) & 0xff; |
| info->slots[0].successful_boot = (sticky_reg0_val >> SLOT_SUCCESSFUL_BOOT_OFFSET) & 0xff; |
| info->slots[1].priority = (sticky_reg1_val >> SLOT_PRIORITY_OFFSET) & 0xff; |
| info->slots[1].tries_remaining = (sticky_reg1_val >> SLOT_TRIES_REMAINING_OFFSET) & 0xff; |
| info->slots[1].successful_boot = (sticky_reg1_val >> SLOT_SUCCESSFUL_BOOT_OFFSET) & 0xff; |
| } |
| |
| void boot_info_save_to_reg(AvbABData *info, char *slot) |
| { |
| unsigned int sticky_reg0_val = 0; |
| unsigned int sticky_reg1_val = 0; |
| unsigned int cur_slot_index = 0; |
| unsigned int next_boot_slot_index = 0; |
| |
| sticky_reg0_val = ((info->slots[0].priority & 0xff) << SLOT_PRIORITY_OFFSET) | |
| ((info->slots[0].tries_remaining & 0xff) << SLOT_TRIES_REMAINING_OFFSET) | |
| ((info->slots[0].successful_boot & 0xff) << SLOT_SUCCESSFUL_BOOT_OFFSET); |
| sticky_reg1_val = ((info->slots[1].priority & 0xff) << SLOT_PRIORITY_OFFSET) | |
| ((info->slots[1].tries_remaining & 0xff) << SLOT_TRIES_REMAINING_OFFSET) | |
| ((info->slots[1].successful_boot & 0xff) << SLOT_SUCCESSFUL_BOOT_OFFSET); |
| |
| /* mark the sticky register is valid */ |
| sticky_reg0_val |= (1 << SLOT_STICKY_REG_VALID_OFFSET); |
| /* set slot_x to cur_slot_index and next_boot_slot_index */ |
| if (!strcmp(slot, "a")) { |
| cur_slot_index = 0; |
| next_boot_slot_index = 0; |
| } |
| else if (!strcmp(slot, "b")) { |
| cur_slot_index = 1; |
| next_boot_slot_index = 1; |
| } |
| sticky_reg1_val |= ((cur_slot_index << SLOT_CUR_BOOT_OFFSET) | |
| (next_boot_slot_index << SLOT_NEXT_BOOT_OFFSET)); |
| |
| writel(sticky_reg0_val, P_AO_RTI_STICKY_REG0); |
| writel(sticky_reg1_val, P_AO_RTI_STICKY_REG1); |
| } |
| #endif |
| |
| bool boot_info_validate(AvbABData* info) |
| { |
| if (memcmp(info->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) { |
| printf("Magic %s is incorrect.\n", info->magic); |
| return false; |
| } |
| if (info->version_major > AVB_AB_MAJOR_VERSION) { |
| printf("No support for given major version.\n"); |
| return false; |
| } |
| return true; |
| } |
| |
| void boot_info_reset(AvbABData* info) |
| { |
| memset(info, '\0', sizeof(AvbABData)); |
| memcpy(info->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN); |
| info->version_major = AVB_AB_MAJOR_VERSION; |
| info->version_minor = AVB_AB_MINOR_VERSION; |
| info->slots[0].priority = AVB_AB_MAX_PRIORITY; |
| info->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; |
| info->slots[0].successful_boot = 0; |
| info->slots[1].priority = AVB_AB_MAX_PRIORITY - 1; |
| info->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; |
| info->slots[1].successful_boot = 0; |
| } |
| |
| void dump_boot_info(AvbABData* info) |
| { |
| printf("info->magic = %s\n", info->magic); |
| printf("info->version_major = %d\n", info->version_major); |
| printf("info->version_minor = %d\n", info->version_minor); |
| printf("info->slots[0].priority = %d\n", info->slots[0].priority); |
| printf("info->slots[0].tries_remaining = %d\n", info->slots[0].tries_remaining); |
| printf("info->slots[0].successful_boot = %d\n", info->slots[0].successful_boot); |
| printf("info->slots[1].priority = %d\n", info->slots[1].priority); |
| printf("info->slots[1].tries_remaining = %d\n", info->slots[1].tries_remaining); |
| printf("info->slots[1].successful_boot = %d\n", info->slots[1].successful_boot); |
| |
| printf("info->crc32 = %d\n", info->crc32); |
| } |
| |
| #ifndef CONFIG_G_AB_SYSTEM |
| static bool slot_is_bootable(AvbABSlotData* slot) { |
| return slot->priority > 0 && |
| (slot->successful_boot || (slot->tries_remaining > 0)); |
| } |
| #endif |
| |
| int get_active_slot(AvbABData* info) { |
| if (info->slots[0].priority > info->slots[1].priority) |
| return 0; |
| else |
| return 1; |
| } |
| |
| #ifdef CONFIG_G_AB_SYSTEM |
| int boot_info_set_active_slot(AvbABData* info, int slot, int switch_flag) |
| { |
| unsigned int other_slot_number; |
| |
| /* Make requested slot top priority, unsuccessful, and with max tries. */ |
| info->slots[slot].priority = AVB_AB_MAX_PRIORITY; |
| info->slots[slot].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; |
| info->slots[slot].successful_boot = 0; |
| |
| /* Ensure other slot doesn't have as high a priority. */ |
| other_slot_number = 1 - slot; |
| if (switch_flag == 0) { |
| /* switch good slot to good slot, reduce the priority of the current slot */ |
| if (info->slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) { |
| info->slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1; |
| } |
| } |
| else { |
| /* switch bad slot to good slot, mark the current slot to bad */ |
| info->slots[other_slot_number].priority = 0; |
| info->slots[other_slot_number].tries_remaining = 0; |
| info->slots[other_slot_number].successful_boot = 0; |
| } |
| |
| #ifdef BL33_DEBUG_PRINT |
| dump_boot_info(info); |
| #endif |
| return 0; |
| } |
| |
| #else |
| int boot_info_set_active_slot(AvbABData* info, int slot) |
| { |
| unsigned int other_slot_number; |
| |
| /* Make requested slot top priority, unsuccessful, and with max tries. */ |
| info->slots[slot].priority = AVB_AB_MAX_PRIORITY; |
| info->slots[slot].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; |
| info->slots[slot].successful_boot = 0; |
| |
| /* Ensure other slot doesn't have as high a priority. */ |
| other_slot_number = 1 - slot; |
| if (info->slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) { |
| info->slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1; |
| } |
| |
| dump_boot_info(info); |
| |
| return 0; |
| } |
| #endif |
| |
| int boot_info_open_partition(char *miscbuf) |
| { |
| char *partition = "misc"; |
| //int i; |
| printf("Start read %s partition datas!\n", partition); |
| if (store_read((unsigned char *)partition, |
| 0, MISCBUF_SIZE, (unsigned char *)miscbuf) < 0) { |
| printf("failed to store read %s.\n", partition); |
| return -1; |
| } |
| |
| /*for (i = AB_METADATA_MISC_PARTITION_OFFSET;i < (AB_METADATA_MISC_PARTITION_OFFSET+AVB_AB_DATA_SIZE);i++) |
| printf("buf: %c \n", miscbuf[i]);*/ |
| return 0; |
| } |
| |
| bool boot_info_load(AvbABData *out_info, char *miscbuf) |
| { |
| memcpy(out_info, miscbuf+AB_METADATA_MISC_PARTITION_OFFSET, AVB_AB_DATA_SIZE); |
| dump_boot_info(out_info); |
| return true; |
| } |
| |
| bool boot_info_save(AvbABData *info, char *miscbuf) |
| { |
| char *partition = "misc"; |
| printf("save boot-info \n"); |
| #ifdef CONFIG_G_AB_SYSTEM |
| info->crc32 = avb_crc32((const uint8_t*)info, sizeof(AvbABData) - sizeof(uint32_t)); |
| memcpy(miscbuf, info, AVB_AB_DATA_SIZE); |
| #else |
| info->crc32 = avb_htobe32( |
| avb_crc32((const uint8_t*)info, sizeof(AvbABData) - sizeof(uint32_t))); |
| |
| memcpy(miscbuf+AB_METADATA_MISC_PARTITION_OFFSET, info, AVB_AB_DATA_SIZE); |
| #endif |
| #ifdef BL33_DEBUG_PRINT |
| dump_boot_info(info); |
| #endif |
| store_write((unsigned char *)partition, 0, MISCBUF_SIZE, (unsigned char *)miscbuf); |
| return true; |
| } |
| |
| static int do_GetValidSlot( |
| cmd_tbl_t * cmdtp, |
| int flag, |
| int argc, |
| char * const argv[]) |
| { |
| #ifdef CONFIG_G_AB_SYSTEM |
| unsigned int cur_slot_index; |
| unsigned int sticky_reg0_val = 0; |
| unsigned int sticky_reg1_val = 0; |
| unsigned int misc_corruption_flag = 0; |
| |
| sticky_reg1_val = readl(P_AO_RTI_STICKY_REG1); |
| sticky_reg0_val = readl(P_AO_RTI_STICKY_REG0); |
| cur_slot_index = (sticky_reg1_val >> SLOT_CUR_BOOT_OFFSET) & 0xf; |
| misc_corruption_flag = (sticky_reg0_val >> SLOT_MISC_CORRUPTION_OFFSET) & 0x1; |
| |
| pr_info("The index of active slot is:0x%x\n", cur_slot_index); |
| if (cur_slot_index == 0) { |
| env_set("active_slot","_a"); |
| env_set("boot_part","boot_a"); |
| env_set("slot-suffixes","a"); |
| } |
| else if (cur_slot_index == 1) { |
| env_set("active_slot","_b"); |
| env_set("boot_part","boot_b"); |
| env_set("slot-suffixes","b"); |
| } |
| else { |
| printf("Invalid slot num\n"); |
| return -1; |
| } |
| has_boot_slot = 1; |
| has_system_slot = 1; |
| |
| /* the misc image is damaged, it's should boot from slot a */ |
| if ((misc_corruption_flag == 1) && (cur_slot_index == 0)) { |
| /* reconstruct a default misc image and write to misc partition */ |
| char miscbuf[MISCBUF_SIZE] = {0}; |
| AvbABData info; |
| pr_info("reconstruct a default misc image\n"); |
| boot_info_reset(&info); |
| boot_info_save_to_reg(&info, "a"); |
| boot_info_save(&info, miscbuf); |
| } |
| |
| #else |
| char miscbuf[MISCBUF_SIZE] = {0}; |
| AvbABData info; |
| int slot; |
| bool bootable_a, bootable_b; |
| |
| if (argc != 1) { |
| return cmd_usage(cmdtp); |
| } |
| |
| boot_info_open_partition(miscbuf); |
| boot_info_load(&info, miscbuf); |
| |
| if (!boot_info_validate(&info)) { |
| printf("boot-info is invalid. Resetting.\n"); |
| boot_info_reset(&info); |
| boot_info_save(&info, miscbuf); |
| } |
| |
| slot = get_active_slot(&info); |
| printf("active slot = %d\n", slot); |
| |
| bootable_a = slot_is_bootable(&(info.slots[0])); |
| bootable_b = slot_is_bootable(&(info.slots[1])); |
| |
| if ((slot == 0) && (bootable_a)) { |
| if (has_boot_slot == 1) { |
| env_set("active_slot","_a"); |
| env_set("boot_part","boot_a"); |
| env_set("slot-suffixes","0"); |
| } |
| else { |
| env_set("active_slot","normal"); |
| env_set("boot_part","boot"); |
| } |
| return 0; |
| } |
| |
| if ((slot == 1) && (bootable_b)) { |
| if (has_boot_slot == 1) { |
| env_set("active_slot","_b"); |
| env_set("boot_part","boot_b"); |
| env_set("slot-suffixes","1"); |
| } |
| else { |
| env_set("active_slot","normal"); |
| env_set("boot_part","boot"); |
| } |
| return 0; |
| } |
| #endif |
| |
| return 0; |
| } |
| |
| static int do_SetActiveSlot( |
| cmd_tbl_t * cmdtp, |
| int flag, |
| int argc, |
| char * const argv[]) |
| { |
| char miscbuf[MISCBUF_SIZE] = {0}; |
| AvbABData info; |
| |
| #ifdef CONFIG_G_AB_SYSTEM |
| if (argc != 3) { |
| #else |
| if (argc != 2) { |
| #endif |
| return cmd_usage(cmdtp); |
| } |
| |
| if (has_boot_slot == 0) { |
| printf("device is not ab mode\n"); |
| return -1; |
| } |
| |
| #ifdef CONFIG_G_AB_SYSTEM |
| unsigned int switch_flag; |
| /* get default data from sticky register */ |
| boot_info_reset(&info); |
| boot_info_update(&info); |
| switch_flag = (unsigned int)simple_strtoul(argv[2], NULL, 16); |
| if ((switch_flag != 0) && (switch_flag != 1)) { |
| printf("Invalid flag for switch slot\n"); |
| return -1; |
| } |
| #else |
| boot_info_open_partition(miscbuf); |
| boot_info_load(&info, miscbuf); |
| |
| if (!boot_info_validate(&info)) { |
| printf("boot-info is invalid. Resetting.\n"); |
| boot_info_reset(&info); |
| boot_info_save(&info, miscbuf); |
| } |
| #endif |
| |
| if (strcmp(argv[1], "a") == 0) { |
| env_set("active_slot","_a"); |
| env_set("boot_part","boot_a"); |
| printf("set active slot a \n"); |
| #ifdef CONFIG_G_AB_SYSTEM |
| env_set("slot-suffixes","a"); |
| boot_info_set_active_slot(&info, 0, switch_flag); |
| #else |
| env_set("slot-suffixes","0"); |
| boot_info_set_active_slot(&info, 0); |
| #endif |
| } else if (strcmp(argv[1], "b") == 0) { |
| env_set("active_slot","_b"); |
| env_set("boot_part","boot_b"); |
| printf("set active slot b \n"); |
| #ifdef CONFIG_G_AB_SYSTEM |
| env_set("slot-suffixes","b"); |
| boot_info_set_active_slot(&info, 1, switch_flag); |
| #else |
| env_set("slot-suffixes","1"); |
| boot_info_set_active_slot(&info, 1); |
| #endif |
| } else { |
| printf("error input slot\n"); |
| return -1; |
| } |
| |
| #ifdef CONFIG_G_AB_SYSTEM |
| /* save new ab data to sticky register */ |
| boot_info_save_to_reg(&info, argv[1]); |
| #endif |
| boot_info_save(&info, miscbuf); |
| |
| return 0; |
| } |
| |
| int do_GetSystemMode (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| char* system; |
| #ifdef CONFIG_SYSTEM_AS_ROOT |
| system = CONFIG_SYSTEM_AS_ROOT; |
| strcpy(system, CONFIG_SYSTEM_AS_ROOT); |
| printf("CONFIG_SYSTEM_AS_ROOT: %s \n", CONFIG_SYSTEM_AS_ROOT); |
| if (strcmp(system, "systemroot") == 0) { |
| env_set("system_mode","1"); |
| } |
| else { |
| env_set("system_mode","0"); |
| } |
| #else |
| env_set("system_mode","0"); |
| #endif |
| |
| return 0; |
| } |
| |
| int do_GetAvbMode (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| #ifdef CONFIG_AVB2 |
| char* avbmode; |
| avbmode = CONFIG_AVB2; |
| strcpy(avbmode, CONFIG_AVB2); |
| printf("CONFIG_AVB2: %s \n", CONFIG_AVB2); |
| if (strcmp(avbmode, "avb2") == 0) { |
| env_set("avb2","1"); |
| } |
| else { |
| env_set("avb2","0"); |
| } |
| #else |
| env_set("avb2","0"); |
| #endif |
| |
| return 0; |
| } |
| |
| #ifdef CONFIG_G_AB_SYSTEM |
| /* write sticky register to misc partitioin */ |
| int do_SyncAvbData(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| char miscbuf[MISCBUF_SIZE] = {0}; |
| AvbABData info; |
| |
| /* init ab data */ |
| boot_info_reset(&info); |
| /* copy ab data from sticky register to info struct */ |
| boot_info_update(&info); |
| /* write ab data to misc partition */ |
| boot_info_save(&info, miscbuf); |
| |
| return 0; |
| } |
| |
| U_BOOT_CMD( |
| sync_ab_data, 1,0, do_SyncAvbData, |
| "sync_ab_data", |
| "\nThis command will write the sticky register to misc partitioin\n" |
| "So you can execute command: sync_ab_data" |
| ); |
| |
| int do_GetSlotState(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| unsigned int sticky_reg_val = 0; |
| unsigned int result = 0; |
| char cur_retry_count_str[8] = {0}; |
| |
| if (argc != 3) { |
| return cmd_usage(cmdtp); |
| } |
| |
| if (!strcmp(argv[1], "a")) { |
| sticky_reg_val = readl(P_AO_RTI_STICKY_REG0); |
| } |
| |
| else if (!strcmp(argv[1], "b")) { |
| sticky_reg_val = readl(P_AO_RTI_STICKY_REG1); |
| } |
| else { |
| return cmd_usage(cmdtp); |
| } |
| |
| if (!strcmp(argv[2], "successful")) { |
| result = (sticky_reg_val >> SLOT_SUCCESSFUL_BOOT_OFFSET) & 0xff; |
| } |
| else if (!strcmp(argv[2], "unbootable")) { |
| result = (sticky_reg_val >> SLOT_PRIORITY_OFFSET) & 0xff; |
| } |
| else if (!strcmp(argv[2], "retry-count")) { |
| result = (sticky_reg_val >> SLOT_TRIES_REMAINING_OFFSET) & 0xff; |
| /* For command: fastboot getvar slot-retry-count:slot_x */ |
| snprintf(cur_retry_count_str, sizeof(cur_retry_count_str), "%d", result); |
| env_set("cur_retry_count", cur_retry_count_str); |
| } |
| else { |
| return cmd_usage(cmdtp); |
| } |
| |
| printf("slot %s: %s = %d\n", argv[1], argv[2], result); |
| return result; |
| } |
| |
| U_BOOT_CMD( |
| get_slot_state, 3,0, do_GetSlotState, |
| "get_slot_state", |
| "\nThis command will get the slot status\n" |
| "So you can execute command: get_slot_state [a|b] [successful|unbootable|retry-count]" |
| ); |
| #endif |
| |
| #endif /* CONFIG_BOOTLOADER_CONTROL_BLOCK */ |
| |
| U_BOOT_CMD( |
| get_valid_slot, 2, 0, do_GetValidSlot, |
| "get_valid_slot", |
| "\nThis command will choose valid slot to boot up which saved in misc\n" |
| "partition by mark to decide whether execute command!\n" |
| "So you can execute command: get_valid_slot" |
| ); |
| |
| #ifdef CONFIG_G_AB_SYSTEM |
| U_BOOT_CMD( |
| set_active_slot, 3, 1, do_SetActiveSlot, |
| "set_active_slot", |
| "\nThis command will set active slot\n" |
| "set_active_slot slot_name switch_flag\n" |
| " slot_name: a|b\n" |
| " switch_flag: 0 - switch good slot to good slot\n" |
| " 1 - switch bad slot to good slot" |
| ); |
| #else |
| U_BOOT_CMD( |
| set_active_slot, 2, 1, do_SetActiveSlot, |
| "set_active_slot", |
| "\nThis command will set active slot\n" |
| "So you can execute command: set_active_slot a" |
| ); |
| #endif |
| |
| U_BOOT_CMD( |
| get_system_as_root_mode, 1, 0, do_GetSystemMode, |
| "get_system_as_root_mode", |
| "\nThis command will get system_as_root_mode\n" |
| "So you can execute command: get_system_as_root_mode" |
| ); |
| |
| U_BOOT_CMD( |
| get_avb_mode, 1, 0, do_GetAvbMode, |
| "get_avb_mode", |
| "\nThis command will get avb mode\n" |
| "So you can execute command: get_avb_mode" |
| ); |
| |