blob: 21267f6aa285b1d8f865456fabc8eeda76b87d37 [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
Xindong Xuc0b93662023-12-08 10:35:55 +080051#if (IS_ENABLED(CONFIG_CMD_BCB))
Bo Lv72d0e902023-01-02 14:27:34 +000052static bool env_command_check(const char *cmd)
53{
54 int index = 0;
55 int envListNum = 0;
56 char *s = NULL;
57 char *v = NULL;
58 char *strcopy = NULL;
59 const char **envListArr = (const char **)_env_list_execute_;
60
61 const char **pArr = (const char **)envListArr;
62
63 while (*pArr++) {
64 ++envListNum;
65 }
66
67 printf("envListNum = %d\n", envListNum);
68
69 if (envListNum == 0) {
70 return false;
71 }
72
73 strcopy = strdup(cmd);
74 if (!strcopy) {
75 return false;
76 }
77
78 s = strcopy;
79 while ((v = strsep(&s, ";")) != NULL) {
80 char *p = v;
81
82 strsep(&p, " ");
83 for (index = 0; index < envListNum; index++) {
84 if (!strcmp(envListArr[index], v)) {
85 break;
86 }
87 }
88
89 if (index == envListNum) {
90 printf("%s not in the white list.\n", v);
91 free(strcopy);
92 strcopy = NULL;
93 return false;
94 }
95 }
96
97 free(strcopy);
98 strcopy = NULL;
99 return true;
100}
Xindong Xuc0b93662023-12-08 10:35:55 +0800101#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000102
103static int clear_misc_partition(char *clearbuf, int size)
104{
105 char *partition = "misc";
106
107 memset(clearbuf, 0, size);
108 if (store_write((const char *)partition,
109 0, size, (unsigned char *)clearbuf) < 0) {
110 printf("failed to clear %s.\n", partition);
111 return -1;
112 }
113
114 return 0;
115}
116
117static int my_atoi(const char *str)
118{
119 int result = 0;
120 int signal = 1;
121
122 if ((*str >= '0' && *str <= '9') || *str == '-' || *str == '+') {
123 if (*str == '-' || *str == '+') {
124 if (*str == '-')
125 signal = -1;
126 str++;
127 }
128 } else {
129 return 0;
130 }
131
132 while (*str >= '0' && *str <= '9')
133 result = result * 10 + (*str++ - '0');
134
135 return signal * result;
136}
137
138static int do_RunBcbCommand(
139 cmd_tbl_t * cmdtp,
140 int flag,
141 int argc,
142 char * const argv[])
143{
144 int i = 0;
145 char command[COMMANDBUF_SIZE] = {0};
146 char status[STATUSBUF_SIZE] = {0};
147 char recovery[RECOVERYBUF_SIZE] = {0};
148 char miscbuf[MISCBUF_SIZE] = {0};
149 char clearbuf[COMMANDBUF_SIZE+STATUSBUF_SIZE+RECOVERYBUF_SIZE] = {0};
150 char* RebootMode;
Zhigang Yu3cd307e2024-11-05 10:46:20 +0800151 char *powermode;
Bo Lv72d0e902023-01-02 14:27:34 +0000152 int remain_time = 0;
153
154 if (argc != 2) {
155 return cmd_usage(cmdtp);
156 }
157
158 printf("Command: ");
159 for (i = 0; i < argc; i++) {
160 printf("%s ", argv[i]);
161 }
162 printf("\n");
163
164 char *partition = "misc";
165 char *command_mark = (char *)argv[1];
166
167 if (strlen(command_mark) > sizeof(command)) {
168 //printf("Bcb command mark range out of length(%d > %d).\n",
169 //strlen(command_mark), sizeof(command));
170 goto ERR;
171 }
172
173 if (!memcmp(command_mark, CMD_WIPE_DATA, strlen(command_mark))) {
174 printf("Start to write --wipe_data to %s\n", partition);
175 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
176 memcpy(miscbuf+sizeof(command)+sizeof(status), "recovery\n--wipe_data", sizeof("recovery\n--wipe_data"));
177 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
178 } else if (!memcmp(command_mark, CMD_SYSTEM_CRASH, strlen(command_mark))) {
179 printf("Start to write --system_crash to %s\n", partition);
180 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
181 memcpy(miscbuf+sizeof(command)+sizeof(status), "recovery\n--system_crash", sizeof("recovery\n--system_crash"));
182 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
183 } else if (!memcmp(command_mark, CMD_RESIZE_DATA, strlen(command_mark))) {
184 printf("Start to write --resize2fs_data to %s\n", partition);
185 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
186 memcpy(miscbuf+sizeof(command)+sizeof(status), "recovery\n--resize2fs_data", sizeof("recovery\n--resize2fs_data"));
187 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
188 } else if (!memcmp(command_mark, CMD_FOR_RECOVERY, strlen(CMD_FOR_RECOVERY))) {
189 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
190 sprintf(recovery, "%s%s", "recovery\n--", command_mark);
191 memcpy(miscbuf+sizeof(command)+sizeof(status), recovery, strlen(recovery));
192 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
193 return 0;
194 } else if (!memcmp(command_mark, CMD_FASTBOOTD, strlen(command_mark))) {
195 printf("write cmd to enter fastbootd \n");
196 memcpy(miscbuf, CMD_RUN_RECOVERY, sizeof(CMD_RUN_RECOVERY));
197 memcpy(miscbuf+sizeof(command)+sizeof(status), "recovery\n--fastboot", sizeof("recovery\n--fastboot"));
198 store_write((const char *)partition, 0, sizeof(miscbuf), (unsigned char *)miscbuf);
199 return 0;
200 }
201
202 printf("Start read %s partition datas!\n", partition);
203 if (store_read((const char *)partition,
204 0, sizeof(miscbuf), (unsigned char *)miscbuf) < 0) {
205 printf("failed to store read %s.\n", partition);
206 goto ERR;
207 }
208
209 // judge misc partition whether has datas
210 char tmpbuf[MISCBUF_SIZE];
211 memset(tmpbuf, 0, sizeof(tmpbuf));
212 if (!memcmp(tmpbuf, miscbuf, strlen(miscbuf))) {
213 env_set("retry_recovery_times", "7");
214#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
215 run_command("update_env_part -p retry_recovery_times;", 0);
216#else
217 run_command("saveenv;", 0);
218#endif
219 printf("BCB hasn't any datas,exit!\n");
220 return 0;
221 }
222
223 memcpy(command, miscbuf, sizeof(command));
224 memcpy(status, miscbuf+sizeof(command), sizeof(status));
225 memcpy(recovery, miscbuf+sizeof(command)+sizeof(status), sizeof(recovery));
226 memcpy(clearbuf, miscbuf, sizeof(clearbuf));
227
228 printf("get bootloader message from misc partition:\n");
229 printf("[command:%s]\n[status:%s]\n[recovery:%s]\n",
230 command, status, recovery);
231
232 run_command("get_rebootmode", 0);
233 RebootMode = env_get("reboot_mode");
Zhigang Yu3cd307e2024-11-05 10:46:20 +0800234 if (RebootMode && strstr(RebootMode, "quiescent")) {
235 printf("quiescent mode.\n");
Bo Lv72d0e902023-01-02 14:27:34 +0000236 run_command("run storeargs", 0);
237 run_command("setenv bootconfig ${bootconfig} androidboot.quiescent=1;", 0);
238 }
239
Zhigang Yu3cd307e2024-11-05 10:46:20 +0800240 powermode = env_get("powermode");
241 if (RebootMode && !strcmp(RebootMode, "cold_boot")) {
242 if (powermode && !strcmp(powermode, "standby")) {
243 printf("cold_boot default standby, ignore recovery mode\n");
244 clear_misc_partition(clearbuf, sizeof(clearbuf));
245 return 0;
246 }
247 }
248
Bo Lv72d0e902023-01-02 14:27:34 +0000249 char *retry_times;
250
251 retry_times = env_get("retry_recovery_times");
252 if (retry_times) {
253 printf("retry_time: %s\n", retry_times);
254 remain_time = my_atoi(retry_times);
255 printf("retry_time remain_time = %d\n", remain_time);
256 }
257
258 if (remain_time == 0) {
259 printf("clear recovery cmds in misc\n");
260 if (clear_misc_partition(clearbuf, sizeof(clearbuf)) < 0) {
261 printf("clear misc partition failed.\n");
262 goto ERR;
263 }
264 env_set("retry_recovery_times", "7");
265#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
266 run_command("update_env_part -p retry_recovery_times;", 0);
267#else
268 run_command("saveenv;", 0);
269#endif
270 run_command("run enter_fastboot", 0);
271 }
272
273 if (!memcmp(command, CMD_RUN_RECOVERY, strlen(CMD_RUN_RECOVERY))) {
274 if (retry_times && remain_time > 0) {
275 sprintf(retry_times, "%d", remain_time - 1);
276 printf("retry_time: %s\n", retry_times);
277 env_set("retry_recovery_times", retry_times);
278#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
279 run_command("update_env_part -p retry_recovery_times;", 0);
280#else
281 run_command("saveenv;", 0);
282#endif
283 }
284
285 if (run_command("run recovery_from_flash", 0) < 0) {
286 printf("run_command for cmd:run recovery_from_flash failed.\n");
287 return -1;
288 }
289 printf("run command:run recovery_from_flash successful.\n");
290 return 0;
291 }
292
Xindong Xuc0b93662023-12-08 10:35:55 +0800293#if (IS_ENABLED(CONFIG_CMD_BCB))
Bo Lv72d0e902023-01-02 14:27:34 +0000294 //uboot-command only valid once, not matter success or not
295 if (clear_misc_partition(clearbuf, sizeof(clearbuf)) < 0) {
296 printf("clear misc partition failed.\n");
297 goto ERR;
298 }
299
300 if (!memcmp(command_mark, command, strlen(command_mark))) {
301 printf("%s\n", recovery);
302 if (run_command((char *)recovery, 0) < 0) {
303 printf("run_command for cmd:%s failed.\n", recovery);
304 goto ERR;
305 }
306 printf("run command successful.\n");
307 } else if (!strncmp(command_mark, "uboot-command", strlen("uboot-command"))) {
308 printf("uboot-command: %s\n", command);
309
310 if (!env_command_check(command)) {
311 printf("not all uboot-command in white-list\n");
312 goto ERR;
313 }
314 if (run_command((char *)command, 0) < 0) {
315 printf("run_command for cmd:%s failed.\n", command);
316 goto ERR;
317 }
318 printf("run uboot-command successful.\n");
319
320 } else {
321 printf("command mark(%s) not match %s,don't execute.\n",
322 command_mark, command);
323 }
Xindong Xuc0b93662023-12-08 10:35:55 +0800324#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000325
326 return 0;
327
328 ERR:
329 return -1;
330}
331#else
332static int do_RunBcbCommand(
333 cmd_tbl_t * cmdtp,
334 int flag,
335 int argc,
336 char * const argv[])
337{
338 if (argc != 2) {
339 return cmd_usage(cmdtp);
340 }
341
342 // Do-Nothing!
343 return 0;
344}
345#endif /* CONFIG_BOOTLOADER_CONTROL_BLOCK */
346
347
348// BCB: Bootloader Control Block
349U_BOOT_CMD(
350 bcb, 2, 0, do_RunBcbCommand,
351 "bcb",
352 "\nThis command will run some commands which saved in misc\n"
353 "partition by mark to decide whether execute command!\n"
354 "Command format:\n"
355 " bcb bcb_mark\n"
356 "Example:\n"
357 " /dev/block/misc partition is saved some contents:\n"
358 " uboot-command\n" // command mark
359 " N/A\n"
360 " setenv aa 11;setenv bb 22;setenv cc 33;saveenv;\n" // command
361 "So you can execute command: bcb uboot-command"
362);