blob: 69274cdeee56a8ac40bec4e1650c23c928b2e1f2 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <command.h>
8#include <env.h>
9#include <malloc.h>
10#include <asm/byteorder.h>
11#include <config.h>
12#include <asm/amlogic/arch/io.h>
13#include <amlogic/storage.h>
14#include <stdlib.h>
15
16#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
17
18#define COMMANDBUF_SIZE 32
19#define STATUSBUF_SIZE 32
20#define RECOVERYBUF_SIZE 768
21
22#define BOOTINFO_OFFSET 864
23#define SLOTBUF_SIZE 32
24#define MISCBUF_SIZE 1088
25
26#define CMD_WIPE_DATA "wipe_data"
27#define CMD_SYSTEM_CRASH "system_crash"
28#define CMD_RUN_RECOVERY "boot-recovery"
29#define CMD_RESIZE_DATA "resize2fs_data"
30#define CMD_FOR_RECOVERY "recovery_"
31#define CMD_FASTBOOTD "fastbootd"
32
33static const char * const temp_for_compile[] = {"__test1", "__test2", "__test3", NULL};
34extern const char * const _env_list_execute_[0] __attribute__((weak, alias("temp_for_compile")));
35
36struct bootloader_message {
37 char command[32];
38 char status[32];
39 char recovery[768];
40
41 // The 'recovery' field used to be 1024 bytes. It has only ever
42 // been used to store the recovery command line, so 768 bytes
43 // should be plenty. We carve off the last 256 bytes to store the
44 // stage string (for multistage packages) and possible future
45 // expansion.
46 char stage[32];
47 char slot_suffix[32];
48 char reserved[192];
49};
50
51static bool env_command_check(const char *cmd)
52{
53 int index = 0;
54 int envListNum = 0;
55 char *s = NULL;
56 char *v = NULL;
57 char *strcopy = NULL;
58 const char **envListArr = (const char **)_env_list_execute_;
59
60 const char **pArr = (const char **)envListArr;
61
62 while (*pArr++) {
63 ++envListNum;
64 }
65
66 printf("envListNum = %d\n", envListNum);
67
68 if (envListNum == 0) {
69 return false;
70 }
71
72 strcopy = strdup(cmd);
73 if (!strcopy) {
74 return false;
75 }
76
77 s = strcopy;
78 while ((v = strsep(&s, ";")) != NULL) {
79 char *p = v;
80
81 strsep(&p, " ");
82 for (index = 0; index < envListNum; index++) {
83 if (!strcmp(envListArr[index], v)) {
84 break;
85 }
86 }
87
88 if (index == envListNum) {
89 printf("%s not in the white list.\n", v);
90 free(strcopy);
91 strcopy = NULL;
92 return false;
93 }
94 }
95
96 free(strcopy);
97 strcopy = NULL;
98 return true;
99}
100
101static int clear_misc_partition(char *clearbuf, int size)
102{
103 char *partition = "misc";
104
105 memset(clearbuf, 0, size);
106 if (store_write((const char *)partition,
107 0, size, (unsigned char *)clearbuf) < 0) {
108 printf("failed to clear %s.\n", partition);
109 return -1;
110 }
111
112 return 0;
113}
114
115static int my_atoi(const char *str)
116{
117 int result = 0;
118 int signal = 1;
119
120 if ((*str >= '0' && *str <= '9') || *str == '-' || *str == '+') {
121 if (*str == '-' || *str == '+') {
122 if (*str == '-')
123 signal = -1;
124 str++;
125 }
126 } else {
127 return 0;
128 }
129
130 while (*str >= '0' && *str <= '9')
131 result = result * 10 + (*str++ - '0');
132
133 return signal * result;
134}
135
136static int do_RunBcbCommand(
137 cmd_tbl_t * cmdtp,
138 int flag,
139 int argc,
140 char * const argv[])
141{
142 int i = 0;
143 char command[COMMANDBUF_SIZE] = {0};
144 char status[STATUSBUF_SIZE] = {0};
145 char recovery[RECOVERYBUF_SIZE] = {0};
146 char miscbuf[MISCBUF_SIZE] = {0};
147 char clearbuf[COMMANDBUF_SIZE+STATUSBUF_SIZE+RECOVERYBUF_SIZE] = {0};
148 char* RebootMode;
149 int remain_time = 0;
150
151 if (argc != 2) {
152 return cmd_usage(cmdtp);
153 }
154
155 printf("Command: ");
156 for (i = 0; i < argc; i++) {
157 printf("%s ", argv[i]);
158 }
159 printf("\n");
160
161 char *partition = "misc";
162 char *command_mark = (char *)argv[1];
163
164 if (strlen(command_mark) > sizeof(command)) {
165 //printf("Bcb command mark range out of length(%d > %d).\n",
166 //strlen(command_mark), sizeof(command));
167 goto ERR;
168 }
169
170 if (!memcmp(command_mark, CMD_WIPE_DATA, strlen(command_mark))) {
171 printf("Start to write --wipe_data to %s\n", partition);
172 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
173 memcpy(miscbuf+sizeof(command)+sizeof(status), "recovery\n--wipe_data", sizeof("recovery\n--wipe_data"));
174 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
175 } else if (!memcmp(command_mark, CMD_SYSTEM_CRASH, strlen(command_mark))) {
176 printf("Start to write --system_crash to %s\n", partition);
177 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
178 memcpy(miscbuf+sizeof(command)+sizeof(status), "recovery\n--system_crash", sizeof("recovery\n--system_crash"));
179 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
180 } else if (!memcmp(command_mark, CMD_RESIZE_DATA, strlen(command_mark))) {
181 printf("Start to write --resize2fs_data to %s\n", partition);
182 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
183 memcpy(miscbuf+sizeof(command)+sizeof(status), "recovery\n--resize2fs_data", sizeof("recovery\n--resize2fs_data"));
184 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
185 } else if (!memcmp(command_mark, CMD_FOR_RECOVERY, strlen(CMD_FOR_RECOVERY))) {
186 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
187 sprintf(recovery, "%s%s", "recovery\n--", command_mark);
188 memcpy(miscbuf+sizeof(command)+sizeof(status), recovery, strlen(recovery));
189 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
190 return 0;
191 } else if (!memcmp(command_mark, CMD_FASTBOOTD, strlen(command_mark))) {
192 printf("write cmd to enter fastbootd \n");
193 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
194 memcpy(miscbuf+sizeof(command)+sizeof(status), "recovery\n--fastboot", sizeof("recovery\n--fastboot"));
195 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
196 return 0;
197 }
198
199 printf("Start read %s partition datas!\n", partition);
200 if (store_read((const char *)partition,
201 0, sizeof(miscbuf), (unsigned char *)miscbuf) < 0) {
202 printf("failed to store read %s.\n", partition);
203 goto ERR;
204 }
205
206 // judge misc partition whether has datas
207 char tmpbuf[MISCBUF_SIZE];
208 memset(tmpbuf, 0, sizeof(tmpbuf));
209 if (!memcmp(tmpbuf, miscbuf, strlen(miscbuf))) {
210 env_set("retry_recovery_times", "7");
211#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
212 run_command("update_env_part -p retry_recovery_times;", 0);
213#else
214 run_command("saveenv;", 0);
215#endif
216 printf("BCB hasn't any datas,exit!\n");
217 return 0;
218 }
219
220 memcpy(command, miscbuf, sizeof(command));
221 memcpy(status, miscbuf+sizeof(command), sizeof(status));
222 memcpy(recovery, miscbuf+sizeof(command)+sizeof(status), sizeof(recovery));
223 memcpy(clearbuf, miscbuf, sizeof(clearbuf));
224
225 printf("get bootloader message from misc partition:\n");
226 printf("[command:%s]\n[status:%s]\n[recovery:%s]\n",
227 command, status, recovery);
228
229 run_command("get_rebootmode", 0);
230 RebootMode = env_get("reboot_mode");
231 if (strstr(RebootMode, "quiescent") != NULL) {
232 printf("quiescent mode.\n");
233 run_command("run storeargs", 0);
234 run_command("setenv bootconfig ${bootconfig} androidboot.quiescent=1;", 0);
235 }
236
237 char *retry_times;
238
239 retry_times = env_get("retry_recovery_times");
240 if (retry_times) {
241 printf("retry_time: %s\n", retry_times);
242 remain_time = my_atoi(retry_times);
243 printf("retry_time remain_time = %d\n", remain_time);
244 }
245
246 if (remain_time == 0) {
247 printf("clear recovery cmds in misc\n");
248 if (clear_misc_partition(clearbuf, sizeof(clearbuf)) < 0) {
249 printf("clear misc partition failed.\n");
250 goto ERR;
251 }
252 env_set("retry_recovery_times", "7");
253#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
254 run_command("update_env_part -p retry_recovery_times;", 0);
255#else
256 run_command("saveenv;", 0);
257#endif
258 run_command("run enter_fastboot", 0);
259 }
260
261 if (!memcmp(command, CMD_RUN_RECOVERY, strlen(CMD_RUN_RECOVERY))) {
262 if (retry_times && remain_time > 0) {
263 sprintf(retry_times, "%d", remain_time - 1);
264 printf("retry_time: %s\n", retry_times);
265 env_set("retry_recovery_times", retry_times);
266#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
267 run_command("update_env_part -p retry_recovery_times;", 0);
268#else
269 run_command("saveenv;", 0);
270#endif
271 }
272
273 if (run_command("run recovery_from_flash", 0) < 0) {
274 printf("run_command for cmd:run recovery_from_flash failed.\n");
275 return -1;
276 }
277 printf("run command:run recovery_from_flash successful.\n");
278 return 0;
279 }
280
281 //uboot-command only valid once, not matter success or not
282 if (clear_misc_partition(clearbuf, sizeof(clearbuf)) < 0) {
283 printf("clear misc partition failed.\n");
284 goto ERR;
285 }
286
287 if (!memcmp(command_mark, command, strlen(command_mark))) {
288 printf("%s\n", recovery);
289 if (run_command((char *)recovery, 0) < 0) {
290 printf("run_command for cmd:%s failed.\n", recovery);
291 goto ERR;
292 }
293 printf("run command successful.\n");
294 } else if (!strncmp(command_mark, "uboot-command", strlen("uboot-command"))) {
295 printf("uboot-command: %s\n", command);
296
297 if (!env_command_check(command)) {
298 printf("not all uboot-command in white-list\n");
299 goto ERR;
300 }
301 if (run_command((char *)command, 0) < 0) {
302 printf("run_command for cmd:%s failed.\n", command);
303 goto ERR;
304 }
305 printf("run uboot-command successful.\n");
306
307 } else {
308 printf("command mark(%s) not match %s,don't execute.\n",
309 command_mark, command);
310 }
311
312 return 0;
313
314 ERR:
315 return -1;
316}
317#else
318static int do_RunBcbCommand(
319 cmd_tbl_t * cmdtp,
320 int flag,
321 int argc,
322 char * const argv[])
323{
324 if (argc != 2) {
325 return cmd_usage(cmdtp);
326 }
327
328 // Do-Nothing!
329 return 0;
330}
331#endif /* CONFIG_BOOTLOADER_CONTROL_BLOCK */
332
333
334// BCB: Bootloader Control Block
335U_BOOT_CMD(
336 bcb, 2, 0, do_RunBcbCommand,
337 "bcb",
338 "\nThis command will run some commands which saved in misc\n"
339 "partition by mark to decide whether execute command!\n"
340 "Command format:\n"
341 " bcb bcb_mark\n"
342 "Example:\n"
343 " /dev/block/misc partition is saved some contents:\n"
344 " uboot-command\n" // command mark
345 " N/A\n"
346 " setenv aa 11;setenv bb 22;setenv cc 33;saveenv;\n" // command
347 "So you can execute command: bcb uboot-command"
348);