1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (c) 2016 Beniamino Galvani
4 *
5 * Author: Beniamino Galvani <b.galvani@gmail.com>
6 * Author: Vyacheslav Bocharov <adeep@lexina.in>
7 * Author: Neil Armstrong <narmstrong@baylibre.com>
8 * Author: Alexey Romanov <avromanov@sberdevices.ru>
9 */
10
11 #include <command.h>
12 #include <common.h>
13 #include <env.h>
14 #include <asm/arch/sm.h>
15 #include <stdlib.h>
16 #include <display_options.h>
17
do_sm_serial(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])18 static int do_sm_serial(struct cmd_tbl *cmdtp, int flag, int argc,
19 char *const argv[])
20 {
21 ulong address;
22 int ret;
23
24 if (argc < 2)
25 return CMD_RET_USAGE;
26
27 address = simple_strtoul(argv[1], NULL, 0);
28
29 ret = meson_sm_get_serial((void *)address, SM_SERIAL_SIZE);
30 if (ret)
31 return CMD_RET_FAILURE;
32
33 return CMD_RET_SUCCESS;
34 }
35
36 #define MAX_REBOOT_REASONS 14
37
38 static const char *reboot_reasons[MAX_REBOOT_REASONS] = {
39 [REBOOT_REASON_COLD] = "cold_boot",
40 [REBOOT_REASON_NORMAL] = "normal",
41 [REBOOT_REASON_RECOVERY] = "recovery",
42 [REBOOT_REASON_UPDATE] = "update",
43 [REBOOT_REASON_FASTBOOT] = "fastboot",
44 [REBOOT_REASON_SUSPEND_OFF] = "suspend_off",
45 [REBOOT_REASON_HIBERNATE] = "hibernate",
46 [REBOOT_REASON_BOOTLOADER] = "bootloader",
47 [REBOOT_REASON_SHUTDOWN_REBOOT] = "shutdown_reboot",
48 [REBOOT_REASON_RPMBP] = "rpmbp",
49 [REBOOT_REASON_CRASH_DUMP] = "crash_dump",
50 [REBOOT_REASON_KERNEL_PANIC] = "kernel_panic",
51 [REBOOT_REASON_WATCHDOG_REBOOT] = "watchdog_reboot",
52 };
53
do_sm_reboot_reason(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])54 static int do_sm_reboot_reason(struct cmd_tbl *cmdtp, int flag, int argc,
55 char *const argv[])
56 {
57 const char *reason_str;
58 char *destarg = NULL;
59 int reason;
60
61 if (argc > 1)
62 destarg = argv[1];
63
64 reason = meson_sm_get_reboot_reason();
65 if (reason < 0)
66 return CMD_RET_FAILURE;
67
68 if (reason >= MAX_REBOOT_REASONS ||
69 !reboot_reasons[reason])
70 reason_str = "unknown";
71 else
72 reason_str = reboot_reasons[reason];
73
74 if (destarg)
75 env_set(destarg, reason_str);
76 else
77 printf("reboot reason: %s (%x)\n", reason_str, reason);
78
79 return CMD_RET_SUCCESS;
80 }
81
do_efuse_read(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])82 static int do_efuse_read(struct cmd_tbl *cmdtp, int flag, int argc,
83 char *const argv[])
84 {
85 ulong address, offset, size;
86 int ret;
87
88 if (argc < 4)
89 return CMD_RET_USAGE;
90
91 offset = simple_strtoul(argv[1], NULL, 0);
92 size = simple_strtoul(argv[2], NULL, 0);
93
94 address = simple_strtoul(argv[3], NULL, 0);
95
96 ret = meson_sm_read_efuse(offset, (void *)address, size);
97 if (ret != size)
98 return CMD_RET_FAILURE;
99
100 return CMD_RET_SUCCESS;
101 }
102
do_efuse_write(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])103 static int do_efuse_write(struct cmd_tbl *cmdtp, int flag, int argc,
104 char *const argv[])
105 {
106 ulong address, offset, size;
107 int ret;
108
109 if (argc < 4)
110 return CMD_RET_USAGE;
111
112 offset = simple_strtoul(argv[1], NULL, 0);
113 size = simple_strtoul(argv[2], NULL, 0);
114
115 address = simple_strtoul(argv[3], NULL, 0);
116
117 ret = meson_sm_write_efuse(offset, (void *)address, size);
118 if (ret != size)
119 return CMD_RET_FAILURE;
120
121 return CMD_RET_SUCCESS;
122 }
123
do_efuse_dump(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])124 static int do_efuse_dump(struct cmd_tbl *cmdtp, int flag, int argc,
125 char *const argv[])
126 {
127 ulong offset, size;
128 u8 *buffer;
129 int ret;
130
131 if (argc != 3)
132 return CMD_RET_USAGE;
133
134 offset = simple_strtoul(argv[1], NULL, 0);
135 size = simple_strtoul(argv[2], NULL, 0);
136 buffer = malloc(size);
137 if (!buffer) {
138 pr_err("Failed to allocate %lu bytes\n", size);
139 return CMD_RET_FAILURE;
140 }
141
142 ret = meson_sm_read_efuse(offset, (void *)buffer, size);
143 if (ret != size) {
144 ret = CMD_RET_FAILURE;
145 goto free_buffer;
146 }
147
148 print_buffer(0, buffer, 1, size, 0);
149
150 free_buffer:
151 free(buffer);
152 return ret;
153 }
154
155 static struct cmd_tbl cmd_sm_sub[] = {
156 U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
157 U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
158 U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""),
159 U_BOOT_CMD_MKENT(efusewrite, 4, 0, do_efuse_write, "", ""),
160 U_BOOT_CMD_MKENT(efusedump, 3, 1, do_efuse_dump, "", ""),
161 };
162
do_sm(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])163 static int do_sm(struct cmd_tbl *cmdtp, int flag, int argc,
164 char *const argv[])
165 {
166 struct cmd_tbl *c;
167
168 if (argc < 2)
169 return CMD_RET_USAGE;
170
171 /* Strip off leading 'sm' command argument */
172 argc--;
173 argv++;
174
175 c = find_cmd_tbl(argv[0], &cmd_sm_sub[0], ARRAY_SIZE(cmd_sm_sub));
176
177 if (c)
178 return c->cmd(cmdtp, flag, argc, argv);
179 else
180 return CMD_RET_USAGE;
181 }
182
183 U_BOOT_CMD(
184 sm, 5, 0, do_sm,
185 "Secure Monitor Control",
186 "serial <address> - read chip unique id to memory address\n"
187 "sm reboot_reason [name] - get reboot reason and store to environment\n"
188 "sm efuseread <offset> <size> <address> - read efuse to memory address\n"
189 "sm efusewrite <offset> <size> <address> - write into efuse from memory address\n"
190 "sm efusedump <offset> <size> - dump efuse data range to console"
191 );
192