697 lines
18 KiB
C
697 lines
18 KiB
C
/*
|
|
* Copyright (c) 2013, Google, Inc. All rights reserved
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files
|
|
* (the "Software"), to deal in the Software without restriction,
|
|
* including without limitation the rights to use, copy, modify, merge,
|
|
* publish, distribute, sublicense, and/or sell copies of the Software,
|
|
* and to permit persons to whom the Software is furnished to do so,
|
|
* subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
#include <debug.h>
|
|
#include <assert.h>
|
|
#include <err.h>
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <list.h>
|
|
#include <dev/flash_nor.h>
|
|
#include <lib/cksum.h>
|
|
#include <lib/sysparam.h>
|
|
|
|
/* implementation of system parameter block, stored in nor flash */
|
|
/* sysparams are simple name/value pairs, with the data unstructured */
|
|
|
|
/* TODO: optimize in memory copy to store direct pointer to data instead of making copy */
|
|
|
|
#define LOCAL_TRACE 0
|
|
|
|
#define SYSPARAM_MAGIC 'SYSP'
|
|
|
|
#define SYSPARAM_FLAG_LOCK 0x1
|
|
|
|
struct sysparam_phys {
|
|
uint32_t magic;
|
|
uint32_t crc32; // crc of entire structure below crc including padding
|
|
uint32_t flags;
|
|
uint16_t namelen;
|
|
uint16_t datalen;
|
|
|
|
//uint8_t name[namelen];
|
|
// 0 padding to next multiple of 4
|
|
//uint8_t data[data];
|
|
// 0 padding to next multiple of 4
|
|
|
|
uint8_t namedata[0];
|
|
};
|
|
|
|
/* a copy we keep in memory */
|
|
struct sysparam {
|
|
struct list_node node;
|
|
|
|
uint32_t flags;
|
|
|
|
char *name;
|
|
|
|
size_t datalen;
|
|
void *data;
|
|
|
|
/* in memory size to hold this structure, the name string, and the data */
|
|
size_t memlen;
|
|
};
|
|
|
|
/* global state */
|
|
static struct {
|
|
struct list_node list;
|
|
|
|
bool dirty;
|
|
|
|
const struct flash_nor_bank *flash_bank;
|
|
size_t flash_offset;
|
|
size_t flash_len;
|
|
} params;
|
|
|
|
status_t sysparam_init(void)
|
|
{
|
|
LTRACE_ENTRY;
|
|
|
|
list_initialize(¶ms.list);
|
|
|
|
LTRACE_EXIT;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
static inline bool sysparam_is_locked(const struct sysparam *param)
|
|
{
|
|
return param->flags & SYSPARAM_FLAG_LOCK;
|
|
}
|
|
|
|
static inline size_t sysparam_len(const struct sysparam_phys *sp)
|
|
{
|
|
size_t len = sizeof(struct sysparam_phys);
|
|
|
|
len += ROUNDUP(sp->namelen, 4);
|
|
len += ROUNDUP(sp->datalen, 4);
|
|
|
|
return len;
|
|
}
|
|
|
|
static inline uint32_t sysparam_crc32(const struct sysparam_phys *sp)
|
|
{
|
|
size_t len = sysparam_len(sp);
|
|
|
|
LTRACEF("len %d\n", len);
|
|
uint32_t sum = crc32(0, (const void *)&sp->flags, len - 8);
|
|
LTRACEF("sum is 0x%x\n", sum);
|
|
|
|
return sum;
|
|
}
|
|
|
|
static struct sysparam *sysparam_create(const char *name, size_t namelen, const void *data, size_t datalen, uint32_t flags)
|
|
{
|
|
struct sysparam *param = malloc(sizeof(struct sysparam));
|
|
if (!param)
|
|
return NULL;
|
|
|
|
param->flags = flags;
|
|
param->memlen = sizeof(struct sysparam);
|
|
|
|
param->name = malloc(namelen + 1);
|
|
if (!param->name) {
|
|
free(param);
|
|
return NULL;
|
|
}
|
|
param->memlen += namelen + 1;
|
|
|
|
memcpy(param->name, name, namelen);
|
|
param->name[namelen] = '\0';
|
|
|
|
param->datalen = datalen;
|
|
size_t alloclen = ROUNDUP(datalen, 4); /* allocate a multiple of 4 for padding purposes */
|
|
param->data = malloc(alloclen);
|
|
if (!param->data) {
|
|
free(param->name);
|
|
free(param);
|
|
return NULL;
|
|
}
|
|
param->memlen += alloclen;
|
|
|
|
memcpy(param->data, data, datalen);
|
|
memset((char *)param->data + datalen, 0, alloclen - datalen); /* zero out the trailing space */
|
|
|
|
return param;
|
|
}
|
|
|
|
static struct sysparam *sysparam_read_phys(const struct sysparam_phys *sp)
|
|
{
|
|
return sysparam_create((const char *)sp->namedata, sp->namelen, sp->namedata + ROUNDUP(sp->namelen, 4), sp->datalen, sp->flags);
|
|
}
|
|
|
|
static struct sysparam *sysparam_find(const char *name)
|
|
{
|
|
struct sysparam *param;
|
|
list_for_every_entry(¶ms.list, param, struct sysparam, node) {
|
|
if (strcmp(name, param->name) == 0)
|
|
return param;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
status_t sysparam_scan(const struct flash_nor_bank *bank, size_t offset, size_t len)
|
|
{
|
|
LTRACEF("bank %p, offset %zx, len %zx\n", bank, offset, len);
|
|
|
|
DEBUG_ASSERT(bank);
|
|
DEBUG_ASSERT(offset + len <= bank->len);
|
|
DEBUG_ASSERT((offset % bank->page_size) == 0);
|
|
|
|
params.flash_bank = bank;
|
|
params.flash_offset = offset;
|
|
params.flash_len = len;
|
|
params.dirty = false;
|
|
|
|
flash_nor_begin(bank->num);
|
|
|
|
status_t err = NO_ERROR;
|
|
size_t pos = offset;
|
|
while (pos < offset + len) {
|
|
struct sysparam_phys *sp = FLASH_PTR(bank, pos);
|
|
|
|
/* examine the sysparam entry, making sure it's valid */
|
|
if (sp->magic != SYSPARAM_MAGIC) {
|
|
pos += 4; /* try searching in the next spot */
|
|
//LTRACEF("failed magic check\n");
|
|
continue;
|
|
}
|
|
|
|
/* looks valid, see if length is sane */
|
|
size_t splen = sysparam_len(sp);
|
|
if (pos + splen > offset + len) {
|
|
/* length exceeds the size of the area */
|
|
LTRACEF("param at 0x%x: bad length\n", pos);
|
|
break;
|
|
}
|
|
|
|
pos += splen;
|
|
|
|
/* calculate a checksum of it */
|
|
uint32_t sum = sysparam_crc32(sp);
|
|
|
|
if (sp->crc32 != sum) {
|
|
/* failed checksum */
|
|
LTRACEF("param at 0x%x: failed checksum\n", pos - splen);
|
|
continue;
|
|
}
|
|
|
|
LTRACEF("got param at offset 0x%zx\n", pos - splen);
|
|
|
|
struct sysparam *param = sysparam_read_phys(sp);
|
|
if (!param) {
|
|
LTRACEF("param at 0x%x: failed to make memory copy\n", pos - splen);
|
|
err = ERR_NO_MEMORY;
|
|
break;
|
|
}
|
|
|
|
list_add_tail(¶ms.list, ¶m->node);
|
|
}
|
|
|
|
flash_nor_end(bank->num);
|
|
|
|
LTRACE_EXIT;
|
|
return err;
|
|
}
|
|
|
|
status_t sysparam_reload(void)
|
|
{
|
|
if (params.flash_bank == NULL)
|
|
return ERR_INVALID_ARGS;
|
|
if (params.flash_len == 0)
|
|
return ERR_INVALID_ARGS;
|
|
|
|
/* wipe out the existing memory entries */
|
|
struct sysparam *param;
|
|
struct sysparam *temp;
|
|
list_for_every_entry_safe(¶ms.list, param, temp, struct sysparam, node) {
|
|
list_delete(¶m->node);
|
|
|
|
free(param->name);
|
|
free(param->data);
|
|
free(param);
|
|
}
|
|
|
|
/* reset the list back to scratch */
|
|
params.dirty = false;
|
|
|
|
status_t err = sysparam_scan(params.flash_bank, params.flash_offset, params.flash_len);
|
|
|
|
return err;
|
|
}
|
|
|
|
ssize_t sysparam_read(const char *name, void *data, size_t len)
|
|
{
|
|
struct sysparam *param;
|
|
|
|
param = sysparam_find(name);
|
|
if (!param)
|
|
return ERR_NOT_FOUND;
|
|
|
|
size_t toread = MIN(len, param->datalen);
|
|
memcpy(data, param->data, toread);
|
|
|
|
return toread;
|
|
}
|
|
|
|
ssize_t sysparam_length(const char *name)
|
|
{
|
|
struct sysparam *param;
|
|
|
|
param = sysparam_find(name);
|
|
if (!param)
|
|
return ERR_NOT_FOUND;
|
|
|
|
return param->datalen;
|
|
}
|
|
|
|
status_t sysparam_get_ptr(const char *name, const void **ptr, size_t *len)
|
|
{
|
|
struct sysparam *param;
|
|
|
|
param = sysparam_find(name);
|
|
if (!param)
|
|
return ERR_NOT_FOUND;
|
|
|
|
if (ptr)
|
|
*ptr = param->data;
|
|
if (len)
|
|
*len = param->datalen;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#if SYSPARAM_ALLOW_WRITE
|
|
|
|
/* write all of the parameters in memory to the space reserved in flash */
|
|
status_t sysparam_write(void)
|
|
{
|
|
if (params.flash_bank == NULL)
|
|
return ERR_INVALID_ARGS;
|
|
if (params.flash_len == 0)
|
|
return ERR_INVALID_ARGS;
|
|
|
|
if (!params.dirty)
|
|
return NO_ERROR;
|
|
|
|
/* preflight the length, make sure we have enough space */
|
|
struct sysparam *param;
|
|
size_t total_len = 0;
|
|
list_for_every_entry(¶ms.list, param, struct sysparam, node) {
|
|
total_len += sizeof(struct sysparam_phys);
|
|
total_len += ROUNDUP(strlen(param->name), 4);
|
|
total_len += ROUNDUP(param->datalen, 4);
|
|
}
|
|
|
|
if (total_len > params.flash_len)
|
|
return ERR_NO_MEMORY;
|
|
|
|
flash_nor_begin(params.flash_bank->num);
|
|
|
|
/* serialize all of the parameters */
|
|
size_t pos = params.flash_offset;
|
|
list_for_every_entry(¶ms.list, param, struct sysparam, node) {
|
|
struct sysparam_phys phys;
|
|
|
|
/* start filling out a struct */
|
|
phys.magic = SYSPARAM_MAGIC;
|
|
phys.crc32 = 0;
|
|
phys.flags = param->flags;
|
|
phys.namelen = strlen(param->name);
|
|
phys.datalen = param->datalen;
|
|
|
|
/* calculate the crc of the entire thing + padding */
|
|
uint32_t zero = 0;
|
|
uint32_t sum = crc32(0, (const void *)&phys.flags, 8);
|
|
sum = crc32(sum, (const void *)param->name, strlen(param->name));
|
|
if (strlen(param->name) % 4)
|
|
sum = crc32(sum, (const void *)&zero, 4 - (strlen(param->name) % 4));
|
|
sum = crc32(sum, (const void *)param->data, ROUNDUP(param->datalen, 4));
|
|
LTRACEF("crc is 0x%x\n", sum);
|
|
phys.crc32 = sum;
|
|
|
|
/* write the param out, a piece at a time */
|
|
/* structure portion */
|
|
flash_nor_write_pending(params.flash_bank->num, pos, sizeof(struct sysparam_phys), &phys);
|
|
pos += sizeof(struct sysparam_phys);
|
|
|
|
/* name portion */
|
|
flash_nor_write_pending(params.flash_bank->num, pos, ROUNDUP(strlen(param->name), 2), param->name);
|
|
pos += ROUNDUP(strlen(param->name), 2);
|
|
if (pos % 4) {
|
|
/* write 2 zeros to realign */
|
|
flash_nor_write_pending(params.flash_bank->num, pos, 2, &zero);
|
|
pos += 2;
|
|
}
|
|
|
|
/* data portion */
|
|
flash_nor_write_pending(params.flash_bank->num, pos, ROUNDUP(param->datalen, 4), param->data);
|
|
pos += ROUNDUP(param->datalen, 4);
|
|
}
|
|
|
|
/* write zeros to the rest of the sysparam block */
|
|
uint32_t zero = 0;
|
|
while (pos < params.flash_offset + params.flash_len) {
|
|
flash_nor_write_pending(params.flash_bank->num, pos, sizeof(zero), &zero);
|
|
pos += sizeof(zero);
|
|
}
|
|
|
|
/* flush everything to flash */
|
|
flash_nor_flush(params.flash_bank->num);
|
|
|
|
flash_nor_end(params.flash_bank->num);
|
|
|
|
params.dirty = false;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t sysparam_add(const char *name, const void *value, size_t len)
|
|
{
|
|
struct sysparam *param;
|
|
|
|
param = sysparam_find(name);
|
|
if (param)
|
|
return ERR_ALREADY_EXISTS;
|
|
|
|
param = sysparam_create(name, strlen(name), value, len, 0);
|
|
if (!param)
|
|
return ERR_NO_MEMORY;
|
|
|
|
list_add_tail(¶ms.list, ¶m->node);
|
|
|
|
params.dirty = true;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t sysparam_remove(const char *name)
|
|
{
|
|
struct sysparam *param;
|
|
|
|
param = sysparam_find(name);
|
|
if (!param)
|
|
return ERR_NOT_FOUND;
|
|
|
|
if (sysparam_is_locked(param))
|
|
return ERR_NOT_ALLOWED;
|
|
|
|
list_delete(¶m->node);
|
|
|
|
free(param->name);
|
|
free(param->data);
|
|
free(param);
|
|
|
|
params.dirty = true;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t sysparam_lock(const char *name)
|
|
{
|
|
struct sysparam *param;
|
|
|
|
param = sysparam_find(name);
|
|
if (!param)
|
|
return ERR_NOT_FOUND;
|
|
|
|
/* set the lock bit if it isn't already */
|
|
if (!sysparam_is_locked(param)) {
|
|
param->flags |= SYSPARAM_FLAG_LOCK;
|
|
params.dirty = true;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#endif // SYSPARAM_ALLOW_WRITE
|
|
|
|
#define MAX_DUMP_LEN 16
|
|
|
|
void sysparam_dump(bool show_all)
|
|
{
|
|
printf("system parameters:\n");
|
|
|
|
size_t total_memlen = 0;
|
|
|
|
struct sysparam *param;
|
|
list_for_every_entry(¶ms.list, param, struct sysparam, node) {
|
|
printf("________%c %-16s : ",
|
|
(param->flags & SYSPARAM_FLAG_LOCK) ? 'L' : '_',
|
|
param->name);
|
|
|
|
const uint8_t *dat = (const uint8_t *)param->data;
|
|
uint32_t pr_len = param->datalen;
|
|
|
|
if (!show_all) {
|
|
if (pr_len > MAX_DUMP_LEN)
|
|
pr_len = MAX_DUMP_LEN;
|
|
}
|
|
|
|
for (uint i = 0; i < pr_len; i++) {
|
|
printf("%02x", dat[i]);
|
|
}
|
|
if (pr_len != param->datalen)
|
|
printf("...\n");
|
|
else
|
|
printf("\n");
|
|
|
|
total_memlen += param->memlen;
|
|
}
|
|
|
|
printf("total in-memory usage: %zu bytes\n", total_memlen);
|
|
}
|
|
|
|
#if WITH_LIB_CONSOLE
|
|
|
|
#include <lib/console.h>
|
|
#include <ctype.h>
|
|
|
|
static ssize_t hexstr_to_val(const char *str, uint8_t **buf)
|
|
{
|
|
/* parse the value parameter as a hex code */
|
|
uint8_t *hexbuffer = calloc(1, strlen(str) / 2 + 1);
|
|
uint pos;
|
|
for (pos = 0; str[pos] != 0; pos++) {
|
|
uint8_t c = str[pos];
|
|
|
|
if (!isxdigit(c)) {
|
|
return ERR_NOT_VALID;
|
|
}
|
|
|
|
if (c >= '0' && c <= '9')
|
|
c -= '0';
|
|
else if (c >= 'a' && c <= 'f')
|
|
c -= 'a' - 0xa;
|
|
else if (c >= 'A' && c <= 'F')
|
|
c -= 'A' - 0xa;
|
|
|
|
hexbuffer[pos / 2] |= (!(pos % 2)) ? (c << 4) : c;
|
|
}
|
|
pos = (pos + 1) / 2; /* round down, keeping partial bytes */
|
|
|
|
*buf = hexbuffer;
|
|
return pos;
|
|
}
|
|
|
|
static int cmd_sysparam(int argc, const cmd_args *argv)
|
|
{
|
|
status_t err;
|
|
|
|
if (argc < 2) {
|
|
notenoughargs:
|
|
printf("ERROR not enough arguments\n");
|
|
usage:
|
|
printf("usage: %s dump\n", argv[0].str);
|
|
printf("usage: %s list\n", argv[0].str);
|
|
printf("usage: %s reload\n", argv[0].str);
|
|
#if SYSPARAM_ALLOW_WRITE
|
|
printf("usage: %s add <param> <string value>\n", argv[0].str);
|
|
printf("usage: %s addhex <param> <hex value>\n", argv[0].str);
|
|
printf("usage: %s addlong <param>\n", argv[0].str);
|
|
printf("usage: %s remove <param>\n", argv[0].str);
|
|
printf("usage: %s lock <param>\n", argv[0].str);
|
|
printf("usage: %s write\n", argv[0].str);
|
|
#endif
|
|
printf("usage: %s length <param>\n", argv[0].str);
|
|
printf("usage: %s read <param>\n", argv[0].str);
|
|
return -1;
|
|
}
|
|
|
|
err = NO_ERROR;
|
|
if (!strcmp(argv[1].str, "dump")) {
|
|
sysparam_dump(true);
|
|
} else if (!strcmp(argv[1].str, "list")) {
|
|
struct sysparam *param;
|
|
list_for_every_entry(¶ms.list, param, struct sysparam, node) {
|
|
printf("%s\n", param->name);
|
|
}
|
|
} else if (!strcmp(argv[1].str, "reload")) {
|
|
err = sysparam_reload();
|
|
#if SYSPARAM_ALLOW_WRITE
|
|
} else if (!strcmp(argv[1].str, "add")) {
|
|
if (argc < 4) goto notenoughargs;
|
|
|
|
err = sysparam_add(argv[2].str, argv[3].str, strlen(argv[3].str));
|
|
} else if (!strcmp(argv[1].str, "addhex")) {
|
|
if (argc < 4) goto notenoughargs;
|
|
|
|
/* parse the value parameter as a hex code */
|
|
uint8_t *hexbuffer;
|
|
|
|
ssize_t len = hexstr_to_val(argv[3].str, &hexbuffer);
|
|
if (len < 0) {
|
|
err = ERR_INVALID_ARGS;
|
|
goto done;
|
|
}
|
|
|
|
err = sysparam_add(argv[2].str, hexbuffer, len);
|
|
free(hexbuffer);
|
|
} else if (!strcmp(argv[1].str, "addlong")) {
|
|
if (argc < 3) goto notenoughargs;
|
|
|
|
char *str;
|
|
ssize_t buflen = 64;
|
|
ssize_t len = 0;
|
|
str = malloc(buflen + 1);
|
|
if (!str) {
|
|
err = ERR_NO_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
for (;;) {
|
|
int c = getchar();
|
|
if (err < 0)
|
|
break;
|
|
if (c == '\r')
|
|
continue;
|
|
if (c == '\04') /* ^d */
|
|
break;
|
|
if (c == '\n')
|
|
break;
|
|
|
|
if (len == buflen) {
|
|
buflen *= 2;
|
|
char *origstr = str;
|
|
str = realloc(str, buflen + 1);
|
|
if (!str) {
|
|
err = ERR_NO_MEMORY;
|
|
free(origstr);
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
str[len++] = c;
|
|
}
|
|
str[len] = '\0';
|
|
|
|
/* parse the value parameter as a hex code */
|
|
uint8_t *hexbuffer;
|
|
|
|
len = hexstr_to_val(str, &hexbuffer);
|
|
|
|
free(str);
|
|
|
|
if (len < 0) {
|
|
err = ERR_INVALID_ARGS;
|
|
goto done;
|
|
}
|
|
|
|
err = sysparam_add(argv[2].str, hexbuffer, len);
|
|
|
|
free(hexbuffer);
|
|
} else if (!strcmp(argv[1].str, "remove")) {
|
|
if (argc < 3) goto notenoughargs;
|
|
|
|
err = sysparam_remove(argv[2].str);
|
|
} else if (!strcmp(argv[1].str, "lock")) {
|
|
if (argc < 3) goto notenoughargs;
|
|
|
|
err = sysparam_lock(argv[2].str);
|
|
} else if (!strcmp(argv[1].str, "write")) {
|
|
err = sysparam_write();
|
|
#endif // SYSPARAM_ALLOW_WRITE
|
|
} else if (!strcmp(argv[1].str, "length")) {
|
|
if (argc < 3) goto notenoughargs;
|
|
ssize_t len = sysparam_length(argv[2].str);
|
|
if (len >= 0) {
|
|
printf("%zd\n", len);
|
|
}
|
|
err = (len >= 0) ? NO_ERROR : len;
|
|
} else if (!strcmp(argv[1].str, "read")) {
|
|
if (argc < 3) goto notenoughargs;
|
|
ssize_t len = sysparam_length(argv[2].str);
|
|
if (len < 0) {
|
|
err = len;
|
|
goto done;
|
|
}
|
|
uint8_t *buf = malloc(len);
|
|
if (!buf) {
|
|
err = ERR_NO_MEMORY;
|
|
goto done;
|
|
}
|
|
len = sysparam_read(argv[2].str, buf, len);
|
|
if (len < 0) {
|
|
err = len;
|
|
goto done;
|
|
}
|
|
err = NO_ERROR;
|
|
|
|
for (int i = 0; i < len; i++)
|
|
printf("%02x", buf[i]);
|
|
printf("\n");
|
|
free(buf);
|
|
} else {
|
|
printf("ERROR unknown command\n");
|
|
goto usage;
|
|
}
|
|
|
|
done:
|
|
/* shared error reporting */
|
|
if (err >= NO_ERROR) {
|
|
printf("OK\n");
|
|
} else if (err == ERR_NO_MEMORY) {
|
|
printf("ERROR out of memory\n");
|
|
} else if (err == ERR_ALREADY_EXISTS) {
|
|
printf("ERROR already exists\n");
|
|
} else if (err == ERR_INVALID_ARGS) {
|
|
printf("ERROR invalid argument\n");
|
|
} else if (err == ERR_NOT_FOUND) {
|
|
printf("ERROR not found\n");
|
|
} else if (err == ERR_NOT_ALLOWED) {
|
|
printf("ERROR not allowed (locked)\n");
|
|
} else {
|
|
printf("ERROR generic error %d\n", err);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
STATIC_COMMAND_START
|
|
{ "sysparam", "commands for manipulating system parameters", &cmd_sysparam },
|
|
STATIC_COMMAND_END(sysparam);
|
|
|
|
#endif // WITH_LIB_CONSOLE
|