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