1*2e192b24SSimon Glass /* 2*2e192b24SSimon Glass * (C) Copyright 2001 3*2e192b24SSimon Glass * Kyle Harris, kharris@nexus-tech.net 4*2e192b24SSimon Glass * 5*2e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6*2e192b24SSimon Glass */ 7*2e192b24SSimon Glass 8*2e192b24SSimon Glass /* 9*2e192b24SSimon Glass * The "source" command allows to define "script images", i. e. files 10*2e192b24SSimon Glass * that contain command sequences that can be executed by the command 11*2e192b24SSimon Glass * interpreter. It returns the exit status of the last command 12*2e192b24SSimon Glass * executed from the script. This is very similar to running a shell 13*2e192b24SSimon Glass * script in a UNIX shell, hence the name for the command. 14*2e192b24SSimon Glass */ 15*2e192b24SSimon Glass 16*2e192b24SSimon Glass /* #define DEBUG */ 17*2e192b24SSimon Glass 18*2e192b24SSimon Glass #include <common.h> 19*2e192b24SSimon Glass #include <command.h> 20*2e192b24SSimon Glass #include <image.h> 21*2e192b24SSimon Glass #include <malloc.h> 22*2e192b24SSimon Glass #include <mapmem.h> 23*2e192b24SSimon Glass #include <asm/byteorder.h> 24*2e192b24SSimon Glass #include <asm/io.h> 25*2e192b24SSimon Glass #if defined(CONFIG_8xx) 26*2e192b24SSimon Glass #include <mpc8xx.h> 27*2e192b24SSimon Glass #endif 28*2e192b24SSimon Glass 29*2e192b24SSimon Glass int 30*2e192b24SSimon Glass source (ulong addr, const char *fit_uname) 31*2e192b24SSimon Glass { 32*2e192b24SSimon Glass ulong len; 33*2e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 34*2e192b24SSimon Glass const image_header_t *hdr; 35*2e192b24SSimon Glass #endif 36*2e192b24SSimon Glass u32 *data; 37*2e192b24SSimon Glass int verify; 38*2e192b24SSimon Glass void *buf; 39*2e192b24SSimon Glass #if defined(CONFIG_FIT) 40*2e192b24SSimon Glass const void* fit_hdr; 41*2e192b24SSimon Glass int noffset; 42*2e192b24SSimon Glass const void *fit_data; 43*2e192b24SSimon Glass size_t fit_len; 44*2e192b24SSimon Glass #endif 45*2e192b24SSimon Glass 46*2e192b24SSimon Glass verify = getenv_yesno ("verify"); 47*2e192b24SSimon Glass 48*2e192b24SSimon Glass buf = map_sysmem(addr, 0); 49*2e192b24SSimon Glass switch (genimg_get_format(buf)) { 50*2e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 51*2e192b24SSimon Glass case IMAGE_FORMAT_LEGACY: 52*2e192b24SSimon Glass hdr = buf; 53*2e192b24SSimon Glass 54*2e192b24SSimon Glass if (!image_check_magic (hdr)) { 55*2e192b24SSimon Glass puts ("Bad magic number\n"); 56*2e192b24SSimon Glass return 1; 57*2e192b24SSimon Glass } 58*2e192b24SSimon Glass 59*2e192b24SSimon Glass if (!image_check_hcrc (hdr)) { 60*2e192b24SSimon Glass puts ("Bad header crc\n"); 61*2e192b24SSimon Glass return 1; 62*2e192b24SSimon Glass } 63*2e192b24SSimon Glass 64*2e192b24SSimon Glass if (verify) { 65*2e192b24SSimon Glass if (!image_check_dcrc (hdr)) { 66*2e192b24SSimon Glass puts ("Bad data crc\n"); 67*2e192b24SSimon Glass return 1; 68*2e192b24SSimon Glass } 69*2e192b24SSimon Glass } 70*2e192b24SSimon Glass 71*2e192b24SSimon Glass if (!image_check_type (hdr, IH_TYPE_SCRIPT)) { 72*2e192b24SSimon Glass puts ("Bad image type\n"); 73*2e192b24SSimon Glass return 1; 74*2e192b24SSimon Glass } 75*2e192b24SSimon Glass 76*2e192b24SSimon Glass /* get length of script */ 77*2e192b24SSimon Glass data = (u32 *)image_get_data (hdr); 78*2e192b24SSimon Glass 79*2e192b24SSimon Glass if ((len = uimage_to_cpu (*data)) == 0) { 80*2e192b24SSimon Glass puts ("Empty Script\n"); 81*2e192b24SSimon Glass return 1; 82*2e192b24SSimon Glass } 83*2e192b24SSimon Glass 84*2e192b24SSimon Glass /* 85*2e192b24SSimon Glass * scripts are just multi-image files with one component, seek 86*2e192b24SSimon Glass * past the zero-terminated sequence of image lengths to get 87*2e192b24SSimon Glass * to the actual image data 88*2e192b24SSimon Glass */ 89*2e192b24SSimon Glass while (*data++); 90*2e192b24SSimon Glass break; 91*2e192b24SSimon Glass #endif 92*2e192b24SSimon Glass #if defined(CONFIG_FIT) 93*2e192b24SSimon Glass case IMAGE_FORMAT_FIT: 94*2e192b24SSimon Glass if (fit_uname == NULL) { 95*2e192b24SSimon Glass puts ("No FIT subimage unit name\n"); 96*2e192b24SSimon Glass return 1; 97*2e192b24SSimon Glass } 98*2e192b24SSimon Glass 99*2e192b24SSimon Glass fit_hdr = buf; 100*2e192b24SSimon Glass if (!fit_check_format (fit_hdr)) { 101*2e192b24SSimon Glass puts ("Bad FIT image format\n"); 102*2e192b24SSimon Glass return 1; 103*2e192b24SSimon Glass } 104*2e192b24SSimon Glass 105*2e192b24SSimon Glass /* get script component image node offset */ 106*2e192b24SSimon Glass noffset = fit_image_get_node (fit_hdr, fit_uname); 107*2e192b24SSimon Glass if (noffset < 0) { 108*2e192b24SSimon Glass printf ("Can't find '%s' FIT subimage\n", fit_uname); 109*2e192b24SSimon Glass return 1; 110*2e192b24SSimon Glass } 111*2e192b24SSimon Glass 112*2e192b24SSimon Glass if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) { 113*2e192b24SSimon Glass puts ("Not a image image\n"); 114*2e192b24SSimon Glass return 1; 115*2e192b24SSimon Glass } 116*2e192b24SSimon Glass 117*2e192b24SSimon Glass /* verify integrity */ 118*2e192b24SSimon Glass if (verify) { 119*2e192b24SSimon Glass if (!fit_image_verify(fit_hdr, noffset)) { 120*2e192b24SSimon Glass puts ("Bad Data Hash\n"); 121*2e192b24SSimon Glass return 1; 122*2e192b24SSimon Glass } 123*2e192b24SSimon Glass } 124*2e192b24SSimon Glass 125*2e192b24SSimon Glass /* get script subimage data address and length */ 126*2e192b24SSimon Glass if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { 127*2e192b24SSimon Glass puts ("Could not find script subimage data\n"); 128*2e192b24SSimon Glass return 1; 129*2e192b24SSimon Glass } 130*2e192b24SSimon Glass 131*2e192b24SSimon Glass data = (u32 *)fit_data; 132*2e192b24SSimon Glass len = (ulong)fit_len; 133*2e192b24SSimon Glass break; 134*2e192b24SSimon Glass #endif 135*2e192b24SSimon Glass default: 136*2e192b24SSimon Glass puts ("Wrong image format for \"source\" command\n"); 137*2e192b24SSimon Glass return 1; 138*2e192b24SSimon Glass } 139*2e192b24SSimon Glass 140*2e192b24SSimon Glass debug ("** Script length: %ld\n", len); 141*2e192b24SSimon Glass return run_command_list((char *)data, len, 0); 142*2e192b24SSimon Glass } 143*2e192b24SSimon Glass 144*2e192b24SSimon Glass /**************************************************/ 145*2e192b24SSimon Glass #if defined(CONFIG_CMD_SOURCE) 146*2e192b24SSimon Glass static int do_source(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 147*2e192b24SSimon Glass { 148*2e192b24SSimon Glass ulong addr; 149*2e192b24SSimon Glass int rcode; 150*2e192b24SSimon Glass const char *fit_uname = NULL; 151*2e192b24SSimon Glass 152*2e192b24SSimon Glass /* Find script image */ 153*2e192b24SSimon Glass if (argc < 2) { 154*2e192b24SSimon Glass addr = CONFIG_SYS_LOAD_ADDR; 155*2e192b24SSimon Glass debug ("* source: default load address = 0x%08lx\n", addr); 156*2e192b24SSimon Glass #if defined(CONFIG_FIT) 157*2e192b24SSimon Glass } else if (fit_parse_subimage (argv[1], load_addr, &addr, &fit_uname)) { 158*2e192b24SSimon Glass debug ("* source: subimage '%s' from FIT image at 0x%08lx\n", 159*2e192b24SSimon Glass fit_uname, addr); 160*2e192b24SSimon Glass #endif 161*2e192b24SSimon Glass } else { 162*2e192b24SSimon Glass addr = simple_strtoul(argv[1], NULL, 16); 163*2e192b24SSimon Glass debug ("* source: cmdline image address = 0x%08lx\n", addr); 164*2e192b24SSimon Glass } 165*2e192b24SSimon Glass 166*2e192b24SSimon Glass printf ("## Executing script at %08lx\n", addr); 167*2e192b24SSimon Glass rcode = source (addr, fit_uname); 168*2e192b24SSimon Glass return rcode; 169*2e192b24SSimon Glass } 170*2e192b24SSimon Glass 171*2e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP 172*2e192b24SSimon Glass static char source_help_text[] = 173*2e192b24SSimon Glass "[addr]\n" 174*2e192b24SSimon Glass "\t- run script starting at addr\n" 175*2e192b24SSimon Glass "\t- A valid image header must be present" 176*2e192b24SSimon Glass #if defined(CONFIG_FIT) 177*2e192b24SSimon Glass "\n" 178*2e192b24SSimon Glass "For FIT format uImage addr must include subimage\n" 179*2e192b24SSimon Glass "unit name in the form of addr:<subimg_uname>" 180*2e192b24SSimon Glass #endif 181*2e192b24SSimon Glass ""; 182*2e192b24SSimon Glass #endif 183*2e192b24SSimon Glass 184*2e192b24SSimon Glass U_BOOT_CMD( 185*2e192b24SSimon Glass source, 2, 0, do_source, 186*2e192b24SSimon Glass "run script from memory", source_help_text 187*2e192b24SSimon Glass ); 188*2e192b24SSimon Glass #endif 189