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