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> 376aff3115Swdenk #include "fw_env.h" 386aff3115Swdenk 396aff3115Swdenk #define CMD_PRINTENV "fw_printenv" 406aff3115Swdenk #define CMD_SETENV "fw_setenv" 416aff3115Swdenk 42bd7b26f8SStefano Babic static struct option long_options[] = { 43bd7b26f8SStefano Babic {"script", required_argument, NULL, 's'}, 44bd7b26f8SStefano Babic {"help", no_argument, NULL, 'h'}, 45bd7b26f8SStefano Babic {NULL, 0, NULL, 0} 46bd7b26f8SStefano Babic }; 47bd7b26f8SStefano Babic 48371ee137SAndreas Fenkart struct common_args common_args; 4907ce9440SAndreas Fenkart struct printenv_args printenv_args; 5007ce9440SAndreas Fenkart struct setenv_args setenv_args; 5107ce9440SAndreas Fenkart 52bd7b26f8SStefano Babic void usage(void) 53bd7b26f8SStefano Babic { 54bd7b26f8SStefano Babic 55bd7b26f8SStefano Babic fprintf(stderr, "fw_printenv/fw_setenv, " 56bd7b26f8SStefano Babic "a command line interface to U-Boot environment\n\n" 579884f44cSMichael Heimpold #ifndef CONFIG_FILE 58a8a752c0SMarek Vasut "usage:\tfw_printenv [-a key] [-n] [variable name]\n" 59a8a752c0SMarek Vasut "\tfw_setenv [-a key] [variable name] [variable value]\n" 609884f44cSMichael Heimpold #else 619884f44cSMichael Heimpold "usage:\tfw_printenv [-c /my/fw_env.config] [-a key] [-n] [variable name]\n" 629884f44cSMichael Heimpold "\tfw_setenv [-c /my/fw_env.config] [-a key] [variable name] [variable value]\n" 639884f44cSMichael Heimpold #endif 64bd7b26f8SStefano Babic "\tfw_setenv -s [ file ]\n" 65bd7b26f8SStefano Babic "\tfw_setenv -s - < [ file ]\n\n" 66bd7b26f8SStefano Babic "The file passed as argument contains only pairs " 67bd7b26f8SStefano Babic "name / value\n" 68bd7b26f8SStefano Babic "Example:\n" 69bd7b26f8SStefano Babic "# Any line starting with # is treated as comment\n" 70bd7b26f8SStefano Babic "\n" 71bd7b26f8SStefano Babic "\t netdev eth0\n" 72bd7b26f8SStefano Babic "\t kernel_addr 400000\n" 73bd7b26f8SStefano Babic "\t var1\n" 74bd7b26f8SStefano Babic "\t var2 The quick brown fox jumps over the " 75bd7b26f8SStefano Babic "lazy dog\n" 76bd7b26f8SStefano Babic "\n" 77bd7b26f8SStefano Babic "A variable without value will be dropped. It is possible\n" 78bd7b26f8SStefano Babic "to put any number of spaces between the fields, but any\n" 79bd7b26f8SStefano Babic "space inside the value is treated as part of the value " 80bd7b26f8SStefano Babic "itself.\n\n" 81bd7b26f8SStefano Babic ); 82bd7b26f8SStefano Babic } 83bd7b26f8SStefano Babic 8407ce9440SAndreas Fenkart int parse_printenv_args(int argc, char *argv[]) 856aff3115Swdenk { 86bd7b26f8SStefano Babic int c; 876aff3115Swdenk 88371ee137SAndreas Fenkart #ifdef CONFIG_FILE 89371ee137SAndreas Fenkart common_args.config_file = CONFIG_FILE; 90371ee137SAndreas Fenkart #endif 91371ee137SAndreas Fenkart 929884f44cSMichael Heimpold while ((c = getopt_long (argc, argv, "a:c:ns:h", 93bd7b26f8SStefano Babic long_options, NULL)) != EOF) { 94bd7b26f8SStefano Babic switch (c) { 95a8a752c0SMarek Vasut case 'a': 96371ee137SAndreas Fenkart if (parse_aes_key(optarg, common_args.aes_key)) { 97371ee137SAndreas Fenkart fprintf(stderr, "AES key parse error\n"); 98371ee137SAndreas Fenkart return EXIT_FAILURE; 99371ee137SAndreas Fenkart } 100371ee137SAndreas Fenkart common_args.aes_flag = 1; 101a8a752c0SMarek Vasut break; 102371ee137SAndreas Fenkart #ifdef CONFIG_FILE 1039884f44cSMichael Heimpold case 'c': 104371ee137SAndreas Fenkart common_args.config_file = optarg; 1059884f44cSMichael Heimpold break; 106371ee137SAndreas Fenkart #endif 107122bc088SDaniel Hobi case 'n': 108371ee137SAndreas Fenkart printenv_args.name_suppress = 1; 109122bc088SDaniel Hobi break; 11007ce9440SAndreas Fenkart case 'h': 11107ce9440SAndreas Fenkart usage(); 11207ce9440SAndreas Fenkart exit(EXIT_SUCCESS); 11307ce9440SAndreas Fenkart break; 11407ce9440SAndreas Fenkart default: /* '?' */ 11507ce9440SAndreas Fenkart usage(); 11607ce9440SAndreas Fenkart exit(EXIT_FAILURE); 11707ce9440SAndreas Fenkart break; 11807ce9440SAndreas Fenkart } 11907ce9440SAndreas Fenkart } 12007ce9440SAndreas Fenkart return 0; 12107ce9440SAndreas Fenkart } 12207ce9440SAndreas Fenkart 12307ce9440SAndreas Fenkart int parse_setenv_args(int argc, char *argv[]) 12407ce9440SAndreas Fenkart { 12507ce9440SAndreas Fenkart int c; 12607ce9440SAndreas Fenkart 127371ee137SAndreas Fenkart #ifdef CONFIG_FILE 128371ee137SAndreas Fenkart common_args.config_file = CONFIG_FILE; 129371ee137SAndreas Fenkart #endif 130371ee137SAndreas Fenkart 13107ce9440SAndreas Fenkart while ((c = getopt_long (argc, argv, "a:c:ns:h", 13207ce9440SAndreas Fenkart long_options, NULL)) != EOF) { 13307ce9440SAndreas Fenkart switch (c) { 13407ce9440SAndreas Fenkart case 'a': 135371ee137SAndreas Fenkart if (parse_aes_key(optarg, common_args.aes_key)) { 136371ee137SAndreas Fenkart fprintf(stderr, "AES key parse error\n"); 137371ee137SAndreas Fenkart return EXIT_FAILURE; 138371ee137SAndreas Fenkart } 139371ee137SAndreas Fenkart common_args.aes_flag = 1; 14007ce9440SAndreas Fenkart break; 141371ee137SAndreas Fenkart #ifdef CONFIG_FILE 14207ce9440SAndreas Fenkart case 'c': 143371ee137SAndreas Fenkart common_args.config_file = optarg; 14407ce9440SAndreas Fenkart break; 145371ee137SAndreas Fenkart #endif 146bd7b26f8SStefano Babic case 's': 14707ce9440SAndreas Fenkart setenv_args.script_file = optarg; 148bd7b26f8SStefano Babic break; 149bd7b26f8SStefano Babic case 'h': 150bd7b26f8SStefano Babic usage(); 15107ce9440SAndreas Fenkart exit(EXIT_SUCCESS); 15207ce9440SAndreas Fenkart break; 15329ccd7c3SDaniel Hobi default: /* '?' */ 15407ce9440SAndreas Fenkart usage(); 15507ce9440SAndreas Fenkart exit(EXIT_FAILURE); 15607ce9440SAndreas Fenkart break; 157bd7b26f8SStefano Babic } 158bd7b26f8SStefano Babic } 15907ce9440SAndreas Fenkart return 0; 16007ce9440SAndreas Fenkart } 16107ce9440SAndreas Fenkart 16207ce9440SAndreas Fenkart int main(int argc, char *argv[]) 16307ce9440SAndreas Fenkart { 16407ce9440SAndreas Fenkart char *cmdname = *argv; 16507ce9440SAndreas Fenkart const char *lockname = "/var/lock/" CMD_PRINTENV ".lock"; 16607ce9440SAndreas Fenkart int lockfd = -1; 16707ce9440SAndreas Fenkart int retval = EXIT_SUCCESS; 16807ce9440SAndreas Fenkart 16907ce9440SAndreas Fenkart if (strrchr(cmdname, '/') != NULL) 17007ce9440SAndreas Fenkart cmdname = strrchr(cmdname, '/') + 1; 17107ce9440SAndreas Fenkart 17207ce9440SAndreas Fenkart if (strcmp(cmdname, CMD_PRINTENV) == 0) { 17307ce9440SAndreas Fenkart if (parse_printenv_args(argc, argv)) 17407ce9440SAndreas Fenkart exit(EXIT_FAILURE); 17507ce9440SAndreas Fenkart } else if (strcmp(cmdname, CMD_SETENV) == 0) { 17607ce9440SAndreas Fenkart if (parse_setenv_args(argc, argv)) 17707ce9440SAndreas Fenkart exit(EXIT_FAILURE); 17807ce9440SAndreas Fenkart } else { 17907ce9440SAndreas Fenkart fprintf(stderr, 18007ce9440SAndreas Fenkart "Identity crisis - may be called as `%s' or as `%s' but not as `%s'\n", 18107ce9440SAndreas Fenkart CMD_PRINTENV, CMD_SETENV, cmdname); 18207ce9440SAndreas Fenkart exit(EXIT_FAILURE); 18307ce9440SAndreas Fenkart } 18407ce9440SAndreas Fenkart 185*1ce68697SAndreas Fenkart /* shift parsed flags, jump to non-option arguments */ 186*1ce68697SAndreas Fenkart argc -= optind; 187*1ce68697SAndreas Fenkart argv += optind; 188*1ce68697SAndreas Fenkart 18907ce9440SAndreas Fenkart lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666); 19007ce9440SAndreas Fenkart if (-1 == lockfd) { 19107ce9440SAndreas Fenkart fprintf(stderr, "Error opening lock file %s\n", lockname); 19207ce9440SAndreas Fenkart return EXIT_FAILURE; 19307ce9440SAndreas Fenkart } 19407ce9440SAndreas Fenkart 19507ce9440SAndreas Fenkart if (-1 == flock(lockfd, LOCK_EX)) { 19607ce9440SAndreas Fenkart fprintf(stderr, "Error locking file %s\n", lockname); 19707ce9440SAndreas Fenkart close(lockfd); 19807ce9440SAndreas Fenkart return EXIT_FAILURE; 19907ce9440SAndreas Fenkart } 200bd7b26f8SStefano Babic 2016aff3115Swdenk if (strcmp(cmdname, CMD_PRINTENV) == 0) { 202bc11756dSGrant Erickson if (fw_printenv(argc, argv) != 0) 203e4a223f0SJoe Hershberger retval = EXIT_FAILURE; 2046aff3115Swdenk } else if (strcmp(cmdname, CMD_SETENV) == 0) { 20507ce9440SAndreas Fenkart if (!setenv_args.script_file) { 2066aff3115Swdenk if (fw_setenv(argc, argv) != 0) 207e4a223f0SJoe Hershberger retval = EXIT_FAILURE; 208bd7b26f8SStefano Babic } else { 20907ce9440SAndreas Fenkart if (fw_parse_script(setenv_args.script_file) != 0) 210e4a223f0SJoe Hershberger retval = EXIT_FAILURE; 211bd7b26f8SStefano Babic } 212e4a223f0SJoe Hershberger } 213e4a223f0SJoe Hershberger 214e4a223f0SJoe Hershberger flock(lockfd, LOCK_UN); 215e4a223f0SJoe Hershberger close(lockfd); 216e4a223f0SJoe Hershberger return retval; 2176aff3115Swdenk } 218