]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/env.c
97bd2e3fe7717ae002f280718927fb66e93a2e7d
5 #include <avr/eeprom.h>
18 #define ENV_SIZE CONFIG_ENV_SIZE-2
21 #define ENV_GET_VAL (1<<0)
27 * TODO: move elsewhere
31 static void print_blanks(uint_fast8_t count
)
38 void dump_ram(const uint8_t *startaddr
, int len
, char *title
)
41 uint8_t pre
= (size_t) startaddr
% 16;
42 const uint8_t *addr
= (uint8_t *) ((size_t) startaddr
& ~0x0f);
47 printf_P(PSTR("%s\n"),title
);
53 printf_P(PSTR(" %.4x:"), (size_t) addr
);
54 print_blanks(3 * pre
);
55 for (i
= pre
; i
< llen
; i
++)
56 printf_P(PSTR(" %.2x"), addr
[i
]);
57 print_blanks(3 * (16 - i
+ 1) + pre
);
58 for (i
= pre
; i
< llen
; i
++)
59 printf_P(PSTR("%c"), isprint(addr
[i
]) ? addr
[i
] : '.');
70 extern unsigned int __brkval
;
72 dump_ram((uint8_t *) __malloc_heap_start
,
73 __brkval
- (unsigned int) __malloc_heap_start
,
77 /* TODO: combine with dump_ram() */
78 void dump_eep(const uint8_t *addr
, int len
)
83 printf_P(PSTR("eeprom dump:"));
85 printf_P(PSTR("\n 0x%.4x:"), (unsigned int) addr
);
86 for (i
= 0; i
<16; i
++)
87 buf
[i
] = eeprom_read_byte(addr
+ i
);
88 for (i
= 0; i
<16; i
++)
89 printf_P(PSTR(" %.2x"), buf
[i
]);
91 for (i
= 0; i
<16; i
++)
92 printf_P(PSTR("%c"), isprint(buf
[i
]) ? buf
[i
] : '.');
95 len
-= len
> 16 ? 16 : len
;
101 const FLASH
char default_env
[] = {
102 "bootdelay=" "3" DELIM
103 "bootcmd=" "echo hallo" DELIM
104 "baudrate=" "115200" DELIM
109 typedef struct environment_s
{
110 uint16_t crc
; /* CRC16 over data bytes */
111 char data
[ENV_SIZE
]; /* Environment data */
116 typedef struct env_item_s
{
117 #define EF_N_EEP (1<<7)
118 #define EF_V_EEP (1<<6)
119 #define EF_DIRTY (1<<0)
132 static env_item_t env_list
[CONFIG_ENVVAR_MAX
];
133 static int entrycount
;
136 static char env_get_char(uint16_t index
)
138 unsigned int off
= CONFIG_ENV_OFFSET
;
140 return (char) eeprom_read_byte((const uint8_t *)off
+ index
+
141 offsetof(env_t
, data
));
145 uint16_t ee_name_get(char *buf
, env_item_t
*ep
)
150 if (ep
->flags
& EF_N_EEP
) {
152 while ((c
= env_get_char(ep
->name
.eep
+ i
)) != '=' &&
153 c
!= '\0' && i
< CONFIG_SYS_ENV_NAMELEN
) {
158 if (i
> 0 && c
!= '=') {
159 debug("** ee_name: '%s' not '=' terminated!\n", buf
);
162 strncpy(buf
, ep
->name
.ram
, CONFIG_SYS_ENV_NAMELEN
);
163 i
= strnlen(buf
, CONFIG_SYS_ENV_NAMELEN
);
170 uint16_t ee_val_get(char *buf
, uint16_t index
, int len
)
175 while ((c
= env_get_char (index
+ i
)) != '\0' && i
< len
) {
182 /* TODO: len check */
188 int comp_env_key_item(const void *key
, const void *item
)
190 char buf
[CONFIG_SYS_ENV_NAMELEN
+1];
191 env_item_t
*ep
= (env_item_t
*) item
;
193 ee_name_get(buf
, ep
);
195 return strcmp((char *) key
, buf
);
199 int comp_env_items(const void *m1
, const void *m2
)
201 char b1
[CONFIG_SYS_ENV_NAMELEN
+1];
202 char b2
[CONFIG_SYS_ENV_NAMELEN
+1];
204 env_item_t
*ep1
= (env_item_t
*) m1
;
205 env_item_t
*ep2
= (env_item_t
*) m2
;
207 ee_name_get(b1
, ep1
);
208 ee_name_get(b2
, ep2
);
210 return strcmp(b1
, b2
);
214 env_item_t
* ee_entry_get(const char *s
, env_item_t
*ep
, uint_fast8_t flag
)
216 char name
[CONFIG_SYS_ENV_NAMELEN
+1];
220 //printf_P(PSTR("*** ee_entry_get: >>>>>>>>> ENTER <<<<<<<<<\n"));
223 while ((nlen
= ee_name_get(name
, idx
)) != 0 && idx
< CONFIG_ENV_SIZE
) {
225 //printf_P(PSTR("** idx: %d, name: '%s', s: '%s', nlen: %d, cpres:%d\n"),
226 // idx, name, s, nlen, strncmp(name, s, nlen));
228 if (strncmp(name
, s
, nlen
) == 0)
232 while (env_get_char(idx
++) != 0)
238 ep
->flags
= EF_N_EEP
;
240 if (flag
& ENV_GET_VAL
) {
241 vp
= xmalloc(CONFIG_SYS_CBSIZE
);
242 nlen
= ee_val_get(vp
, idx
+ nlen
+ 1, CONFIG_SYS_CBSIZE
);
243 ep
->val
= xrealloc(vp
, nlen
+ 1);
248 //printf_P(PSTR("*** ee_entry_get: >>>>>> LEAVE 0x%.4x <<<<<\n"),
249 // (unsigned int) ep);
253 //printf_P(PSTR("*** ee_entry_get: >>>>>> LEAVE <NULL> <<<<<\n"));
259 static char p_env_name_buf
[CONFIG_SYS_ENV_NAMELEN
+1];
261 static char *dbg_p_env_name(env_item_t
*p
)
263 if (p
->flags
& EF_N_EEP
) {
264 if (ee_name_get(p_env_name_buf
, p
) != 0)
265 return p_env_name_buf
;
269 return "<NO EEP_NAME>";
273 int env_item_print(env_item_t
*ep
)
275 char buf
[CONFIG_SYS_ENV_NAMELEN
+1];
279 ee_name_get(buf
, ep
);
280 len
= printf_P(PSTR("%s="), buf
);
282 if (e
.val
.ram
!= NULL
) {
285 if (e
.flags
& EF_V_EEP
)
286 c
= env_get_char(e
.val
.eep
++);
304 static env_item_t
*envlist_search(const char *name
)
306 return bsearch(name
, env_list
, entrycount
,
307 sizeof(env_item_t
), comp_env_key_item
);
311 env_item_t
*envlist_insert(const char *key
, env_item_t
*e
)
313 const size_t size
= sizeof(env_item_t
);
315 if (entrycount
< CONFIG_ENVVAR_MAX
) {
316 env_list
[entrycount
++] = *e
;
317 qsort(env_list
, entrycount
, size
, comp_env_items
);
319 return bsearch(key
, env_list
, entrycount
,
320 size
, comp_env_key_item
);
327 env_item_t
*envlist_enter(env_item_t
*e
)
329 char *key
= e
->name
.ram
;
330 const size_t size
= sizeof(env_item_t
);
333 ep
= bsearch(key
, env_list
, entrycount
,
334 size
, comp_env_key_item
);
337 if (entrycount
< CONFIG_ENVVAR_MAX
) {
339 env_list
[entrycount
++] = *e
;
340 qsort(env_list
, entrycount
, size
, comp_env_items
);
341 ep
= bsearch(key
, env_list
, entrycount
,
342 size
, comp_env_key_item
);
345 if ((ep
->flags
& EF_V_EEP
) == 0) {
348 ep
->val
.ram
= e
->val
.ram
;
352 ep
->flags
|= EF_DIRTY
;
353 ep
->flags
&= ~EF_V_EEP
;
355 if ((ep
->flags
& EF_N_EEP
) == 0) {
356 int nlen
= strnlen(key
, CONFIG_SYS_ENV_NAMELEN
);
357 char *name
= xmalloc(nlen
+ 1);
359 printf_P(PSTR("## Can't malloc %d bytes\n"),
373 static env_item_t
*envlist_get(const char *name
, uint_fast8_t flag
)
377 ep
= envlist_search(name
);
379 if (ep
!= NULL
&& (flag
& ENV_GET_VAL
)) {
380 if (ep
->flags
& EF_V_EEP
) {
383 vp
= xmalloc(CONFIG_SYS_CBSIZE
);
384 len
= ee_val_get(vp
, ep
->val
.eep
, CONFIG_SYS_CBSIZE
);
385 ep
->val
.ram
= xrealloc(vp
, len
+ 1);
386 ep
->flags
&= ~EF_V_EEP
;
394 static int envlist_delete(const char *name
)
396 size_t size
= sizeof(env_item_t
);
397 env_item_t
*ep
= bsearch(name
, env_list
, entrycount
,
398 sizeof(env_item_t
), comp_env_key_item
);
403 if ((ep
->flags
& EF_V_EEP
) == 0)
405 if ((ep
->flags
& EF_N_EEP
) == 0)
409 printf_P(PSTR("*** envlist_delete memmove: 0x%.4x, 0x%.4x, %d\n"),
410 (unsigned) ep
, (unsigned) ep
+ size
,
411 (env_list
- ep
)*size
+ entrycount
*size
);
412 memmove(ep
, ep
+ 1, (env_list
- ep
)*size
+ entrycount
*size
);
417 dump_ram((uint8_t *) &env_list
[0], entrycount
* sizeof(env_item_t
),
420 debug("** entrycount: %d\n", entrycount
);
421 for (int i
=0; i
<entrycount
; i
++) {
422 printf_P(PSTR("** env var [%d] "), i
);
423 env_item_print(&env_list
[i
]);
431 char *getenv(const char *name
)
436 debug("** getenv: %s\n", name
);
438 ep
= envlist_get(name
, ENV_GET_VAL
);
443 dump_ram((uint8_t *) &env_list
[0], entrycount
* sizeof(env_item_t
),
446 debug("** entrycount: %d\n", entrycount
);
447 for (int i
=0; i
<entrycount
; i
++) {
448 printf_P(PSTR("** env var [%d] "), i
);
449 env_item_print(&env_list
[i
]);
461 // rc = env_export(&env_new);
466 // rc = eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR,
467 // off, (uchar *)&env_new, CONFIG_ENV_SIZE);
473 /*-----------------------------------------------------------------------------*/
476 int set_default_env(void)
479 uint16_t crc
= 0xffff;
480 uint16_t eep
= CONFIG_ENV_OFFSET
+ offsetof(env_t
, data
);
481 unsigned int len
= CONFIG_ENV_SIZE
- offsetof(env_t
, data
);
482 unsigned int i
, src
= 0;
483 char c
= 0xff, c0
= c
;
485 printf_P(PSTR("\n\n** set_default_env()\n"));
489 memcpy_P(buf
, default_env
+src
, sizeof(buf
));
491 for (i
=0; i
< (len
< sizeof(buf
) ? len
: sizeof(buf
)) &&
492 !(c
== 0 && c0
== 0);
499 eeprom_update_block(buf
, (char *) eep
, i
);
500 /**/ printf_P(PSTR("eeprom_update_block: eep: 0x%.4x, i:%d\n"),
501 (unsigned int) eep
, i
);
502 /**/ dump_ram((uint8_t *) buf
, i
, "=== buf:");
503 /**/ dump_eep((const uint8_t *) eep
, i
);
505 if (c
== 0 && c0
== 0)
507 if (len
> sizeof(buf
))
513 printf_P(PSTR("** crc adr: 0x%.4x, crc: 0x%.4x\n"),
514 (unsigned int) (uint16_t *) CONFIG_ENV_OFFSET
+ offsetof(env_t
,crc
), crc
);
516 eeprom_update_word((uint16_t *) CONFIG_ENV_OFFSET
+ offsetof(env_t
,crc
), crc
);
518 /**/ dump_eep(0, 128);
525 uint16_t crc
, stored_crc
;
529 debug("\n\n** env_check()\n");
533 stored_crc
= eeprom_read_word((const uint16_t *) CONFIG_ENV_OFFSET
+
534 offsetof(env_t
, crc
));
537 for (i
= offsetof(env_t
, data
);
538 !(c
== 0 && c0
== 0) && i
< CONFIG_ENV_SIZE
;
542 c
= eeprom_read_byte((const uint8_t *) CONFIG_ENV_OFFSET
+ i
);
545 debug("** crc eep: 0x%.4x, crc new: 0x%.4x\n", stored_crc
, crc
);
547 return crc
== stored_crc
;
552 char name
[CONFIG_SYS_ENV_NAMELEN
+1];
557 e
.flags
= EF_N_EEP
| EF_V_EEP
;
559 while ((nlen
= ee_name_get(name
, &e
)) != 0 && idx
< ENV_SIZE
) {
561 if (entrycount
<= CONFIG_ENVVAR_MAX
) {
562 e
.val
.eep
= idx
+ nlen
+ 1;
564 env_list
[entrycount
++] = e
;
567 while (env_get_char(idx
++) != 0 && idx
< ENV_SIZE
)
571 debug("** Too many environment variables!\n");
575 qsort(env_list
, entrycount
, sizeof(env_item_t
), comp_env_items
);
582 * Command interface: print one or all environment variables
584 * Returns -1 in case of error, or length of printed string
586 static int env_print(char *name
)
590 if (name
) { /* print a single name */
592 env_item_t
*ep
= envlist_search(name
);
594 len
= env_item_print(ep
);
596 } else { /* print whole list */
598 for (int i
= 0 ; i
< entrycount
; i
++) {
599 len
+= env_item_print(&env_list
[i
]);
607 int do_env_print(cmd_tbl_t
*cmdtp
, int flag
, int argc
,
613 (void) cmdtp
; (void) flag
;
616 /* print all env vars */
617 rcode
= env_print(NULL
);
620 printf_P(PSTR("\nEnvironment size: %d/%d bytes\n"),
625 /* print selected env vars */
626 for (i
= 1; i
< argc
; ++i
) {
627 int rc
= env_print(argv
[i
]);
629 printf_P(PSTR("## Error: \"%s\" not defined\n"), argv
[i
]);
639 * Set a new environment variable,
640 * or replace or delete an existing one.
642 static int _do_env_set(int flag
, int argc
, char * const argv
[])
645 char *name
, *value
, *s
;
649 debug("Initial value for argc=%d\n", argc
);
654 if (strchr(name
, '=')) {
655 printf_P(PSTR("## Error: illegal character '='"
656 "in variable name \"%s\"\n"), name
);
659 if (strlen(name
) > CONFIG_SYS_ENV_NAMELEN
) {
660 printf_P(PSTR("## Error: Variable name \"%s\" too long. "
661 "(max %d characters)\n"), name
, CONFIG_SYS_ENV_NAMELEN
);
668 if (argc
< 3 || argv
[2] == NULL
) {
669 int rc
= envlist_delete(name
);
674 * Insert / replace new value
676 for (i
= 2, len
= 0; i
< argc
; ++i
)
677 len
+= strlen(argv
[i
]) + 1;
679 value
= xmalloc(len
);
681 printf_P(PSTR("## Can't malloc %d bytes\n"), len
);
684 for (i
= 2, s
= value
; i
< argc
; ++i
) {
687 while ((*s
++ = *v
++) != '\0')
697 ep
= envlist_enter(&e
);
699 printf_P(PSTR("## Error inserting \"%s\" variable.\n"),
707 int setenv(const char *varname
, const char *varvalue
)
709 const char * const argv
[3] = { NULL
, varname
, varvalue
};
712 if (varvalue
== NULL
|| varvalue
[0] == '\0')
715 return _do_env_set(0, argc
, (char * const *)argv
);
720 * Set an environment variable to an integer value
722 * @param varname Environment variable to set
723 * @param value Value to set it to
724 * @return 0 if ok, 1 on error
726 int setenv_ulong(const char *varname
, unsigned long value
)
728 /* TODO: this should be unsigned */
729 char *str
= simple_itoa(value
);
731 return setenv(varname
, str
);
737 * Set an environment variable to an value in hex
739 * @param varname Environment variable to set
740 * @param value Value to set it to
741 * @return 0 if ok, 1 on error
743 int setenv_hex(const char *varname
, unsigned long value
)
745 char str
[sizeof(unsigned long) *2 + 1];
747 sprintf_P(str
, PSTR("%lx"), value
);
748 return setenv(varname
, str
);
751 unsigned long getenv_hex(const char *varname
, unsigned long default_val
)
759 value
= strtoul(s
, &endp
, 16);
766 int do_env_set(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
771 return CMD_RET_USAGE
;
773 return _do_env_set(flag
, argc
, argv
);
777 #if defined(CONFIG_AUTO_COMPLETE)
778 int env_complete(char *var
, int maxv
, char *cmdv
[], int bufsz
, char *buf
)
787 while ((idx
= hmatch_r(var
, idx
, &match
, &env_htab
))) {
788 int vallen
= strlen(match
->key
) + 1;
790 if (found
>= maxv
- 2 || bufsz
< vallen
)
794 memcpy(buf
, match
->key
, vallen
);
799 qsort(cmdv
, found
, sizeof(cmdv
[0]), strcmp_compar
);
802 cmdv
[found
++] = "...";