xref: /rk3399_rockchip-uboot/cmd/script_update.c (revision 8b0f08e57d8c2a3d1c47a66be61334c08d2f61ac)
1a951a295SJoseph Chen /*
2a951a295SJoseph Chen  * (C) Copyright 2022 Rockchip Electronics Co., Ltd.
3a951a295SJoseph Chen  *
4a951a295SJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
5a951a295SJoseph Chen  */
6a951a295SJoseph Chen 
7a951a295SJoseph Chen #include <common.h>
8a951a295SJoseph Chen #include <malloc.h>
9a951a295SJoseph Chen 
10a951a295SJoseph Chen /*
11a951a295SJoseph Chen  * Script file example:
12a951a295SJoseph Chen  **************************
13a951a295SJoseph Chen  * > # script file start
14a951a295SJoseph Chen  * > echo "hello world"
15a951a295SJoseph Chen  * > % script file end
16a951a295SJoseph Chen  **************************
17a951a295SJoseph Chen  */
18a951a295SJoseph Chen #define SCRIPT_FILE_MAX_SIZE	(12 * 1024)
19a951a295SJoseph Chen #define SCRIPT_FILE_COMMENT	'#'
20a951a295SJoseph Chen #define SCRIPT_FILE_END		'%'
21a951a295SJoseph Chen #define IS_COMMENT(x)		(SCRIPT_FILE_COMMENT == (x))
22a951a295SJoseph Chen #define IS_FILE_END(x)		(SCRIPT_FILE_END == (x))
23a951a295SJoseph Chen #define IS_LINE_END(x)		('\r' == (x) || '\n' == (x))
24a951a295SJoseph Chen #define MAX_LINE_SIZE		8000
25a951a295SJoseph Chen 
26a951a295SJoseph Chen static char *script_next_line(char **line_buf_ptr)
27a951a295SJoseph Chen {
28a951a295SJoseph Chen 	char *line_buf = (*line_buf_ptr);
29a951a295SJoseph Chen 	char *next_line;
30a951a295SJoseph Chen 	int i = 0;
31a951a295SJoseph Chen 
32a951a295SJoseph Chen 	/* strip '\r', '\n' and comment */
33a951a295SJoseph Chen 	while (1) {
34a951a295SJoseph Chen 		/* strip '\r' & '\n' */
35a951a295SJoseph Chen 		if (IS_LINE_END(line_buf[0])) {
36a951a295SJoseph Chen 			line_buf++;
37a951a295SJoseph Chen 		/* strip comment */
38a951a295SJoseph Chen 		} else if (IS_COMMENT(line_buf[0])) {
39a951a295SJoseph Chen 			for (i = 0; !IS_LINE_END(line_buf[0]) && i <= MAX_LINE_SIZE; i++)
40a951a295SJoseph Chen 				line_buf++;
41a951a295SJoseph Chen 
42a951a295SJoseph Chen 			if (i > MAX_LINE_SIZE) {
43a951a295SJoseph Chen 				line_buf[0] = SCRIPT_FILE_END;
44a951a295SJoseph Chen 				printf("Error: max line length is %d!!!\n", MAX_LINE_SIZE);
45a951a295SJoseph Chen 				break;
46a951a295SJoseph Chen 			}
47a951a295SJoseph Chen 		} else {
48a951a295SJoseph Chen 			break;
49a951a295SJoseph Chen 		}
50a951a295SJoseph Chen 	}
51a951a295SJoseph Chen 
52a951a295SJoseph Chen 	/* get next line */
53a951a295SJoseph Chen 	if (IS_FILE_END(line_buf[0])) {
54a951a295SJoseph Chen 		next_line = NULL;
55a951a295SJoseph Chen 	} else {
56a951a295SJoseph Chen 		next_line = line_buf;
57a951a295SJoseph Chen 		for (i = 0; !IS_LINE_END(line_buf[0]) && i <= MAX_LINE_SIZE; i++)
58a951a295SJoseph Chen 			line_buf++;
59a951a295SJoseph Chen 
60a951a295SJoseph Chen 		if (i > MAX_LINE_SIZE) {
61a951a295SJoseph Chen 			next_line = NULL;
62a951a295SJoseph Chen 			printf("Error: max line length is %d!!!\n", MAX_LINE_SIZE);
63a951a295SJoseph Chen 		} else {
64a951a295SJoseph Chen 			line_buf[0] = '\0';
65a951a295SJoseph Chen 			*line_buf_ptr = line_buf + 1;
66a951a295SJoseph Chen 		}
67a951a295SJoseph Chen 	}
68a951a295SJoseph Chen 
69a951a295SJoseph Chen 	return next_line;
70a951a295SJoseph Chen }
71a951a295SJoseph Chen 
72a951a295SJoseph Chen static int do_script(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
73a951a295SJoseph Chen {
74a951a295SJoseph Chen 	char *next_line, *script, *buf;
75a951a295SJoseph Chen 	ulong addr;
76ef3691edSJoseph Chen 	int ret = CMD_RET_SUCCESS;
77a951a295SJoseph Chen 
78*8b0f08e5SJoseph Chen #ifdef CONFIG_FIT_SIGNATURE
79*8b0f08e5SJoseph Chen 	printf("Verify-boot: forbit no-signed script\n");
80*8b0f08e5SJoseph Chen 	return CMD_RET_FAILURE;
81*8b0f08e5SJoseph Chen #endif
82*8b0f08e5SJoseph Chen 
83a951a295SJoseph Chen 	if (argc != 2 || !argv[1])
84a951a295SJoseph Chen 		return CMD_RET_USAGE;
85a951a295SJoseph Chen 
86a951a295SJoseph Chen 	addr = simple_strtoul(argv[1], NULL, 16);
87a951a295SJoseph Chen 	if (!addr)
88a951a295SJoseph Chen 		return CMD_RET_USAGE;
89a951a295SJoseph Chen 
90a951a295SJoseph Chen 	buf = calloc(SCRIPT_FILE_MAX_SIZE, 1);
91a951a295SJoseph Chen 	if (!buf)
92a951a295SJoseph Chen 		return CMD_RET_FAILURE;
93a951a295SJoseph Chen 
94a951a295SJoseph Chen 	script = buf;
95a951a295SJoseph Chen 	memcpy(buf, (char *)addr, SCRIPT_FILE_MAX_SIZE);
96a951a295SJoseph Chen 	while ((next_line = script_next_line(&script)) != NULL) {
97a951a295SJoseph Chen 		printf("\n$ %s\n", next_line);
98ef3691edSJoseph Chen 		ret = run_command(next_line, 0);
99ef3691edSJoseph Chen 		if (ret)
100ef3691edSJoseph Chen 			break;	/* fail */
101a951a295SJoseph Chen 	}
102a951a295SJoseph Chen 	free(buf);
103a951a295SJoseph Chen 
104ef3691edSJoseph Chen 	return ret;
105a951a295SJoseph Chen }
106a951a295SJoseph Chen 
107a951a295SJoseph Chen static int do_sd_update(cmd_tbl_t *cmdtp, int flag,
108a951a295SJoseph Chen 			int argc, char * const argv[])
109a951a295SJoseph Chen {
110*8b0f08e5SJoseph Chen 	struct blk_desc *desc;
111*8b0f08e5SJoseph Chen 	int part_type;
112a951a295SJoseph Chen 	char cmd[128];
113a951a295SJoseph Chen 	char *buf;
114a951a295SJoseph Chen 	int ret;
115a951a295SJoseph Chen 
116*8b0f08e5SJoseph Chen 	printf("## retrieving sd_update.txt ...\n");
117*8b0f08e5SJoseph Chen 
118*8b0f08e5SJoseph Chen 	desc = blk_get_devnum_by_type(IF_TYPE_MMC, 1);
119*8b0f08e5SJoseph Chen 	if (!desc)
120*8b0f08e5SJoseph Chen 		return CMD_RET_FAILURE;
121*8b0f08e5SJoseph Chen 
122a951a295SJoseph Chen 	buf = memalign(ARCH_DMA_MINALIGN, SCRIPT_FILE_MAX_SIZE * 2);
123a951a295SJoseph Chen 	if (!buf)
124a951a295SJoseph Chen 		return CMD_RET_FAILURE;
125a951a295SJoseph Chen 
126*8b0f08e5SJoseph Chen 	part_type = desc->part_type;
127*8b0f08e5SJoseph Chen 	desc->part_type = PART_TYPE_DOS;
128*8b0f08e5SJoseph Chen 
129*8b0f08e5SJoseph Chen 	snprintf(cmd, sizeof(cmd),
130*8b0f08e5SJoseph Chen 		 "fatload mmc 1 0x%08lx sd_update.txt", (ulong)buf);
131a951a295SJoseph Chen 	ret = run_command(cmd, 0);
1320ac34d7fSJoseph Chen 	if (!ret) {
133*8b0f08e5SJoseph Chen 		snprintf(cmd, sizeof(cmd), "script 0x%08lx", (ulong)buf);
1340ac34d7fSJoseph Chen 		ret = run_command(cmd, 0);
1350ac34d7fSJoseph Chen 	}
136a951a295SJoseph Chen 	free(buf);
137a951a295SJoseph Chen 
138*8b0f08e5SJoseph Chen 	desc->part_type = part_type;
139*8b0f08e5SJoseph Chen 
140a951a295SJoseph Chen 	return ret;
141a951a295SJoseph Chen }
142a951a295SJoseph Chen 
143a951a295SJoseph Chen static int do_usb_update(cmd_tbl_t *cmdtp, int flag,
144a951a295SJoseph Chen 			 int argc, char * const argv[])
145a951a295SJoseph Chen {
146*8b0f08e5SJoseph Chen 	struct blk_desc *desc;
147*8b0f08e5SJoseph Chen 	int part_type;
148a951a295SJoseph Chen 	char cmd[128];
149a951a295SJoseph Chen 	char *buf;
150a951a295SJoseph Chen 	int ret;
151a951a295SJoseph Chen 
152*8b0f08e5SJoseph Chen 	printf("## retrieving usb_update.txt ...\n");
153*8b0f08e5SJoseph Chen 
154*8b0f08e5SJoseph Chen 	desc = blk_get_devnum_by_type(IF_TYPE_USB, 0);
155*8b0f08e5SJoseph Chen 	if (!desc)
156*8b0f08e5SJoseph Chen 		return CMD_RET_FAILURE;
157*8b0f08e5SJoseph Chen 
158a951a295SJoseph Chen 	buf = memalign(ARCH_DMA_MINALIGN, SCRIPT_FILE_MAX_SIZE * 2);
159a951a295SJoseph Chen 	if (!buf)
160a951a295SJoseph Chen 		return CMD_RET_FAILURE;
161a951a295SJoseph Chen 
162*8b0f08e5SJoseph Chen 	part_type = desc->part_type;
163*8b0f08e5SJoseph Chen 	desc->part_type = PART_TYPE_DOS;
164*8b0f08e5SJoseph Chen 
165*8b0f08e5SJoseph Chen 	snprintf(cmd, sizeof(cmd), "usb reset");
166a951a295SJoseph Chen 	ret = run_command(cmd, 0);
1670ac34d7fSJoseph Chen 	if (!ret) {
168*8b0f08e5SJoseph Chen 		snprintf(cmd, sizeof(cmd), "fatload usb 0 0x%08lx usb_update.txt", (ulong)buf);
1690ac34d7fSJoseph Chen 		ret = run_command(cmd, 0);
1700ac34d7fSJoseph Chen 	}
1710ac34d7fSJoseph Chen 	if (!ret) {
172*8b0f08e5SJoseph Chen 		snprintf(cmd, sizeof(cmd), "script 0x%08lx", (ulong)buf);
1730ac34d7fSJoseph Chen 		ret = run_command(cmd, 0);
1740ac34d7fSJoseph Chen 	}
175a951a295SJoseph Chen 	free(buf);
176a951a295SJoseph Chen 
177*8b0f08e5SJoseph Chen 	desc->part_type = part_type;
178*8b0f08e5SJoseph Chen 
179a951a295SJoseph Chen 	return ret;
180a951a295SJoseph Chen }
181a951a295SJoseph Chen 
182a951a295SJoseph Chen static int do_tftp_update(cmd_tbl_t *cmdtp, int flag,
183a951a295SJoseph Chen 			  int argc, char * const argv[])
184a951a295SJoseph Chen {
185a951a295SJoseph Chen 	char cmd[128];
186a951a295SJoseph Chen 	char *buf;
187a951a295SJoseph Chen 	int dhcp = 0;
188a951a295SJoseph Chen 	int ret;
189a951a295SJoseph Chen 
190*8b0f08e5SJoseph Chen 	printf("## retrieving tftp_update.txt ...\n");
191*8b0f08e5SJoseph Chen 
192a951a295SJoseph Chen 	if ((argc > 1) && !strcmp(argv[1], "-d"))
193a951a295SJoseph Chen 		dhcp = 1;
194a951a295SJoseph Chen 
195a951a295SJoseph Chen 	buf = memalign(ARCH_DMA_MINALIGN, SCRIPT_FILE_MAX_SIZE * 2);
196a951a295SJoseph Chen 	if (!buf)
197a951a295SJoseph Chen 		return CMD_RET_FAILURE;
198a951a295SJoseph Chen 
199a951a295SJoseph Chen 	if (dhcp)
200a951a295SJoseph Chen 		run_command("dhcp", 0);
201a951a295SJoseph Chen 
202*8b0f08e5SJoseph Chen 	snprintf(cmd, sizeof(cmd), "tftp 0x%08lx tftp_update.txt", (ulong)buf);
203a951a295SJoseph Chen 	ret = run_command(cmd, 0);
2040ac34d7fSJoseph Chen 	if (!ret) {
205*8b0f08e5SJoseph Chen 		snprintf(cmd, sizeof(cmd), "script 0x%08lx", (ulong)buf);
2060ac34d7fSJoseph Chen 		ret = run_command(cmd, 0);
2070ac34d7fSJoseph Chen 	}
208a951a295SJoseph Chen 	free(buf);
209a951a295SJoseph Chen 
210a951a295SJoseph Chen 	return ret;
211a951a295SJoseph Chen }
212a951a295SJoseph Chen 
213a951a295SJoseph Chen U_BOOT_CMD(
214a951a295SJoseph Chen 	script, 2, 1, do_script,
215a951a295SJoseph Chen 	"Run a script", "[file addr]"
216a951a295SJoseph Chen );
217a951a295SJoseph Chen 
218a951a295SJoseph Chen U_BOOT_CMD(
219a951a295SJoseph Chen 	sd_update, 1, 1, do_sd_update,
220a951a295SJoseph Chen 	"sdcard auto upgrade", ""
221a951a295SJoseph Chen );
222a951a295SJoseph Chen 
223a951a295SJoseph Chen U_BOOT_CMD(
224a951a295SJoseph Chen 	usb_update, 1, 1, do_usb_update,
225a951a295SJoseph Chen 	"usb auto upgrade", ""
226a951a295SJoseph Chen );
227a951a295SJoseph Chen 
228a951a295SJoseph Chen U_BOOT_CMD(
229a951a295SJoseph Chen 	tftp_update, 2, 1, do_tftp_update,
230a951a295SJoseph Chen 	"tftp auto upgrade", "[-d]"
231a951a295SJoseph Chen );
232a951a295SJoseph Chen 
233