16aff3115Swdenk /* 2bc11756dSGrant Erickson * (C) Copyright 2000-2008 36aff3115Swdenk * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 46aff3115Swdenk * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 66aff3115Swdenk */ 76aff3115Swdenk 86aff3115Swdenk /* 93bac3513Swdenk * Command line user interface to firmware (=U-Boot) environment. 106aff3115Swdenk * 116aff3115Swdenk * Implements: 12a8a752c0SMarek Vasut * fw_printenv [ -a key ] [[ -n name ] | [ name ... ]] 13bc11756dSGrant Erickson * - prints the value of a single environment variable 14bc11756dSGrant Erickson * "name", the ``name=value'' pairs of one or more 15bc11756dSGrant Erickson * environment variables "name", or the whole 16bc11756dSGrant Erickson * environment if no names are specified. 17a8a752c0SMarek Vasut * fw_setenv [ -a key ] name [ value ... ] 186aff3115Swdenk * - If a name without any values is given, the variable 196aff3115Swdenk * with this name is deleted from the environment; 206aff3115Swdenk * otherwise, all "value" arguments are concatenated, 21bc11756dSGrant Erickson * separated by single blank characters, and the 226aff3115Swdenk * resulting string is assigned to the environment 236aff3115Swdenk * variable "name" 24a8a752c0SMarek Vasut * 25a8a752c0SMarek Vasut * If '-a key' is specified, the env block is encrypted with AES 128 CBC. 26a8a752c0SMarek Vasut * The 'key' argument is in the format of 32 hexadecimal numbers (16 bytes 27a8a752c0SMarek Vasut * of AES key), eg. '-a aabbccddeeff00112233445566778899'. 286aff3115Swdenk */ 296aff3115Swdenk 30e4a223f0SJoe Hershberger #include <fcntl.h> 31e4a223f0SJoe Hershberger #include <getopt.h> 326aff3115Swdenk #include <stdio.h> 336aff3115Swdenk #include <string.h> 346aff3115Swdenk #include <stdlib.h> 35e4a223f0SJoe Hershberger #include <sys/file.h> 36e4a223f0SJoe Hershberger #include <unistd.h> 379d80b49aSStefano Babic #include "fw_env_private.h" 386aff3115Swdenk #include "fw_env.h" 396aff3115Swdenk 406aff3115Swdenk #define CMD_PRINTENV "fw_printenv" 416aff3115Swdenk #define CMD_SETENV "fw_setenv" 42b92ae3afSAndreas Fenkart static int do_printenv; 436aff3115Swdenk 44bd7b26f8SStefano Babic static struct option long_options[] = { 45b92ae3afSAndreas Fenkart {"aes", required_argument, NULL, 'a'}, 46b92ae3afSAndreas Fenkart {"config", required_argument, NULL, 'c'}, 47bd7b26f8SStefano Babic {"help", no_argument, NULL, 'h'}, 48b92ae3afSAndreas Fenkart {"script", required_argument, NULL, 's'}, 49b92ae3afSAndreas Fenkart {"noheader", required_argument, NULL, 'n'}, 50d40dbfb7SB, Ravi {"lock", required_argument, NULL, 'l'}, 51bd7b26f8SStefano Babic {NULL, 0, NULL, 0} 52bd7b26f8SStefano Babic }; 53bd7b26f8SStefano Babic 5481974f44SAndreas Fenkart static struct env_opts env_opts; 5581974f44SAndreas Fenkart 5681974f44SAndreas Fenkart /* setenv options */ 5781974f44SAndreas Fenkart static int noheader; 5881974f44SAndreas Fenkart 5981974f44SAndreas Fenkart /* getenv options */ 6081974f44SAndreas Fenkart static char *script_file; 6181974f44SAndreas Fenkart 62b92ae3afSAndreas Fenkart void usage_printenv(void) 63bd7b26f8SStefano Babic { 64bd7b26f8SStefano Babic 65b92ae3afSAndreas Fenkart fprintf(stderr, 66b92ae3afSAndreas Fenkart "Usage: fw_printenv [OPTIONS]... [VARIABLE]...\n" 67b92ae3afSAndreas Fenkart "Print variables from U-Boot environment\n" 68b92ae3afSAndreas Fenkart "\n" 69b92ae3afSAndreas Fenkart " -h, --help print this help.\n" 70b92ae3afSAndreas Fenkart #ifdef CONFIG_ENV_AES 71b92ae3afSAndreas Fenkart " -a, --aes aes key to access environment\n" 729884f44cSMichael Heimpold #endif 73b92ae3afSAndreas Fenkart #ifdef CONFIG_FILE 74b92ae3afSAndreas Fenkart " -c, --config configuration file, default:" CONFIG_FILE "\n" 75b92ae3afSAndreas Fenkart #endif 76b92ae3afSAndreas Fenkart " -n, --noheader do not repeat variable name in output\n" 77d40dbfb7SB, Ravi " -l, --lock lock node, default:/var/lock\n" 78b92ae3afSAndreas Fenkart "\n"); 79b92ae3afSAndreas Fenkart } 80b92ae3afSAndreas Fenkart 81*382bee57SSimon Glass void usage_env_set(void) 82b92ae3afSAndreas Fenkart { 83b92ae3afSAndreas Fenkart fprintf(stderr, 84b92ae3afSAndreas Fenkart "Usage: fw_setenv [OPTIONS]... [VARIABLE]...\n" 85b92ae3afSAndreas Fenkart "Modify variables in U-Boot environment\n" 86bd7b26f8SStefano Babic "\n" 87b92ae3afSAndreas Fenkart " -h, --help print this help.\n" 88b92ae3afSAndreas Fenkart #ifdef CONFIG_ENV_AES 89b92ae3afSAndreas Fenkart " -a, --aes aes key to access environment\n" 90b92ae3afSAndreas Fenkart #endif 91b92ae3afSAndreas Fenkart #ifdef CONFIG_FILE 92b92ae3afSAndreas Fenkart " -c, --config configuration file, default:" CONFIG_FILE "\n" 93b92ae3afSAndreas Fenkart #endif 94d40dbfb7SB, Ravi " -l, --lock lock node, default:/var/lock\n" 95b92ae3afSAndreas Fenkart " -s, --script batch mode to minimize writes\n" 96bd7b26f8SStefano Babic "\n" 97b92ae3afSAndreas Fenkart "Examples:\n" 98b92ae3afSAndreas Fenkart " fw_setenv foo bar set variable foo equal bar\n" 99b92ae3afSAndreas Fenkart " fw_setenv foo clear variable foo\n" 100b92ae3afSAndreas Fenkart " fw_setenv --script file run batch script\n" 101b92ae3afSAndreas Fenkart "\n" 102b92ae3afSAndreas Fenkart "Script Syntax:\n" 103b92ae3afSAndreas Fenkart " key [space] value\n" 1040e280659SVagrant Cascadian " lines starting with '#' are treated as comment\n" 105b92ae3afSAndreas Fenkart "\n" 106b92ae3afSAndreas Fenkart " A variable without value will be deleted. Any number of spaces are\n" 107b92ae3afSAndreas Fenkart " allowed between key and value. Space inside of the value is treated\n" 108b92ae3afSAndreas Fenkart " as part of the value itself.\n" 109b92ae3afSAndreas Fenkart "\n" 110b92ae3afSAndreas Fenkart "Script Example:\n" 111b92ae3afSAndreas Fenkart " netdev eth0\n" 112b92ae3afSAndreas Fenkart " kernel_addr 400000\n" 113b92ae3afSAndreas Fenkart " foo empty empty empty empty empty empty\n" 114b92ae3afSAndreas Fenkart " bar\n" 115b92ae3afSAndreas Fenkart "\n"); 116bd7b26f8SStefano Babic } 117bd7b26f8SStefano Babic 118af93e3d8SAndreas Fenkart static void parse_common_args(int argc, char *argv[]) 1196aff3115Swdenk { 120bd7b26f8SStefano Babic int c; 1216aff3115Swdenk 122371ee137SAndreas Fenkart #ifdef CONFIG_FILE 12381974f44SAndreas Fenkart env_opts.config_file = CONFIG_FILE; 124371ee137SAndreas Fenkart #endif 125371ee137SAndreas Fenkart 126d40dbfb7SB, Ravi while ((c = getopt_long(argc, argv, ":a:c:l:h", long_options, NULL)) != 127af93e3d8SAndreas Fenkart EOF) { 128bd7b26f8SStefano Babic switch (c) { 129a8a752c0SMarek Vasut case 'a': 13081974f44SAndreas Fenkart if (parse_aes_key(optarg, env_opts.aes_key)) { 131371ee137SAndreas Fenkart fprintf(stderr, "AES key parse error\n"); 132af93e3d8SAndreas Fenkart exit(EXIT_FAILURE); 133371ee137SAndreas Fenkart } 13481974f44SAndreas Fenkart env_opts.aes_flag = 1; 135a8a752c0SMarek Vasut break; 136371ee137SAndreas Fenkart #ifdef CONFIG_FILE 1379884f44cSMichael Heimpold case 'c': 13881974f44SAndreas Fenkart env_opts.config_file = optarg; 1399884f44cSMichael Heimpold break; 140371ee137SAndreas Fenkart #endif 141d40dbfb7SB, Ravi case 'l': 142d40dbfb7SB, Ravi env_opts.lockname = optarg; 143d40dbfb7SB, Ravi break; 14407ce9440SAndreas Fenkart case 'h': 145*382bee57SSimon Glass do_printenv ? usage_printenv() : usage_env_set(); 14607ce9440SAndreas Fenkart exit(EXIT_SUCCESS); 14707ce9440SAndreas Fenkart break; 148af93e3d8SAndreas Fenkart default: 149af93e3d8SAndreas Fenkart /* ignore unknown options */ 150af93e3d8SAndreas Fenkart break; 151af93e3d8SAndreas Fenkart } 152af93e3d8SAndreas Fenkart } 153af93e3d8SAndreas Fenkart 154af93e3d8SAndreas Fenkart /* Reset getopt for the next pass. */ 155af93e3d8SAndreas Fenkart opterr = 1; 156af93e3d8SAndreas Fenkart optind = 1; 157af93e3d8SAndreas Fenkart } 158af93e3d8SAndreas Fenkart 159af93e3d8SAndreas Fenkart int parse_printenv_args(int argc, char *argv[]) 160af93e3d8SAndreas Fenkart { 161af93e3d8SAndreas Fenkart int c; 162af93e3d8SAndreas Fenkart 163af93e3d8SAndreas Fenkart parse_common_args(argc, argv); 164af93e3d8SAndreas Fenkart 165d40dbfb7SB, Ravi while ((c = getopt_long(argc, argv, "a:c:ns:l:h", long_options, NULL)) 166d40dbfb7SB, Ravi != EOF) { 167af93e3d8SAndreas Fenkart switch (c) { 168af93e3d8SAndreas Fenkart case 'n': 16981974f44SAndreas Fenkart noheader = 1; 170af93e3d8SAndreas Fenkart break; 171af93e3d8SAndreas Fenkart case 'a': 172af93e3d8SAndreas Fenkart case 'c': 173af93e3d8SAndreas Fenkart case 'h': 174d40dbfb7SB, Ravi case 'l': 175af93e3d8SAndreas Fenkart /* ignore common options */ 176af93e3d8SAndreas Fenkart break; 17707ce9440SAndreas Fenkart default: /* '?' */ 178b92ae3afSAndreas Fenkart usage_printenv(); 17907ce9440SAndreas Fenkart exit(EXIT_FAILURE); 18007ce9440SAndreas Fenkart break; 18107ce9440SAndreas Fenkart } 18207ce9440SAndreas Fenkart } 18307ce9440SAndreas Fenkart return 0; 18407ce9440SAndreas Fenkart } 18507ce9440SAndreas Fenkart 18607ce9440SAndreas Fenkart int parse_setenv_args(int argc, char *argv[]) 18707ce9440SAndreas Fenkart { 18807ce9440SAndreas Fenkart int c; 18907ce9440SAndreas Fenkart 190af93e3d8SAndreas Fenkart parse_common_args(argc, argv); 191371ee137SAndreas Fenkart 192d40dbfb7SB, Ravi while ((c = getopt_long(argc, argv, "a:c:ns:l:h", long_options, NULL)) 193d40dbfb7SB, Ravi != EOF) { 19407ce9440SAndreas Fenkart switch (c) { 195bd7b26f8SStefano Babic case 's': 19681974f44SAndreas Fenkart script_file = optarg; 197bd7b26f8SStefano Babic break; 198af93e3d8SAndreas Fenkart case 'a': 199af93e3d8SAndreas Fenkart case 'c': 200bd7b26f8SStefano Babic case 'h': 201d40dbfb7SB, Ravi case 'l': 202af93e3d8SAndreas Fenkart /* ignore common options */ 20307ce9440SAndreas Fenkart break; 20429ccd7c3SDaniel Hobi default: /* '?' */ 205*382bee57SSimon Glass usage_env_set(); 20607ce9440SAndreas Fenkart exit(EXIT_FAILURE); 20707ce9440SAndreas Fenkart break; 208bd7b26f8SStefano Babic } 209bd7b26f8SStefano Babic } 21007ce9440SAndreas Fenkart return 0; 21107ce9440SAndreas Fenkart } 21207ce9440SAndreas Fenkart 21307ce9440SAndreas Fenkart int main(int argc, char *argv[]) 21407ce9440SAndreas Fenkart { 215d40dbfb7SB, Ravi char *lockname = "/var/lock/" CMD_PRINTENV ".lock"; 21607ce9440SAndreas Fenkart int lockfd = -1; 21707ce9440SAndreas Fenkart int retval = EXIT_SUCCESS; 218b92ae3afSAndreas Fenkart char *_cmdname; 21907ce9440SAndreas Fenkart 220b92ae3afSAndreas Fenkart _cmdname = *argv; 221b92ae3afSAndreas Fenkart if (strrchr(_cmdname, '/') != NULL) 222b92ae3afSAndreas Fenkart _cmdname = strrchr(_cmdname, '/') + 1; 22307ce9440SAndreas Fenkart 224b92ae3afSAndreas Fenkart if (strcmp(_cmdname, CMD_PRINTENV) == 0) { 225b92ae3afSAndreas Fenkart do_printenv = 1; 226b92ae3afSAndreas Fenkart } else if (strcmp(_cmdname, CMD_SETENV) == 0) { 227b92ae3afSAndreas Fenkart do_printenv = 0; 22807ce9440SAndreas Fenkart } else { 22907ce9440SAndreas Fenkart fprintf(stderr, 23007ce9440SAndreas Fenkart "Identity crisis - may be called as `%s' or as `%s' but not as `%s'\n", 231b92ae3afSAndreas Fenkart CMD_PRINTENV, CMD_SETENV, _cmdname); 232b92ae3afSAndreas Fenkart exit(EXIT_FAILURE); 233b92ae3afSAndreas Fenkart } 234b92ae3afSAndreas Fenkart 235b92ae3afSAndreas Fenkart if (do_printenv) { 236b92ae3afSAndreas Fenkart if (parse_printenv_args(argc, argv)) 237b92ae3afSAndreas Fenkart exit(EXIT_FAILURE); 238b92ae3afSAndreas Fenkart } else { 239b92ae3afSAndreas Fenkart if (parse_setenv_args(argc, argv)) 24007ce9440SAndreas Fenkart exit(EXIT_FAILURE); 24107ce9440SAndreas Fenkart } 24207ce9440SAndreas Fenkart 2431ce68697SAndreas Fenkart /* shift parsed flags, jump to non-option arguments */ 2441ce68697SAndreas Fenkart argc -= optind; 2451ce68697SAndreas Fenkart argv += optind; 2461ce68697SAndreas Fenkart 247d40dbfb7SB, Ravi if (env_opts.lockname) { 248d40dbfb7SB, Ravi lockname = malloc(sizeof(env_opts.lockname) + 249d40dbfb7SB, Ravi sizeof(CMD_PRINTENV) + 10); 250d40dbfb7SB, Ravi if (!lockname) { 251d40dbfb7SB, Ravi fprintf(stderr, "Unable allocate memory"); 252d40dbfb7SB, Ravi exit(EXIT_FAILURE); 253d40dbfb7SB, Ravi } 254d40dbfb7SB, Ravi 255d40dbfb7SB, Ravi sprintf(lockname, "%s/%s.lock", 256d40dbfb7SB, Ravi env_opts.lockname, CMD_PRINTENV); 257d40dbfb7SB, Ravi } 258d40dbfb7SB, Ravi 25907ce9440SAndreas Fenkart lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666); 26007ce9440SAndreas Fenkart if (-1 == lockfd) { 26107ce9440SAndreas Fenkart fprintf(stderr, "Error opening lock file %s\n", lockname); 26207ce9440SAndreas Fenkart return EXIT_FAILURE; 26307ce9440SAndreas Fenkart } 26407ce9440SAndreas Fenkart 26507ce9440SAndreas Fenkart if (-1 == flock(lockfd, LOCK_EX)) { 26607ce9440SAndreas Fenkart fprintf(stderr, "Error locking file %s\n", lockname); 26707ce9440SAndreas Fenkart close(lockfd); 26807ce9440SAndreas Fenkart return EXIT_FAILURE; 26907ce9440SAndreas Fenkart } 270bd7b26f8SStefano Babic 271b92ae3afSAndreas Fenkart if (do_printenv) { 27281974f44SAndreas Fenkart if (fw_printenv(argc, argv, noheader, &env_opts) != 0) 273e4a223f0SJoe Hershberger retval = EXIT_FAILURE; 274b92ae3afSAndreas Fenkart } else { 27581974f44SAndreas Fenkart if (!script_file) { 276*382bee57SSimon Glass if (fw_env_set(argc, argv, &env_opts) != 0) 277e4a223f0SJoe Hershberger retval = EXIT_FAILURE; 278bd7b26f8SStefano Babic } else { 27981974f44SAndreas Fenkart if (fw_parse_script(script_file, &env_opts) != 0) 280e4a223f0SJoe Hershberger retval = EXIT_FAILURE; 281bd7b26f8SStefano Babic } 282e4a223f0SJoe Hershberger } 283e4a223f0SJoe Hershberger 284d40dbfb7SB, Ravi if (env_opts.lockname) 285d40dbfb7SB, Ravi free(lockname); 286d40dbfb7SB, Ravi 287e4a223f0SJoe Hershberger flock(lockfd, LOCK_UN); 288e4a223f0SJoe Hershberger close(lockfd); 289e4a223f0SJoe Hershberger return retval; 2906aff3115Swdenk } 291