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> 9*8c39bc79SJoseph Chen #include <dm/device.h> 10a951a295SJoseph Chen 11a951a295SJoseph Chen /* 12a951a295SJoseph Chen * Script file example: 13a951a295SJoseph Chen ************************** 14a951a295SJoseph Chen * > # script file start 15a951a295SJoseph Chen * > echo "hello world" 16a951a295SJoseph Chen * > % script file end 17a951a295SJoseph Chen ************************** 18a951a295SJoseph Chen */ 19a951a295SJoseph Chen #define SCRIPT_FILE_MAX_SIZE (12 * 1024) 20a951a295SJoseph Chen #define SCRIPT_FILE_COMMENT '#' 21a951a295SJoseph Chen #define SCRIPT_FILE_END '%' 22a951a295SJoseph Chen #define IS_COMMENT(x) (SCRIPT_FILE_COMMENT == (x)) 23a951a295SJoseph Chen #define IS_FILE_END(x) (SCRIPT_FILE_END == (x)) 24a951a295SJoseph Chen #define IS_LINE_END(x) ('\r' == (x) || '\n' == (x)) 25a951a295SJoseph Chen #define MAX_LINE_SIZE 8000 26a951a295SJoseph Chen 27a951a295SJoseph Chen static char *script_next_line(char **line_buf_ptr) 28a951a295SJoseph Chen { 29a951a295SJoseph Chen char *line_buf = (*line_buf_ptr); 30a951a295SJoseph Chen char *next_line; 31a951a295SJoseph Chen int i = 0; 32a951a295SJoseph Chen 33a951a295SJoseph Chen /* strip '\r', '\n' and comment */ 34a951a295SJoseph Chen while (1) { 35a951a295SJoseph Chen /* strip '\r' & '\n' */ 36a951a295SJoseph Chen if (IS_LINE_END(line_buf[0])) { 37a951a295SJoseph Chen line_buf++; 38a951a295SJoseph Chen /* strip comment */ 39a951a295SJoseph Chen } else if (IS_COMMENT(line_buf[0])) { 40a951a295SJoseph Chen for (i = 0; !IS_LINE_END(line_buf[0]) && i <= MAX_LINE_SIZE; i++) 41a951a295SJoseph Chen line_buf++; 42a951a295SJoseph Chen 43a951a295SJoseph Chen if (i > MAX_LINE_SIZE) { 44a951a295SJoseph Chen line_buf[0] = SCRIPT_FILE_END; 45a951a295SJoseph Chen printf("Error: max line length is %d!!!\n", MAX_LINE_SIZE); 46a951a295SJoseph Chen break; 47a951a295SJoseph Chen } 48a951a295SJoseph Chen } else { 49a951a295SJoseph Chen break; 50a951a295SJoseph Chen } 51a951a295SJoseph Chen } 52a951a295SJoseph Chen 53a951a295SJoseph Chen /* get next line */ 54a951a295SJoseph Chen if (IS_FILE_END(line_buf[0])) { 55a951a295SJoseph Chen next_line = NULL; 56a951a295SJoseph Chen } else { 57a951a295SJoseph Chen next_line = line_buf; 58a951a295SJoseph Chen for (i = 0; !IS_LINE_END(line_buf[0]) && i <= MAX_LINE_SIZE; i++) 59a951a295SJoseph Chen line_buf++; 60a951a295SJoseph Chen 61a951a295SJoseph Chen if (i > MAX_LINE_SIZE) { 62a951a295SJoseph Chen next_line = NULL; 63a951a295SJoseph Chen printf("Error: max line length is %d!!!\n", MAX_LINE_SIZE); 64a951a295SJoseph Chen } else { 65a951a295SJoseph Chen line_buf[0] = '\0'; 66a951a295SJoseph Chen *line_buf_ptr = line_buf + 1; 67a951a295SJoseph Chen } 68a951a295SJoseph Chen } 69a951a295SJoseph Chen 70a951a295SJoseph Chen return next_line; 71a951a295SJoseph Chen } 72a951a295SJoseph Chen 73a951a295SJoseph Chen static int do_script(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 74a951a295SJoseph Chen { 75a951a295SJoseph Chen char *next_line, *script, *buf; 76a951a295SJoseph Chen ulong addr; 77ef3691edSJoseph Chen int ret = CMD_RET_SUCCESS; 78a951a295SJoseph Chen 798b0f08e5SJoseph Chen #ifdef CONFIG_FIT_SIGNATURE 808b0f08e5SJoseph Chen printf("Verify-boot: forbit no-signed script\n"); 818b0f08e5SJoseph Chen return CMD_RET_FAILURE; 828b0f08e5SJoseph Chen #endif 838b0f08e5SJoseph Chen 84a951a295SJoseph Chen if (argc != 2 || !argv[1]) 85a951a295SJoseph Chen return CMD_RET_USAGE; 86a951a295SJoseph Chen 87a951a295SJoseph Chen addr = simple_strtoul(argv[1], NULL, 16); 88a951a295SJoseph Chen if (!addr) 89a951a295SJoseph Chen return CMD_RET_USAGE; 90a951a295SJoseph Chen 91a951a295SJoseph Chen buf = calloc(SCRIPT_FILE_MAX_SIZE, 1); 92a951a295SJoseph Chen if (!buf) 93a951a295SJoseph Chen return CMD_RET_FAILURE; 94a951a295SJoseph Chen 95a951a295SJoseph Chen script = buf; 96a951a295SJoseph Chen memcpy(buf, (char *)addr, SCRIPT_FILE_MAX_SIZE); 97a951a295SJoseph Chen while ((next_line = script_next_line(&script)) != NULL) { 98a951a295SJoseph Chen printf("\n$ %s\n", next_line); 99ef3691edSJoseph Chen ret = run_command(next_line, 0); 100ef3691edSJoseph Chen if (ret) 101ef3691edSJoseph Chen break; /* fail */ 102a951a295SJoseph Chen } 103a951a295SJoseph Chen free(buf); 104a951a295SJoseph Chen 105ef3691edSJoseph Chen return ret; 106a951a295SJoseph Chen } 107a951a295SJoseph Chen 108a951a295SJoseph Chen static int do_sd_update(cmd_tbl_t *cmdtp, int flag, 109a951a295SJoseph Chen int argc, char * const argv[]) 110a951a295SJoseph Chen { 1118b0f08e5SJoseph Chen struct blk_desc *desc; 1128b0f08e5SJoseph Chen int part_type; 113a951a295SJoseph Chen char cmd[128]; 114a951a295SJoseph Chen char *buf; 115a951a295SJoseph Chen int ret; 116a951a295SJoseph Chen 1178b0f08e5SJoseph Chen printf("## retrieving sd_update.txt ...\n"); 1188b0f08e5SJoseph Chen 1198b0f08e5SJoseph Chen desc = blk_get_devnum_by_type(IF_TYPE_MMC, 1); 1208b0f08e5SJoseph Chen if (!desc) 1218b0f08e5SJoseph Chen return CMD_RET_FAILURE; 1228b0f08e5SJoseph Chen 123a951a295SJoseph Chen buf = memalign(ARCH_DMA_MINALIGN, SCRIPT_FILE_MAX_SIZE * 2); 124a951a295SJoseph Chen if (!buf) 125a951a295SJoseph Chen return CMD_RET_FAILURE; 126a951a295SJoseph Chen 1278b0f08e5SJoseph Chen part_type = desc->part_type; 1288b0f08e5SJoseph Chen desc->part_type = PART_TYPE_DOS; 1298b0f08e5SJoseph Chen 1308b0f08e5SJoseph Chen snprintf(cmd, sizeof(cmd), 1318b0f08e5SJoseph Chen "fatload mmc 1 0x%08lx sd_update.txt", (ulong)buf); 132a951a295SJoseph Chen ret = run_command(cmd, 0); 1330ac34d7fSJoseph Chen if (!ret) { 1348b0f08e5SJoseph Chen snprintf(cmd, sizeof(cmd), "script 0x%08lx", (ulong)buf); 1350ac34d7fSJoseph Chen ret = run_command(cmd, 0); 1360ac34d7fSJoseph Chen } 137a951a295SJoseph Chen free(buf); 138a951a295SJoseph Chen 1398b0f08e5SJoseph Chen desc->part_type = part_type; 1408b0f08e5SJoseph Chen 141a951a295SJoseph Chen return ret; 142a951a295SJoseph Chen } 143a951a295SJoseph Chen 144a951a295SJoseph Chen static int do_usb_update(cmd_tbl_t *cmdtp, int flag, 145a951a295SJoseph Chen int argc, char * const argv[]) 146a951a295SJoseph Chen { 1478b0f08e5SJoseph Chen struct blk_desc *desc; 148*8c39bc79SJoseph Chen struct udevice *dev; 149*8c39bc79SJoseph Chen int devnum = -1; 1508b0f08e5SJoseph Chen int part_type; 151a951a295SJoseph Chen char cmd[128]; 152a951a295SJoseph Chen char *buf; 153a951a295SJoseph Chen int ret; 154a951a295SJoseph Chen 1558b0f08e5SJoseph Chen printf("## retrieving usb_update.txt ...\n"); 1568b0f08e5SJoseph Chen 157*8c39bc79SJoseph Chen if (run_command("usb reset", 0)) 1588b0f08e5SJoseph Chen return CMD_RET_FAILURE; 1598b0f08e5SJoseph Chen 160*8c39bc79SJoseph Chen for (blk_first_device(IF_TYPE_USB, &dev); 161*8c39bc79SJoseph Chen dev; 162*8c39bc79SJoseph Chen blk_next_device(&dev)) { 163*8c39bc79SJoseph Chen desc = dev_get_uclass_platdata(dev); 164*8c39bc79SJoseph Chen if (desc->type == DEV_TYPE_UNKNOWN) 165*8c39bc79SJoseph Chen continue; 166*8c39bc79SJoseph Chen 167*8c39bc79SJoseph Chen if (desc->lba > 0L && desc->blksz > 0L) { 168*8c39bc79SJoseph Chen devnum = desc->devnum; 169*8c39bc79SJoseph Chen break; 170*8c39bc79SJoseph Chen } 171*8c39bc79SJoseph Chen } 172*8c39bc79SJoseph Chen if (devnum < 0) { 173*8c39bc79SJoseph Chen printf("No available udisk\n"); 174*8c39bc79SJoseph Chen return CMD_RET_FAILURE; 175*8c39bc79SJoseph Chen } 176*8c39bc79SJoseph Chen 177*8c39bc79SJoseph Chen desc = blk_get_devnum_by_type(IF_TYPE_USB, devnum); 178*8c39bc79SJoseph Chen if (!desc) { 179*8c39bc79SJoseph Chen printf("No usb %d found\n", devnum); 180*8c39bc79SJoseph Chen return CMD_RET_FAILURE; 181*8c39bc79SJoseph Chen } 182*8c39bc79SJoseph Chen 183a951a295SJoseph Chen buf = memalign(ARCH_DMA_MINALIGN, SCRIPT_FILE_MAX_SIZE * 2); 184a951a295SJoseph Chen if (!buf) 185a951a295SJoseph Chen return CMD_RET_FAILURE; 186a951a295SJoseph Chen 1878b0f08e5SJoseph Chen part_type = desc->part_type; 1888b0f08e5SJoseph Chen desc->part_type = PART_TYPE_DOS; 1898b0f08e5SJoseph Chen 190*8c39bc79SJoseph Chen printf("## scanning usb %d\n", devnum); 191*8c39bc79SJoseph Chen snprintf(cmd, sizeof(cmd), "fatload usb %d 0x%08lx usb_update.txt", 192*8c39bc79SJoseph Chen devnum, (ulong)buf); 193a951a295SJoseph Chen ret = run_command(cmd, 0); 1940ac34d7fSJoseph Chen if (!ret) { 1958b0f08e5SJoseph Chen snprintf(cmd, sizeof(cmd), "script 0x%08lx", (ulong)buf); 1960ac34d7fSJoseph Chen ret = run_command(cmd, 0); 1970ac34d7fSJoseph Chen } 198a951a295SJoseph Chen free(buf); 1998b0f08e5SJoseph Chen desc->part_type = part_type; 2008b0f08e5SJoseph Chen 201a951a295SJoseph Chen return ret; 202a951a295SJoseph Chen } 203a951a295SJoseph Chen 204a951a295SJoseph Chen static int do_tftp_update(cmd_tbl_t *cmdtp, int flag, 205a951a295SJoseph Chen int argc, char * const argv[]) 206a951a295SJoseph Chen { 207a951a295SJoseph Chen char cmd[128]; 208a951a295SJoseph Chen char *buf; 209a951a295SJoseph Chen int dhcp = 0; 210a951a295SJoseph Chen int ret; 211a951a295SJoseph Chen 2128b0f08e5SJoseph Chen printf("## retrieving tftp_update.txt ...\n"); 2138b0f08e5SJoseph Chen 214a951a295SJoseph Chen if ((argc > 1) && !strcmp(argv[1], "-d")) 215a951a295SJoseph Chen dhcp = 1; 216a951a295SJoseph Chen 217a951a295SJoseph Chen buf = memalign(ARCH_DMA_MINALIGN, SCRIPT_FILE_MAX_SIZE * 2); 218a951a295SJoseph Chen if (!buf) 219a951a295SJoseph Chen return CMD_RET_FAILURE; 220a951a295SJoseph Chen 221a951a295SJoseph Chen if (dhcp) 222a951a295SJoseph Chen run_command("dhcp", 0); 223a951a295SJoseph Chen 2248b0f08e5SJoseph Chen snprintf(cmd, sizeof(cmd), "tftp 0x%08lx tftp_update.txt", (ulong)buf); 225a951a295SJoseph Chen ret = run_command(cmd, 0); 2260ac34d7fSJoseph Chen if (!ret) { 2278b0f08e5SJoseph Chen snprintf(cmd, sizeof(cmd), "script 0x%08lx", (ulong)buf); 2280ac34d7fSJoseph Chen ret = run_command(cmd, 0); 2290ac34d7fSJoseph Chen } 230a951a295SJoseph Chen free(buf); 231a951a295SJoseph Chen 232a951a295SJoseph Chen return ret; 233a951a295SJoseph Chen } 234a951a295SJoseph Chen 235a951a295SJoseph Chen U_BOOT_CMD( 236a951a295SJoseph Chen script, 2, 1, do_script, 237a951a295SJoseph Chen "Run a script", "[file addr]" 238a951a295SJoseph Chen ); 239a951a295SJoseph Chen 240a951a295SJoseph Chen U_BOOT_CMD( 241a951a295SJoseph Chen sd_update, 1, 1, do_sd_update, 242a951a295SJoseph Chen "sdcard auto upgrade", "" 243a951a295SJoseph Chen ); 244a951a295SJoseph Chen 245a951a295SJoseph Chen U_BOOT_CMD( 246a951a295SJoseph Chen usb_update, 1, 1, do_usb_update, 247a951a295SJoseph Chen "usb auto upgrade", "" 248a951a295SJoseph Chen ); 249a951a295SJoseph Chen 250a951a295SJoseph Chen U_BOOT_CMD( 251a951a295SJoseph Chen tftp_update, 2, 1, do_tftp_update, 252a951a295SJoseph Chen "tftp auto upgrade", "[-d]" 253a951a295SJoseph Chen ); 254a951a295SJoseph Chen 255