+
+/**
+ * return valid env
+ */
+static
+int env_check_valid(void)
+{
+ const uint16_t offset[2] = {CONFIG_ENV_OFFSET,
+ CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE};
+ uint_fast8_t flags[2], crc_ok[2];
+ int rc;
+
+ /* read FLAGS */
+ flags[0] = eeprom_read_byte ((uint8_t *) offset[0] +
+ offsetof(env_t, flags));
+ flags[1] = eeprom_read_byte ((uint8_t *) offset[1] +
+ offsetof(env_t, flags));
+
+ /* check CRC */
+ crc_ok[0] = (
+ eeprom_read_word((uint16_t *) offset[0] +
+ offsetof(env_t, crc))
+ == env_crc(offset[0] + offsetof(env_t, data))
+ );
+ crc_ok[1] = (
+ eeprom_read_word((uint16_t *) offset[1] +
+ offsetof(env_t, crc))
+ == env_crc(offset[1] + offsetof(env_t, data))
+ );
+
+ if (!crc_ok[0] && !crc_ok[1]) {
+ rc = 0;
+
+ } else if (crc_ok[0] && !crc_ok[1]) {
+ rc = 1;
+ } else if (!crc_ok[0] && crc_ok[1]) {
+ rc = 2;
+ } else {
+ /* both ok - check serial */
+#if 1
+ if (flags[1] == ACTIVE_FLAG && flags[0] != ACTIVE_FLAG)
+ rc = 2;
+ else if (flags[1] == OBSOLETE_FLAG && flags[0] == 0xFF)
+ rc = 2;
+ else
+ rc = 1;
+#else
+ if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG)
+ rc = 1;
+ else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG)
+ rc = 2;
+ else if (flags[0] == 0xFF && flags[1] == 0)
+ rc = 2;
+ else if (flags[1] == 0xFF && flags[0] == 0)
+ rc = 1;
+ else /* flags are equal - almost impossible */
+ rc = 1;
+#endif
+ }
+
+ return rc;
+}
+
+
+int env_init(void)
+{
+ env_valid = env_check_valid();
+ if (env_valid == 0) {
+ printf_P(PSTR("*** Warning - bad CRC, "
+ "using default environment\n\n"));
+ }
+
+ envlist_import(ENVLIST_DELETE);
+ return 0;
+}
+
+
+char *getenv_str(const MEMX char *name)
+{
+ env_item_t *ep;
+ char *ret = NULL;
+
+ ep = envlist_search(name);
+ if (ep != NULL)
+ ret = ep->envvar + strlen(ep->envvar) +1;
+ return ret;
+}
+
+static
+int env_item_save(env_item_t *ep, uint16_t offset, int space_left)
+{
+ int nlen, vlen;
+ char *var = ep->envvar;
+
+ nlen = strlen(var);
+ if (nlen == 0)
+ return 0;
+ vlen = strlen(var + nlen + 1);
+ if (vlen == 0)
+ return 0;
+ if (nlen + vlen + 2 > space_left)
+ return 0;
+
+ eeprom_update_block(var, (uint8_t *) offset, nlen);
+ offset += nlen;
+ eeprom_update_byte((uint8_t *) offset++, '=');
+ eeprom_update_block(var + nlen +1, (uint8_t *) offset, vlen+1);
+
+ return nlen + vlen + 2;
+}
+
+
+static