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