Files

328 lines
7.2 KiB
C

// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <common.h>
#include <command.h>
#include <malloc.h>
#include <asm/byteorder.h>
#include <config.h>
#include <asm/amlogic/arch/reboot.h>
#include <asm/amlogic/arch/io.h>
#include <amlogic/storage.h>
#include <stdlib.h>
#include <amlogic/store_wrapper.h>
#include <linux/libfdt_env.h>
#include <amlogic/libavb/libavb.h>
#define MISCBUF_SIZE 1088
#define ERRCODE_OFFSET 896
struct avb_list {
char part_name[32];
int errno;
};
struct error_list {
char err_string[32];
char err_code[8];
};
struct bootloader_message {
char command[32];
char status[32];
char recovery[768];
// The 'recovery' field used to be 1024 bytes. It has only ever
// been used to store the recovery command line, so 768 bytes
// should be plenty. We carve off the last 256 bytes to store the
// stage string (for multistage packages) and possible future
// expansion.
char stage[32];
char slot_suffix[32];
char reserved[192];
};
#define AVB_MAX_PART (8)
struct avb_list avb_partition[AVB_MAX_PART] = {
{"vbmeta", 1},
{"oem", 2},
{"boot", 3},
{"vbmeta_system", 4},
{"dtb", 5},
{"dtbo", 6},
{"init_boot", 7},
{"vendor_boot", 8}
};
#define MODE_MAX_PART (8)
struct error_list error_mode[MODE_MAX_PART] = {
{"apexd-failed", "E2001"},
{"boringssl-self-check-failed", "E2002"},
{"bpfloader-failed", "E2003"},
{"vold-failed", "E2004"},
{"dm-verity device corrupted", "E2005"},
{"Checkpoint commit failed", "E2006"},
{"kernel_panic", "E2007"},
{"rescueparty", "E2008"}
};
#define MISC_MAX_PART (5)
struct error_list error_misc[MISC_MAX_PART] = {
{"fs_mgr_mount_all", "E3001"},
{"enablefilecrypto", "E3002"},
{"init_user0_failed", "E3003"},
{"set_policy_failed", "E3004"},
{"RescueParty", "E3005"}
};
#define AVB_MAX_ERROR (17)
struct error_list error_avb[AVB_MAX_ERROR] = {
{"avb2 verify failed", "E1---"},
{"OOM failed", "E11--"},
{"IO failed", "E12--"},
{"VERIFICATION failed", "E13--"},
{"ROLLBACK_INDEX failed", "E14--"},
{"PUBLIC_KEY_REJECTED failed", "E15--"},
{"INVALID_METADATA failed", "E16--"},
{"UNSUPPORTED_VERSION failed", "E17--"},
{"INVALID_ARGUMENT failed", "E18--"},
{"vbmeta verify failed", "E1--1"},
{"oem verify failed", "E1--2"},
{"boot verify failed", "E1--3"},
{"vbmeta_system verify failed", "E1--4"},
{"dtb verify failed", "E1--5"},
{"dtbo verify failed", "E1--6"},
{"init_boot verify failed", "E1--7"},
{"vendor_boot verify failed", "E1--8"}
};
char *remove_ab_suffix(char *str)
{
if (!str)
return NULL;
size_t len = strlen(str);
if (len >= 2) {
if (str[len - 2] == '_' && (str[len - 1] == 'a' || str[len - 1] == 'b'))
str[len - 2] = '\0';
}
return str;
}
int get_errno_by_name(char *part_name)
{
int i = 0;
for (i = 0; i < AVB_MAX_PART; i++) {
if (!strcmp(part_name, avb_partition[i].part_name))
return avb_partition[i].errno;
}
return 0;
}
char *get_errno_by_mode(char *mode)
{
int i = 0;
for (i = 0; i < MODE_MAX_PART; i++) {
if (strstr(mode, error_mode[i].err_string))
return error_mode[i].err_code;
if (!strcmp(mode, error_mode[i].err_string))
return error_mode[i].err_code;
}
return NULL;
}
char *get_errno_by_misc(char *mode)
{
int i = 0;
for (i = 0; i < MISC_MAX_PART; i++) {
if (strstr(mode, error_misc[i].err_string))
return error_misc[i].err_code;
if (!strcmp(mode, error_misc[i].err_string))
return error_misc[i].err_code;
}
return NULL;
}
int show_errcode(const char *err_str)
{
int i = 0;
int ret = 0;
int offset_x = 100;
int offset_y = 50;
int offset_n = 0;
static int show_init;
char buf[128] = {0};
bool unlocked;
unlocked = is_device_unlocked();
if (unlocked)
return 0;
if (show_init == 1)
return 0;
ret = run_command("imgread pic logo key_1 $loadaddr", 0);
if (ret) {
printf("bmp source not exist of logo.img, skip errcode show.\n");
show_init = 1;
return 0;
}
if (!err_str || strlen(err_str) == 0)
return -1;
int len = strlen(err_str);
for (i = 0; i < len; i++) {
sprintf(buf, "imgread pic logo key_%c $loadaddr", err_str[i]);
run_command(buf, 0);
offset_n = offset_x + 40 * i;
sprintf(buf, "bmp display $key_%c_offset %d %d", err_str[i], offset_n, offset_y);
run_command(buf, 0);
}
show_init = 1;
return 0;
}
static int do_errcode_avb2(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i = 0;
int errno = 0;
char strerr[8] = {0};
char partition_name[32] = {0};
if (argc != 3)
return cmd_usage(cmdtp);
printf("Command: ");
for (i = 0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
strlcpy(partition_name, argv[1], strlen(argv[1]));
remove_ab_suffix(partition_name);
printf("partition_name:%s\n", partition_name);
errno = get_errno_by_name(partition_name);
sprintf(strerr, "E1%s%02d", argv[2], errno);
printf("strerr=%s\n", strerr);
show_errcode(strerr);
return 0;
}
static int do_errcode_mode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i = 0;
if (argc != 2)
return cmd_usage(cmdtp);
printf("Command: ");
for (i = 0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
char *mode = get_errno_by_mode(argv[1]);
if (mode)
show_errcode(mode);
return 0;
}
static int do_errcode_misc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i = 0;
if (argc != 2)
return cmd_usage(cmdtp);
printf("Command: ");
for (i = 0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
char *mode = get_errno_by_misc(argv[1]);
if (mode)
show_errcode(mode);
return 0;
}
static int do_errcode_show(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i = 0;
printf("AVB2 Error List:\n");
for (i = 0; i < AVB_MAX_ERROR; i++)
printf(" %s : %s\n", error_avb[i].err_code, error_avb[i].err_string);
printf("\nReboot Mode Error List:\n");
for (i = 0; i < MODE_MAX_PART; i++)
printf(" %s : %s\n", error_mode[i].err_code, error_mode[i].err_string);
printf("\nMisc Reason Error List:\n");
for (i = 0; i < MISC_MAX_PART; i++)
printf(" %s : %s\n", error_misc[i].err_code, error_misc[i].err_string);
printf("\n");
return 0;
}
static cmd_tbl_t cmd_errcode_sub[] = {
U_BOOT_CMD_MKENT(avb2, 2, 0, do_errcode_avb2, "", ""),
U_BOOT_CMD_MKENT(mode, 1, 0, do_errcode_mode, "", ""),
U_BOOT_CMD_MKENT(misc, 1, 0, do_errcode_misc, "", ""),
U_BOOT_CMD_MKENT(show, 0, 0, do_errcode_show, "", ""),
};
static int do_RunErrCommand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
cmd_tbl_t *c;
int ret = 0;
/* Strip off leading 'errcode' command argument */
argc--;
argv++;
c = find_cmd_tbl(argv[0], &cmd_errcode_sub[0], ARRAY_SIZE(cmd_errcode_sub));
if (c)
ret = c->cmd(cmdtp, flag, argc, argv);
else
cmd_usage(cmdtp);
return ret;
}
U_BOOT_CMD
(errcode, 4, 0, do_RunErrCommand,
"errcode",
"\nThis command will show and save errcode to misc partition\n"
"Command format:\n"
"errcode avb2 <part_name> <avb2_errcode> --- show avb2 errcode.\n"
"errcode mode <misc_bcb_reserved_reason> --- show reboot mode errcode.\n"
"errcode misc <misc_bcb_recovery_reason> --- show misc bcb errcode.\n"
"errcode show --- show all errcode.\n"
"will show errcode E1402;\n" // command
"So you can execute command: errcode avb2 boot 4"
);