]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/env.c
5 #include <avr/eeprom.h>
16 #define ENV_SIZE (CONFIG_ENV_SIZE - sizeof(uint16_t) -1)
18 #define OBSOLETE_FLAG 0
20 #define ENVLIST_DELETE (1<<0)
29 const FLASH
char default_env
[] = {
30 "bootdelay=" "3" DELIM
31 "bootcmd=" "reset; loadf; go $(startaddr)" DELIM
32 "baudrate=" "115200" DELIM
33 "startaddr=" "0" DELIM
38 typedef struct environment_s
{
39 uint16_t crc
; /* CRC16 over data bytes */
40 uint8_t flags
; /* active/obsolete flags */
41 char data
[ENV_SIZE
]; /* Environment data */
46 typedef struct env_item_s
{
51 static uint8_t env_valid
;
52 static env_item_t env_list
[CONFIG_ENVVAR_MAX
];
53 static int entrycount
;
57 char env_get_char(uint16_t index
)
59 unsigned int off
= CONFIG_ENV_OFFSET
;
64 off
+= CONFIG_ENV_SIZE
;
66 ret
= (char) eeprom_read_byte((const uint8_t *)off
+ index
+
67 offsetof(env_t
, data
));
71 ret
= default_env
[index
];
79 int comp_env_items(const void *m1
, const void *m2
)
81 env_item_t
*ep1
= (env_item_t
*) m1
;
82 env_item_t
*ep2
= (env_item_t
*) m2
;
84 return strcmp(ep1
->envvar
, ep2
->envvar
);
88 env_item_t
*envlist_search(const MEMX
char *name
)
92 e
.envvar
= (char *) name
;
95 char buf
[CONFIG_SYS_ENV_NAMELEN
+1];
97 if (__builtin_avr_flash_segment(name
) != -1) {
99 while ((*p
++ = *name
++) != '\0')
105 return bsearch(&e
, env_list
, entrycount
,
106 sizeof(env_item_t
), comp_env_items
);
111 env_item_t
*envlist_enter(env_item_t
*e
)
113 const size_t size
= sizeof(env_item_t
);
116 ep
= bsearch(e
, env_list
, entrycount
,
117 size
, comp_env_items
);
120 if (entrycount
< CONFIG_ENVVAR_MAX
) {
122 env_list
[entrycount
++] = *e
;
123 qsort(env_list
, entrycount
, size
, comp_env_items
);
124 ep
= bsearch(e
, env_list
, entrycount
,
125 size
, comp_env_items
);
129 ep
->envvar
= e
->envvar
;
137 int env_item_delete(env_item_t
*ep
)
145 size_t size
= sizeof(env_item_t
);
146 memmove(ep
, ep
+ 1, (env_list
- ep
)*size
+ entrycount
*size
);
152 int envlist_delete(const char *name
)
156 e
.envvar
= (char *) name
;
158 env_item_t
*ep
= bsearch(&e
, env_list
, entrycount
,
159 sizeof(env_item_t
), comp_env_items
);
162 return env_item_delete(ep
);
170 int envlist_import(uint8_t flags
)
179 if ((flags
& ENVLIST_DELETE
) != 0)
180 while (entrycount
!= 0)
181 env_item_delete(&env_list
[entrycount
-1]);
183 for (index
= 0; env_get_char(index
) != '\0'; ) {
184 for (len
= 0; env_get_char(index
+ len
) != '\0'; ++len
) {
185 if ((index
+ len
) >= ENV_SIZE
)
189 np
= (char *) xmalloc(len
+1);
191 printf_P(PSTR("## Can't malloc %d bytes\n"), len
+1);
196 while ((c
= env_get_char(index
++)) != '\0') {
197 if (!ef
&& (c
== '=')) {
214 uint16_t env_crc(uint16_t data_offset
)
222 for (i
= 0; !(c
== 0 && c0
== 0) && i
< ENV_SIZE
; i
++)
225 c
= eeprom_read_byte((const uint8_t *) data_offset
+ i
);
236 int env_check_valid(void)
238 const uint16_t offset
[2] = {CONFIG_ENV_OFFSET
,
239 CONFIG_ENV_OFFSET
+ CONFIG_ENV_SIZE
};
240 uint_fast8_t flags
[2], crc_ok
[2];
244 flags
[0] = eeprom_read_byte ((uint8_t *) offset
[0] +
245 offsetof(env_t
, flags
));
246 flags
[1] = eeprom_read_byte ((uint8_t *) offset
[1] +
247 offsetof(env_t
, flags
));
251 eeprom_read_word((uint16_t *) offset
[0] +
252 offsetof(env_t
, crc
))
253 == env_crc(offset
[0] + offsetof(env_t
, data
))
256 eeprom_read_word((uint16_t *) offset
[1] +
257 offsetof(env_t
, crc
))
258 == env_crc(offset
[1] + offsetof(env_t
, data
))
261 if (!crc_ok
[0] && !crc_ok
[1]) {
264 } else if (crc_ok
[0] && !crc_ok
[1]) {
266 } else if (!crc_ok
[0] && crc_ok
[1]) {
269 /* both ok - check serial */
271 if (flags
[1] == ACTIVE_FLAG
&& flags
[0] != ACTIVE_FLAG
)
273 else if (flags
[1] == OBSOLETE_FLAG
&& flags
[0] == 0xFF)
278 if (flags
[0] == ACTIVE_FLAG
&& flags
[1] == OBSOLETE_FLAG
)
280 else if (flags
[0] == OBSOLETE_FLAG
&& flags
[1] == ACTIVE_FLAG
)
282 else if (flags
[0] == 0xFF && flags
[1] == 0)
284 else if (flags
[1] == 0xFF && flags
[0] == 0)
286 else /* flags are equal - almost impossible */
297 env_valid
= env_check_valid();
298 if (env_valid
== 0) {
299 printf_P(PSTR("*** Warning - bad CRC, "
300 "using default environment\n\n"));
303 envlist_import(ENVLIST_DELETE
);
308 char *getenv(const MEMX
char *name
)
313 ep
= envlist_search(name
);
315 ret
= ep
->envvar
+ strlen(ep
->envvar
) +1;
320 int env_item_save(env_item_t
*ep
, uint16_t offset
, int space_left
)
323 char *var
= ep
->envvar
;
328 vlen
= strlen(var
+ nlen
+ 1);
331 if (nlen
+ vlen
+ 2 > space_left
)
334 eeprom_update_block(var
, (uint8_t *) offset
, nlen
);
336 eeprom_update_byte((uint8_t *) offset
++, '=');
337 eeprom_update_block(var
+ nlen
+1, (uint8_t *) offset
, vlen
+1);
339 return nlen
+ vlen
+ 2;
346 unsigned int off
= CONFIG_ENV_OFFSET
+ CONFIG_ENV_SIZE
;
347 unsigned int off_red
= CONFIG_ENV_OFFSET
;
353 if (env_valid
== 2) {
354 off
= CONFIG_ENV_OFFSET
;
355 off_red
= CONFIG_ENV_OFFSET
+ CONFIG_ENV_SIZE
;
358 eeprom_update_byte((uint8_t *) off
+ offsetof(env_t
, flags
), 0xff);
360 pos
= off
+ offsetof(env_t
, data
);
362 for (int i
= 0 ; i
< entrycount
; i
++) {
363 len
= env_item_save(&env_list
[i
], pos
, left
);
371 eeprom_update_byte((uint8_t *) pos
, 0);
372 crc
= env_crc(off
+ offsetof(env_t
, data
));
373 eeprom_update_word((uint16_t *) off
+ offsetof(env_t
, crc
), crc
);
374 eeprom_update_byte((uint8_t *) off
+ offsetof(env_t
, flags
),
378 eeprom_update_byte((uint8_t *) off_red
+ offsetof(env_t
, flags
),
380 env_valid
= (env_valid
== 2) ? 1 : 2;
388 int env_item_print(env_item_t
*ep
)
391 char *ev
= ep
->envvar
;
393 len
= printf_P(PSTR("%s="), ev
);
394 len
+= printf_P(PSTR("%s\n"), ev
+ len
);
401 * Command interface: print one or all environment variables
403 * Returns -1 in case of error, or length of printed string
406 int env_print(const MEMX
char *name
)
410 if (name
) { /* print a single name */
412 env_item_t
*ep
= envlist_search(name
);
414 len
= env_item_print(ep
);
416 } else { /* print whole list */
418 for (int i
= 0 ; i
< entrycount
; i
++) {
419 len
+= env_item_print(&env_list
[i
]);
426 command_ret_t
do_env_print(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
428 command_ret_t rc
= CMD_RET_SUCCESS
;
430 (void) cmdtp
; (void) flag
;
433 /* print all env vars */
434 int size
= env_print(NULL
);
436 return CMD_RET_FAILURE
;
437 printf_P(PSTR("\nEnvironment size: %d/%d bytes\n"),
439 return CMD_RET_SUCCESS
;
442 /* print selected env vars */
443 for (int i
= 1; i
< argc
; ++i
) {
444 int rc
= env_print(argv
[i
]);
446 printf_P(PSTR("## Error: \"%s\" not defined\n"), argv
[i
]);
447 rc
= CMD_RET_FAILURE
;
456 * Set or delete environment variable
458 * Set a new environment variable,
459 * or replace or delete an existing one.
461 * @param flag (not used)
463 * @param argv[1] Environment variable to set or delete
465 * @param argv[2] ... Value to set it to
467 * @return 0 if ok, 1 on error
470 command_ret_t
_do_env_set(int flag
, int argc
, char * const argv
[])
473 char *name
, *value
, *valp
, *p
;
477 debug("Initial value for argc=%d\n", argc
);
482 if (strchr(name
, '=')) {
483 printf_P(PSTR("## Error: illegal character '='"
484 "in variable name \"%s\"\n"), name
);
485 return CMD_RET_FAILURE
;
488 if (len
> CONFIG_SYS_ENV_NAMELEN
) {
489 printf_P(PSTR("## Error: Variable name \"%s\" too long. "
490 "(max %d characters)\n"), name
, CONFIG_SYS_ENV_NAMELEN
);
491 return CMD_RET_FAILURE
;
497 if (argc
< 3 || argv
[2] == NULL
) {
498 int rc
= envlist_delete(name
);
499 return rc
? CMD_RET_FAILURE
: CMD_RET_SUCCESS
;
503 * Insert / replace new value
505 for (i
= 2, len
+= 1; i
< argc
; ++i
)
506 len
+= strlen(argv
[i
]) + 1;
508 value
= xmalloc(len
);
510 printf_P(PSTR("## Can't malloc %d bytes\n"), len
);
511 return CMD_RET_FAILURE
;
514 valp
= value
+ strlen(name
) + 1;
515 for (i
= 2, p
= valp
; i
< argc
; ++i
) {
518 while ((*p
++ = *v
++) != '\0')
526 ep
= envlist_enter(&e
);
528 printf_P(PSTR("## Error inserting \"%s\" variable.\n"),
530 return CMD_RET_FAILURE
;
533 return CMD_RET_SUCCESS
;
537 * Set an environment variable
539 * @param varname Environment variable to set
540 * @param varvalue Value to set it to
541 * @return 0 if ok, 1 on error
544 int setenv(const char *varname
, const char *varvalue
)
546 const char * const argv
[3] = { NULL
, varname
, varvalue
};
549 if (varvalue
== NULL
|| varvalue
[0] == '\0')
552 return (int) _do_env_set(0, argc
, (char * const *)argv
);
557 * Set an environment variable to an integer value
559 * @param varname Environment variable to set
560 * @param value Value to set it to
561 * @return 0 if ok, 1 on error
563 int setenv_ulong(const char *varname
, unsigned long value
)
565 /* TODO: this should be unsigned */
566 char *str
= simple_itoa(value
);
568 return setenv(varname
, str
);
574 * Set an environment variable to an value in hex
576 * @param varname Environment variable to set
577 * @param value Value to set it to
578 * @return 0 if ok, 1 on error
580 int setenv_hex(const MEMX
char *varname
, unsigned long value
)
582 char str
[sizeof(unsigned long) *2 + 1];
584 sprintf_P(str
, PSTR("%lx"), value
);
585 return setenv(varname
, str
);
590 * Decode the integer value of an environment variable and return it.
592 * @param name Name of environemnt variable
593 * @param base Number base to use (normally 10, or 16 for hex)
594 * @param default_val Default value to return if the variable is not
596 * @return the decoded value, or default_val if not found
598 unsigned long getenv_ulong(const MEMX
char *name
, int base
, unsigned long default_val
)
603 env_item_t
*ep
= envlist_search(name
);
606 vp
= ep
->envvar
+ strlen(ep
->envvar
) +1;
607 value
= strtoul(vp
, &endp
, base
);
616 command_ret_t
do_env_set(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
621 return CMD_RET_USAGE
;
623 return _do_env_set(flag
, argc
, argv
);
627 command_ret_t
do_env_default(cmd_tbl_t
*cmdtp
, int flag
,
628 int argc
, char * const argv
[])
630 (void) cmdtp
; (void) flag
; (void) argc
; (void) argv
;
632 uint8_t tmp
= env_valid
;
635 /* Reset the whole environment */
636 printf_P(PSTR("## Resetting to default environment\n"));
637 envlist_import(ENVLIST_DELETE
);
641 return CMD_RET_SUCCESS
;
645 command_ret_t
do_env_save(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
647 (void) cmdtp
; (void) flag
; (void) argc
; (void) argv
;
649 printf_P(PSTR("Saving Environment ...\n"));
650 return saveenv() ? CMD_RET_FAILURE
: CMD_RET_SUCCESS
;
654 #if defined(CONFIG_AUTO_COMPLETE)
655 int env_complete(char *var
, int maxv
, char *cmdv
[], int bufsz
, char *buf
)
664 while ((idx
= hmatch_r(var
, idx
, &match
, &env_htab
))) {
665 int vallen
= strlen(match
->key
) + 1;
667 if (found
>= maxv
- 2 || bufsz
< vallen
)
671 memcpy(buf
, match
->key
, vallen
);
676 qsort(cmdv
, found
, sizeof(cmdv
[0]), strcmp_compar
);
679 cmdv
[found
++] = "...";