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 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 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 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 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 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