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