meta-digi: add 'ubootenv' tool
https://jira.digi.com/browse/DEL-286 Signed-off-by: Javier Viguera <javier.viguera@digi.com>
This commit is contained in:
parent
df80921748
commit
26d98d13ff
|
|
@ -0,0 +1,32 @@
|
||||||
|
SUMMARY = "Digi's ubootenv tool"
|
||||||
|
SECTION = "base"
|
||||||
|
LICENSE = "GPL-2.0"
|
||||||
|
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
|
||||||
|
|
||||||
|
PR = "r0"
|
||||||
|
|
||||||
|
DEPENDS = "libdigi nvram"
|
||||||
|
|
||||||
|
SRC_URI = " \
|
||||||
|
file://env_funcs.c \
|
||||||
|
file://env_funcs.h \
|
||||||
|
file://environment.h \
|
||||||
|
file://main_env.c \
|
||||||
|
"
|
||||||
|
|
||||||
|
S = "${WORKDIR}"
|
||||||
|
|
||||||
|
GIT_SHA1 = "$(cd ${THISDIR} && git rev-parse --short HEAD)"
|
||||||
|
|
||||||
|
CFLAGS += "-Wall -DLINUX -DGIT_SHA1=\"${GIT_SHA1}\" -I${STAGING_INCDIR}/libdigi"
|
||||||
|
|
||||||
|
do_compile() {
|
||||||
|
${CC} ${CFLAGS} -o ubootenv main_env.c env_funcs.c -lnvram -ldigi
|
||||||
|
}
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
mkdir -p ${D}${base_sbindir}
|
||||||
|
install -m 0755 ubootenv ${D}${base_sbindir}/
|
||||||
|
}
|
||||||
|
|
||||||
|
PACKAGE_ARCH = "${MACHINE_ARCH}"
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
/*
|
||||||
|
* env_funcs.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2013 by Digi International Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Description: Function prototypes for all the flavors of the NVRAM tool
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "env_funcs.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: get_var_value
|
||||||
|
* Return: NULL on failure/ pointer where var value starts on succes
|
||||||
|
* Description: Checks if the variable name is contained on the string and
|
||||||
|
* returns a pointer where the variable value starts.
|
||||||
|
*/
|
||||||
|
char *get_var_value(const char *from, const char *var_name, char sep)
|
||||||
|
{
|
||||||
|
char *separator;
|
||||||
|
char *start;
|
||||||
|
|
||||||
|
if (((separator = strchr(from, sep)) != NULL) &&
|
||||||
|
((start = strstr(from, var_name)) != NULL)) {
|
||||||
|
if (start < separator)
|
||||||
|
return (++separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: get_var_name
|
||||||
|
* Return: 1 on success, 0 otherwise
|
||||||
|
* Description: Retrieves the var name from a var string
|
||||||
|
*/
|
||||||
|
int get_var_name(const char *from, char *var_name, char sep)
|
||||||
|
{
|
||||||
|
char *separator;
|
||||||
|
|
||||||
|
if ((separator = strchr(from, sep)) != NULL) {
|
||||||
|
while (from < separator)
|
||||||
|
*var_name++ = *from++;
|
||||||
|
*var_name = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: get_next_env_string
|
||||||
|
* Return: the string to the next environment variable in UBOOT or
|
||||||
|
* NULL on failure
|
||||||
|
* Description: returns the addr of the next string in a data structure
|
||||||
|
* <string>\0<string>\0\0
|
||||||
|
* It does an offset calculation to check for overflow.
|
||||||
|
*/
|
||||||
|
char *get_next_env_string(char *from, char *till)
|
||||||
|
{
|
||||||
|
if (*from == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (from < till && *from)
|
||||||
|
from++;
|
||||||
|
|
||||||
|
if (from == till && *from)
|
||||||
|
return NULL; // Indicate string to long
|
||||||
|
|
||||||
|
return (++from);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: get_var_addr
|
||||||
|
* Return: the pointer to the address string or NULL if not found.
|
||||||
|
* Description: Returns the addr of the variable in a data structure
|
||||||
|
* <string>\0<string>\0\0
|
||||||
|
* It does an offset calculation to check for overflow.
|
||||||
|
*/
|
||||||
|
char *get_var_addr(char *from, char *till, char *var_name)
|
||||||
|
{
|
||||||
|
char *data = from;
|
||||||
|
char *var_addr;
|
||||||
|
char var_name_temp[ENV_MAX_VAR_NAME_LEN + 1];
|
||||||
|
|
||||||
|
sprintf(var_name_temp, "%s%s", var_name, "=");
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (*data && data < till) {
|
||||||
|
if ((var_addr = strstr(data, var_name_temp)) != NULL
|
||||||
|
&& (var_addr == data))
|
||||||
|
return var_addr < till ? var_addr : NULL;
|
||||||
|
}
|
||||||
|
} while ((data = get_next_env_string(data, till)) != NULL);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: get_end_mark
|
||||||
|
* Description:
|
||||||
|
*/
|
||||||
|
char *get_end_mark(char *from, char *till)
|
||||||
|
{
|
||||||
|
while (from < till) {
|
||||||
|
while (*from)
|
||||||
|
from++;
|
||||||
|
if (from >= till)
|
||||||
|
return NULL;
|
||||||
|
if (*(++from) == 0)
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: remove_var
|
||||||
|
* Return: 1 on success, 0 otherwise
|
||||||
|
* Description: Remove environment variables
|
||||||
|
*/
|
||||||
|
int remove_var(char *from, char *till, char *var_name)
|
||||||
|
{
|
||||||
|
char *var_addr;
|
||||||
|
char *env_end;
|
||||||
|
char *var_end;
|
||||||
|
|
||||||
|
/* Check if variable already exists */
|
||||||
|
if ((var_addr = get_var_addr(from, till, var_name)) != NULL) {
|
||||||
|
if ((env_end = get_end_mark(var_addr, till)) != NULL) {
|
||||||
|
if ((var_end = get_next_env_string(var_addr, till)) != NULL) {
|
||||||
|
while (var_end <= env_end)
|
||||||
|
*var_addr++ = *var_end++;
|
||||||
|
while (var_addr <= env_end)
|
||||||
|
*var_addr++ = 0; /* Just to have a clean environment :-) */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: add_var
|
||||||
|
* Return: 1 on success, 0 otherwise
|
||||||
|
* Description: Add a new environment variable
|
||||||
|
*/
|
||||||
|
int add_var(char *from, char *till, char *var_str)
|
||||||
|
{
|
||||||
|
char *var_addr;
|
||||||
|
char var_name[ENV_MAX_VAR_NAME_LEN];
|
||||||
|
|
||||||
|
if (get_var_name(var_str, var_name, '=')) {
|
||||||
|
/* Check if variable already exists */
|
||||||
|
if ((var_addr = get_var_addr(from, till, var_name)) != NULL) {
|
||||||
|
/* @TODO: remove more?? could be that it were there more than once?? */
|
||||||
|
if (!remove_var(var_addr, till, var_name))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Append the variable to the end */
|
||||||
|
if ((var_addr = get_end_mark(from, till)) != NULL) {
|
||||||
|
/* Check if environment is empty. If yes, start from the beginning */
|
||||||
|
if (var_addr == (from + 1))
|
||||||
|
var_addr--;
|
||||||
|
while (var_addr < till && *var_str)
|
||||||
|
*var_addr++ = *var_str++;
|
||||||
|
*var_addr++ = 0;
|
||||||
|
*var_addr = 0;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unable to find environment end\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* env_funcs.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2013 by Digi International Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Description: Data types and prototypes for parsing the NVRAM environment
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ENV_FUNCS_H
|
||||||
|
#define ENV_FUNCS_H
|
||||||
|
|
||||||
|
#define ENV_MAX_VAR_NAME_LEN 50
|
||||||
|
#define ENV_MAX_VAR_VAL_LEN 256
|
||||||
|
|
||||||
|
char *get_var_value(const char *from, const char *var_name, char sep);
|
||||||
|
char *get_next_env_string(char *from, char *till);
|
||||||
|
char *get_var_addr(char *from, char *till, char *var_name);
|
||||||
|
char *get_end_mark(char *from, char *till);
|
||||||
|
int get_var_name(const char *from, char *var_name, char sep);
|
||||||
|
int add_var(char *from, char *till, char *var_str);
|
||||||
|
int remove_var(char *from, char *till, char *var_name);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* environment.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2013 by Digi International Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Description: Data types and definitions for environment in NVRAM
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ENV_TOOL_H_
|
||||||
|
#define __ENV_TOOL_H_
|
||||||
|
|
||||||
|
#define VAR_SEP '\0'
|
||||||
|
#define VAR_ASIGN '='
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long crc;
|
||||||
|
char data[];
|
||||||
|
} env_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,561 @@
|
||||||
|
/*
|
||||||
|
* main_env.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2013 by Digi International Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Description: main() and user code to manage u-boot and linux environment
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VERSION "1.8" "-g"GIT_SHA1
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <mtd/mtd-user.h> /* MEMERASE */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h> /* ioctl */
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <libdigi/crc32.h>
|
||||||
|
|
||||||
|
#include <nvram.h> /* Nv* */
|
||||||
|
|
||||||
|
#include "env_funcs.h"
|
||||||
|
#include "environment.h"
|
||||||
|
|
||||||
|
#define APP_UBOOTENV "ubootenv"
|
||||||
|
#define APP_PRODINFOENV "prodinfoenv"
|
||||||
|
|
||||||
|
static char *fileadd = NULL;
|
||||||
|
static char *printlist = NULL;
|
||||||
|
static char *setstring = NULL;
|
||||||
|
static char *eraselist = NULL;
|
||||||
|
static char *cmdname = NULL;
|
||||||
|
static int dump = 0, clean = 0;
|
||||||
|
static nv_os_type_e envType;
|
||||||
|
|
||||||
|
static const char *envTypes[] = {
|
||||||
|
[NVOS_NONE] = "None",
|
||||||
|
[NVOS_UBOOT] = "U-Boot",
|
||||||
|
[NVOS_PROD_INFO] = "Product Info",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t envDefaultSizes[] = {
|
||||||
|
[NVOS_NONE] = 0,
|
||||||
|
[NVOS_UBOOT] = 8192, /* Default value is CONFIG_ENV_SIZE, normally set by U-Boot */
|
||||||
|
[NVOS_PROD_INFO] = PROD_INFO_DATA_SIZE, /* Defined in nvram.h but shouldn't be except uboot needs it */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* excludeVars[][2] = {
|
||||||
|
{"ethaddr", "ethaddr1" },
|
||||||
|
{"wlanaddr", "ethaddr2" },
|
||||||
|
{"eth1addr", "ethaddr3" },
|
||||||
|
{"ipaddr", "ip1" },
|
||||||
|
{"ipaddr_wlan", "ip2" },
|
||||||
|
{"ipaddr1", "ip3" },
|
||||||
|
{"netmask", "netmask1" },
|
||||||
|
{"netmask_wlan","netmask2" },
|
||||||
|
{"netmask1", "netmask3" },
|
||||||
|
{"serverip", "server" },
|
||||||
|
{"gatewayip", "gateway" },
|
||||||
|
{"dnsip", "dns1" },
|
||||||
|
{"dnsip2", "dns2" },
|
||||||
|
{"dhcp", "dhcp1" },
|
||||||
|
{"dhcp_wlan", "dhcp2" },
|
||||||
|
{"dhcp1", "dhcp3" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *env_os_type_to_string(void)
|
||||||
|
{
|
||||||
|
return envTypes[envType];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int env_onetime_writable(void)
|
||||||
|
{
|
||||||
|
if (NVOS_PROD_INFO == envType)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int env_is_empty(env_t * env, unsigned int envlen)
|
||||||
|
{
|
||||||
|
char *from = (char *)&env->data;
|
||||||
|
char *till = (char *)&env->data + envlen;
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
end = get_end_mark(from, till);
|
||||||
|
/* Check if environment is empty. If yes, start from the beginning */
|
||||||
|
if (end == (from + 1))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int env_have_to_use_nvram(const char *varname)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (envType == NVOS_UBOOT) {
|
||||||
|
for (j = 0; j < ARRAY_SIZE(excludeVars); j++) {
|
||||||
|
if (strcmp(varname, excludeVars[j][0]) == 0)
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Usage: %s [options]\n"
|
||||||
|
"%s %s Copyright Digi International Inc.\n\n"
|
||||||
|
"Prints or updates the %s environment\n"
|
||||||
|
"\n"
|
||||||
|
" -d, --dump Prints the values of all the environment\n"
|
||||||
|
" -p, --print 'var_name_list' Prints the value of the list of variables\n"
|
||||||
|
" The list has to be simple quoted ('')\n"
|
||||||
|
" -s, --set 'var_name=var_value' Sets var_value in the variable var_name\n"
|
||||||
|
" The string has to be simple quoted ('') to allow\n"
|
||||||
|
" spaces\n"
|
||||||
|
" -e --erase 'var_name_list' Removes the list of variables (simple quoted)\n"
|
||||||
|
" -c --clean Removes all variables\n"
|
||||||
|
" -a --fileadd file_name Adds variables from file_name. To init the full\n"
|
||||||
|
" environment from file use -c -a simultaneously\n"
|
||||||
|
" -h --help Displays usage information\n\n",
|
||||||
|
cmdname, cmdname, VERSION, env_os_type_to_string());
|
||||||
|
|
||||||
|
if (env_onetime_writable()) {
|
||||||
|
fprintf(stdout, " WARNING: Variables can only be set the first time\n"
|
||||||
|
" and become read-only afterwards.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_usage_and_exit(int exit_code)
|
||||||
|
{
|
||||||
|
show_usage();
|
||||||
|
exit(exit_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_options(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int opt_index, opt, optcount = 0;
|
||||||
|
static const char *short_options = "?hdcp:s:e:a:";
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
{"dump", no_argument, NULL, 'd'},
|
||||||
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
{"erase", required_argument, NULL, 'e'},
|
||||||
|
{"clean", no_argument, NULL, 'c'},
|
||||||
|
{"fileadd", required_argument, NULL, 'a'},
|
||||||
|
{"print", required_argument, NULL, 'p'},
|
||||||
|
{"set", required_argument, NULL, 's'},
|
||||||
|
{0, 0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (opt_index = 0;;) {
|
||||||
|
|
||||||
|
opt = getopt_long(argc, argv, short_options, long_options, &opt_index);
|
||||||
|
if (opt == EOF)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case 'd':
|
||||||
|
dump = 1;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
printlist = optarg;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
setstring = optarg;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
fileadd = optarg;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
eraselist = optarg;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
clean = 1;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case '?':
|
||||||
|
show_usage_and_exit(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
optcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optcount == 0)
|
||||||
|
show_usage_and_exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
/* Check options */
|
||||||
|
if (dump && (printlist != NULL)) {
|
||||||
|
fprintf(stderr, "--dump and --print can't be used simultaneously\n");
|
||||||
|
show_usage_and_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (clean && (eraselist != NULL)) {
|
||||||
|
fprintf(stderr, "--clean and --erase can't be used simultaneously\n");
|
||||||
|
show_usage_and_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int env_add_var(const char *varstring, env_t * env, unsigned int envlen)
|
||||||
|
{
|
||||||
|
char *nvramCmd[3] = { "set", "network", NULL };
|
||||||
|
char tmpstr[50];
|
||||||
|
|
||||||
|
char *varval;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (varstring == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!get_var_name(varstring, tmpstr, VAR_ASIGN))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Check if is a special variable */
|
||||||
|
if ((j = env_have_to_use_nvram(tmpstr)) != -1) {
|
||||||
|
if ((varval = get_var_value(varstring, excludeVars[j][0], VAR_ASIGN)) != NULL) {
|
||||||
|
/* Define command to be used by nvram */
|
||||||
|
sprintf(tmpstr, "%s=%s", excludeVars[j][1], varval);
|
||||||
|
nvramCmd[2] = tmpstr;
|
||||||
|
if (!NvCmdLine(3, (const char **)nvramCmd)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!add_var(env->data, env->data + envlen, (char *)varstring)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int env_add_vars_from_file(char *filename, env_t * env, unsigned int envlen)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char line[ENV_MAX_VAR_NAME_LEN + ENV_MAX_VAR_VAL_LEN + 3];
|
||||||
|
int ret = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
if ((fp = fopen(filename, "r")) == NULL)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
while (!feof(fp)) {
|
||||||
|
if (fgets(line, sizeof(line), fp)) {
|
||||||
|
/* TODO should we remove comments starting with # ?? */
|
||||||
|
/* Remove '\n' */
|
||||||
|
if (line[strlen(line) - 1] == '\n')
|
||||||
|
line[strlen(line) - 1] = 0;
|
||||||
|
if (env_add_var((const char *)line, env, envlen)) {
|
||||||
|
fprintf(stderr, "Unable to add environment variable %s\n",
|
||||||
|
line);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (fp)
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void env_remove_varlist(const char *varlist, env_t * env, unsigned int envlen)
|
||||||
|
{
|
||||||
|
char *var;
|
||||||
|
|
||||||
|
var = strtok((char *)varlist, " ");
|
||||||
|
|
||||||
|
while (var != NULL) {
|
||||||
|
if (!remove_var(env->data, env->data + envlen, var))
|
||||||
|
fprintf(stderr, "Unable to remove environment variable %s\n", var);
|
||||||
|
var = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int env_validate(env_t * env, int datalen, int verbose)
|
||||||
|
{
|
||||||
|
unsigned long new_crc;
|
||||||
|
|
||||||
|
/* Check stored crc with data */
|
||||||
|
new_crc = crc32(0, (const unsigned char *)env->data, datalen);
|
||||||
|
|
||||||
|
if ((unsigned int)env->crc != new_crc) {
|
||||||
|
if ( verbose ) {
|
||||||
|
fprintf(stderr, "CRC failure: got 0x%08x expected 0x%08x\n",
|
||||||
|
(unsigned int)env->crc, (unsigned int)new_crc);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void env_printenv_nvram_vars(char *varname)
|
||||||
|
{
|
||||||
|
struct nv_critical *crit;
|
||||||
|
nv_param_ip_t *ip_params;
|
||||||
|
int index;
|
||||||
|
int oneloop = 0;
|
||||||
|
|
||||||
|
if (NvCriticalGet(&crit)) {
|
||||||
|
|
||||||
|
ip_params = &crit->s.p.xIP;
|
||||||
|
for (index = 3; index < ARRAY_SIZE(excludeVars); index++) {
|
||||||
|
if (varname != NULL) {
|
||||||
|
if ((index = env_have_to_use_nvram(varname)) == -1)
|
||||||
|
break;
|
||||||
|
oneloop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case 3:
|
||||||
|
fprintf(stdout, "ipaddr=%s\n",
|
||||||
|
NvToStringIP(ip_params->axDevice[0].uiIP));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fprintf(stdout, "ipaddr_wlan=%s\n",
|
||||||
|
NvToStringIP(ip_params->axDevice[1].uiIP));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
fprintf(stdout, "ipaddr1=%s\n",
|
||||||
|
NvToStringIP(crit->s.p.eth1dev.uiIP));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
fprintf(stdout, "netmask=%s\n",
|
||||||
|
NvToStringIP(ip_params->axDevice[0].uiNetMask));
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
fprintf(stdout, "netmask_wlan=%s\n",
|
||||||
|
NvToStringIP(ip_params->axDevice[1].uiNetMask));
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
fprintf(stdout, "netmask1=%s\n",
|
||||||
|
NvToStringIP(crit->s.p.eth1dev.uiNetMask));
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
fprintf(stdout, "serverip=%s\n",
|
||||||
|
NvToStringIP(ip_params->uiIPServer));
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
fprintf(stdout, "gatewayip=%s\n",
|
||||||
|
NvToStringIP(ip_params->uiIPGateway));
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
fprintf(stdout, "dnsip=%s\n",
|
||||||
|
NvToStringIP(ip_params->auiIPDNS[0]));
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
fprintf(stdout, "dnsip2=%s\n",
|
||||||
|
NvToStringIP(ip_params->auiIPDNS[1]));
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
fprintf(stdout, "dhcp=%s\n",
|
||||||
|
(ip_params->axDevice[0].flags.bDHCP ? "on" : "off"));
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
fprintf(stdout, "dhcp_wlan=%s\n",
|
||||||
|
(ip_params->axDevice[1].flags.bDHCP ? "on" : "off"));
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
fprintf(stdout, "dhcp1=%s\n",
|
||||||
|
(crit->s.p.eth1dev.flags.bDHCP ? "on" : "off"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (oneloop)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void env_printenv(int dump, char *varlist, env_t * env, unsigned int envlen)
|
||||||
|
{
|
||||||
|
char *var;
|
||||||
|
char *data = env->data;
|
||||||
|
char *varinenv;
|
||||||
|
|
||||||
|
if (dump) {
|
||||||
|
/* print the full environment */
|
||||||
|
while (data != NULL && *data) {
|
||||||
|
fprintf(stdout, "%s\n", data);
|
||||||
|
data = get_next_env_string(data, env->data + envlen);
|
||||||
|
}
|
||||||
|
if (envType == NVOS_UBOOT)
|
||||||
|
env_printenv_nvram_vars(NULL);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
var = strtok((char *)varlist, " ");
|
||||||
|
|
||||||
|
while (var != NULL) {
|
||||||
|
|
||||||
|
if (envType == NVOS_UBOOT)
|
||||||
|
env_printenv_nvram_vars(var);
|
||||||
|
if ((varinenv =
|
||||||
|
get_var_addr(env->data, env->data + envlen, var)) != NULL) {
|
||||||
|
fprintf(stdout, "%s\n", varinenv);
|
||||||
|
}
|
||||||
|
var = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned int envlen = 0;
|
||||||
|
env_t *env = NULL;
|
||||||
|
nv_param_os_cfg_t xCfg;
|
||||||
|
size_t iSize;
|
||||||
|
int save_env = 0;
|
||||||
|
int ret = EXIT_SUCCESS;
|
||||||
|
int found;
|
||||||
|
char *cmdstart;
|
||||||
|
|
||||||
|
cmdname = argv[0];
|
||||||
|
|
||||||
|
cmdname = *argv;
|
||||||
|
|
||||||
|
if ((cmdstart = strrchr(cmdname, '/')) != NULL) {
|
||||||
|
cmdname = cmdstart + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cmdname, APP_UBOOTENV) == 0)
|
||||||
|
envType = NVOS_UBOOT;
|
||||||
|
else if (strcmp(cmdname, APP_PRODINFOENV) == 0)
|
||||||
|
envType = NVOS_PROD_INFO;
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "This application can be invoked as:\n"
|
||||||
|
"%s\n%s\n\n", APP_UBOOTENV, APP_PRODINFOENV);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read and process command line */
|
||||||
|
process_options(argc, argv);
|
||||||
|
|
||||||
|
if (!NvInit(NVR_AUTO)) {
|
||||||
|
fprintf(stderr, "Unable to initialize nvram\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
found = NvOSCfgFind(&xCfg, envType);
|
||||||
|
|
||||||
|
if (!found && clean) {
|
||||||
|
/* Add missing section to nvram if --clean specified */
|
||||||
|
|
||||||
|
if (envDefaultSizes[envType] != 0 ) {
|
||||||
|
if (!NvOSCfgAdd(envType, envDefaultSizes[envType])) {
|
||||||
|
fprintf(stderr, "Unable to add missing %s environment to flash\n",
|
||||||
|
env_os_type_to_string());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try again to find our section */
|
||||||
|
found = NvOSCfgFind(&xCfg, envType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
fprintf(stderr, "Unable to detect %s environment in flash\n",
|
||||||
|
env_os_type_to_string());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
env = malloc(xCfg.uiSize);
|
||||||
|
if (NULL == env) {
|
||||||
|
perror("malloc");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(env, 0, xCfg.uiSize);
|
||||||
|
/* Adjust envlen for just for data, crc32 value not included */
|
||||||
|
envlen = xCfg.uiSize - sizeof(unsigned long);
|
||||||
|
|
||||||
|
if (!NvOSCfgGet(envType, (void *)env, xCfg.uiSize, &iSize)) {
|
||||||
|
/* This can't fail; we either found it, created it, or exited. */
|
||||||
|
/* But just to be safe... */
|
||||||
|
fprintf(stderr, "Unable to get %s environment from flash\n",
|
||||||
|
env_os_type_to_string());
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
goto free_and_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if env is one-time writable, is valid, and was already written */
|
||||||
|
if (env_onetime_writable() && !env_validate(env, envlen, 0) &&
|
||||||
|
!env_is_empty(env, envlen)) {
|
||||||
|
if ( clean || fileadd || eraselist || setstring ) {
|
||||||
|
fprintf(stderr, "Environment is one-time writable only\n");
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
goto free_and_ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clean) {
|
||||||
|
memset(env, 0, xCfg.uiSize);
|
||||||
|
save_env = 1;
|
||||||
|
} else {
|
||||||
|
if (env_validate(env, envlen, 1)) {
|
||||||
|
fprintf(stderr, "Invalid %s environment found\n",
|
||||||
|
env_os_type_to_string());
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
goto free_and_ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileadd != NULL) {
|
||||||
|
if (env_add_vars_from_file(fileadd, env, envlen) < 0) {
|
||||||
|
fprintf(stderr, "Unable to add %s environment from file %s\n",
|
||||||
|
env_os_type_to_string(), fileadd);
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
goto free_and_ret;
|
||||||
|
}
|
||||||
|
save_env = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eraselist != NULL) {
|
||||||
|
env_remove_varlist(eraselist, env, envlen);
|
||||||
|
save_env = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setstring != NULL) {
|
||||||
|
if (env_add_var(setstring, env, envlen)) {
|
||||||
|
fprintf(stderr, "Unable to add environment variable %s\n", setstring);
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
goto free_and_ret;
|
||||||
|
}
|
||||||
|
save_env = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dump) {
|
||||||
|
env_printenv(1, NULL, env, envlen);
|
||||||
|
} else if (printlist != NULL) {
|
||||||
|
env_printenv(0, printlist, env, envlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save_env) {
|
||||||
|
/* Compute new crc32 value just in case we are going to update the value in flash */
|
||||||
|
env->crc = crc32(0, (const unsigned char *)env->data, envlen);
|
||||||
|
|
||||||
|
if (!NvOSCfgSet(envType, env, xCfg.uiSize)) {
|
||||||
|
fprintf(stderr, "Unable to set %s environment to store in flash\n",
|
||||||
|
env_os_type_to_string());
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (!NvSave()) {
|
||||||
|
fprintf(stderr, "Unable to save %s environment in flash\n",
|
||||||
|
env_os_type_to_string());
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free_and_ret:
|
||||||
|
free(env);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -39,6 +39,7 @@ RDEPENDS_${PN} = "\
|
||||||
${VIRTUAL-RUNTIME_login_manager} \
|
${VIRTUAL-RUNTIME_login_manager} \
|
||||||
${VIRTUAL-RUNTIME_init_manager} \
|
${VIRTUAL-RUNTIME_init_manager} \
|
||||||
${VIRTUAL-RUNTIME_update-alternatives} \
|
${VIRTUAL-RUNTIME_update-alternatives} \
|
||||||
|
ubootenv \
|
||||||
update-flash \
|
update-flash \
|
||||||
usbutils \
|
usbutils \
|
||||||
${MACHINE_ESSENTIAL_EXTRA_RDEPENDS}"
|
${MACHINE_ESSENTIAL_EXTRA_RDEPENDS}"
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ RDEPENDS_${PN} = "\
|
||||||
${VIRTUAL-RUNTIME_login_manager} \
|
${VIRTUAL-RUNTIME_login_manager} \
|
||||||
${VIRTUAL-RUNTIME_init_manager} \
|
${VIRTUAL-RUNTIME_init_manager} \
|
||||||
${VIRTUAL-RUNTIME_update-alternatives} \
|
${VIRTUAL-RUNTIME_update-alternatives} \
|
||||||
|
ubootenv \
|
||||||
update-flash \
|
update-flash \
|
||||||
usbutils \
|
usbutils \
|
||||||
${MACHINE_ESSENTIAL_EXTRA_RDEPENDS}"
|
${MACHINE_ESSENTIAL_EXTRA_RDEPENDS}"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue