+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
#include "common.h"
#include <string.h>
#include <stdlib.h>
-
+#include <stdbool.h>
#include <avr/eeprom.h>
#include "config.h"
#include "debug.h"
#include "xmalloc.h"
#include "crc.h"
+#include "getopt-min.h"
#include "command.h"
-
#include "env.h"
#define DELIM "\0"
const FLASH char default_env[] = {
- "bootdelay=" "3" DELIM
- "bootcmd=" "reset; loadf; go $(startaddr)" DELIM
- "baudrate=" "115200" DELIM
- "startaddr=" "0" DELIM
+ ENV_BAUDRATE "=" "115200" DELIM
+ ENV_BOOTDELAY "=" "3" DELIM
+ ENV_BOOTCMD "=" "pin ${pins}; loadcpm3; go ${startaddress}" DELIM
+ ENV_CPM3_SYSFILE "=" CONFIG_CPM3_SYSFILE DELIM
+ ENV_PINALIAS "=" "0:PG5,1:PG4,2:PB4,3:PB5,4:PB6,5:PB7,"
+ "6:PG3,7:PG2,8:PG1,9:PG0,10:PE7" DELIM
+ ENV_STARTADDRESS "=" "0" DELIM
+ "pins" "=" "2,8 low 9 high 3 2" DELIM
DELIM
};
+
/* EEPROM storage */
typedef struct environment_s {
uint16_t crc; /* CRC16 over data bytes */
}
+static const FLASH char *comp_key;
+
static
int comp_env_items(const void *m1, const void *m2)
{
env_item_t *ep1 = (env_item_t *) m1;
env_item_t *ep2 = (env_item_t *) m2;
- return strcmp(ep1->envvar, ep2->envvar);
+ if (ep1 == NULL)
+ return - strcmp_P(ep2->envvar, comp_key);
+ else
+ return strcmp(ep1->envvar, ep2->envvar);
}
env_item_t *envlist_search(const MEMX char *name)
{
- env_item_t e;
-
- e.envvar = (char *) name;
-
#ifdef __MEMX
- char buf[CONFIG_SYS_ENV_NAMELEN+1];
-
if (__builtin_avr_flash_segment(name) != -1) {
- char *p = buf;
- while ((*p++ = *name++) != '\0')
- ;
- e.envvar = buf;
+ comp_key = name;
+ return bsearch(0, env_list, entrycount,
+ sizeof(env_item_t), comp_env_items);
+ } else {
+
+ env_item_t e;
+ e.envvar = (char *) name;
+
+ return bsearch(&e, env_list, entrycount,
+ sizeof(env_item_t), comp_env_items);
}
-#endif /* __MEMX */
+#else
+ env_item_t e;
+ e.envvar = (char *) name;
return bsearch(&e, env_list, entrycount,
sizeof(env_item_t), comp_env_items);
+#endif /* __MEMX */
}
}
static
-int envlist_delete(const char *name)
+int envlist_delete(const MEMX char *name)
{
- env_item_t e;
-
- e.envvar = (char *) name;
-
- env_item_t *ep = bsearch(&e, env_list, entrycount,
- sizeof(env_item_t), comp_env_items);
+ env_item_t *ep = envlist_search(name);
if (ep != NULL)
return env_item_delete(ep);
}
-char *getenv(const MEMX char *name)
+char *getenv_str(const MEMX char *name)
{
env_item_t *ep;
char *ret = NULL;
static
-int env_item_print(env_item_t *ep)
+int env_item_print(env_item_t *ep, bool mode)
{
int len;
char *ev = ep->envvar;
+ if (mode) {
+ len = printf_P(PSTR("setenv %s "), ev) - 7;
+ len += printf_P(PSTR("'%s'\n"), ev + len) - 2;
+ } else {
len = printf_P(PSTR("%s="), ev);
len += printf_P(PSTR("%s\n"), ev + len);
-
+ }
return len;
}
* Returns -1 in case of error, or length of printed string
*/
static
-int env_print(const MEMX char *name)
+int env_print(const MEMX char *name, bool mode)
{
int len = -1;
env_item_t *ep = envlist_search(name);
if (ep != NULL)
- len = env_item_print(ep);
+ len = env_item_print(ep, mode);
} else { /* print whole list */
len = 0;
for (int i = 0 ; i < entrycount; i++) {
- len += env_item_print(&env_list[i]);
+ len += env_item_print(&env_list[i], mode);
}
}
return len;
}
-command_ret_t do_env_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- command_ret_t rc = CMD_RET_SUCCESS;
-
- (void) cmdtp; (void) flag;
-
- if (argc == 1) {
- /* print all env vars */
- int size = env_print(NULL);
- if (size < 0)
- return CMD_RET_FAILURE;
- printf_P(PSTR("\nEnvironment size: %d/%d bytes\n"),
- size, ENV_SIZE);
- return CMD_RET_SUCCESS;
- }
-
- /* print selected env vars */
- for (int i = 1; i < argc; ++i) {
- int rc = env_print(argv[i]);
- if (rc < 0) {
- printf_P(PSTR("## Error: \"%s\" not defined\n"), argv[i]);
- rc = CMD_RET_FAILURE;
- }
- }
-
- return rc;
-}
-
-
/**
* Set or delete environment variable
*
env_item_t e, *ep;
(void) flag;
- debug("Initial value for argc=%d\n", argc);
name = argv[1];
value = argv[2];
* @return 0 if ok, 1 on error
*/
static
-int setenv(const char *varname, const char *varvalue)
+int setenv(const MEMX char *varname, const char *varvalue)
{
- const char * const argv[3] = { NULL, varname, varvalue };
+ int rc;
+
+#ifdef __MEMX
+ char *tmpname = NULL;
+ if (__builtin_avr_flash_segment(varname) != -1) {
+ tmpname = malloc(strlen_P(varname)+1);
+ if (tmpname == NULL) {
+ printf_P(PSTR("setenv: Out of Memory!\n"));
+ return 1;
+ }
+ strcpy_P(tmpname, varname);
+ } else
+ tmpname = (char *) varname;
+#endif
+
+ const char * const argv[3] = { NULL, tmpname, varvalue };
int argc = 3;
if (varvalue == NULL || varvalue[0] == '\0')
--argc;
- return (int) _do_env_set(0, argc, (char * const *)argv);
+ rc = (int) _do_env_set(0, argc, (char * const *)argv);
+
+#ifdef __MEMX
+ free(tmpname);
+#endif
+ return rc;
}
-#if 0
/**
* Set an environment variable to an integer value
*
- * @param varname Environment variable to set
- * @param value Value to set it to
+ * @param name Environment variable to set
+ * @param value Value to set it to
+ * @param radix Base
* @return 0 if ok, 1 on error
*/
-int setenv_ulong(const char *varname, unsigned long value)
+static
+int setenv_intval(const MEMX char *name, unsigned long value, int radix)
{
- /* TODO: this should be unsigned */
- char *str = simple_itoa(value);
+ char buf[11];
- return setenv(varname, str);
-}
-#endif
+ ultoa(value, buf, radix);
+ return setenv(name, buf);
+}
/**
- * Set an environment variable to an value in hex
+ * Set an environment variable to a decimal integer value
*
- * @param varname Environment variable to set
- * @param value Value to set it to
+ * @param name Environment variable to set
+ * @param value Value to set it to
* @return 0 if ok, 1 on error
*/
-int setenv_hex(const MEMX char *varname, unsigned long value)
+int setenv_ulong(const MEMX char *name, unsigned long value)
{
- char str[sizeof(unsigned long) *2 + 1];
+ return setenv_intval(name, value, 10);
+}
- sprintf_P(str, PSTR("%lx"), value);
- return setenv(varname, str);
+
+/**
+ * Set an environment variable to a value in hex
+ *
+ * @param name Environment variable to set
+ * @param value Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+int setenv_hex(const MEMX char *name, unsigned long value)
+{
+ return setenv_intval(name, value, 16);
}
}
+/*
+ * Read an environment variable as a boolean
+ */
+bool getenv_yesno(const MEMX char *name)
+{
+ char *s = getenv_str(name);
+
+ if (s == NULL)
+ return false;
+
+ return strchr_P(PSTR("1yYtT"), *s) != NULL;
+
+/*
+ return *s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T' ?
+ 1 : 0;
+*/
+}
+
+command_ret_t do_env_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ (void) cmdtp; (void) flag;
+
+ bool mode = 0;
+ command_ret_t rc = CMD_RET_SUCCESS;
+
+ /* reset getopt() */
+ optind = 0;
+
+ int opt;
+ while ((opt = getopt(argc, argv, PSTR("s"))) != -1) {
+ switch (opt) {
+ case 's':
+ mode = 1;
+ break;
+ default: /* '?' */
+ return CMD_RET_USAGE;
+ }
+ }
+
+ if (optind == argc) {
+ /* print all env vars */
+ int size = env_print(NULL, mode);
+ if (size < 0)
+ return CMD_RET_FAILURE;
+ if (mode == 0)
+ printf_P(PSTR("\nEnvironment size: %d/%d bytes\n"),
+ size, ENV_SIZE);
+ return CMD_RET_SUCCESS;
+ }
+
+ /* print selected env vars */
+ while (optind < argc) {
+ int rc = env_print(argv[optind], mode);
+ if (rc < 0) {
+ printf_P(PSTR("## Error: \"%s\" not defined\n"), argv[optind]);
+ rc = CMD_RET_FAILURE;
+ }
+ optind++;
+ }
+
+ return rc;
+}
+
+
command_ret_t do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
(void) cmdtp;