diff options
Diffstat (limited to 'package/rbcfg/src/main.c')
-rw-r--r-- | package/rbcfg/src/main.c | 791 |
1 files changed, 0 insertions, 791 deletions
diff --git a/package/rbcfg/src/main.c b/package/rbcfg/src/main.c deleted file mode 100644 index 5614a6c..0000000 --- a/package/rbcfg/src/main.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * RouterBOOT configuration utility - * - * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stddef.h> -#include <stdint.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/stat.h> -#include <linux/limits.h> - -#include "rbcfg.h" -#include "cyg_crc.h" - -#define RBCFG_TMP_FILE "/tmp/.rbcfg" -#define RBCFG_MTD_NAME "soft_config" - -#define RB_ERR_NOTFOUND 1 -#define RB_ERR_INVALID 2 -#define RB_ERR_NOMEM 3 -#define RB_ERR_IO 4 - -#define ARRAY_SIZE(_a) (sizeof((_a)) / sizeof((_a)[0])) - -struct rbcfg_ctx { - char *mtd_device; - char *tmp_file; - char *buf; - unsigned buflen; -}; - -struct rbcfg_value { - const char *name; - const char *desc; - union { - uint32_t u32; - const char *raw; - } val; -}; - -#define RBCFG_ENV_TYPE_U32 0 - -struct rbcfg_env { - const char *name; - int type; - uint16_t id; - const struct rbcfg_value *values; - int num_values; -}; - -#define CMD_FLAG_USES_CFG 0x01 - -struct rbcfg_command { - const char *command; - const char *usage; - int flags; - int (*exec)(int argc, const char *argv[]); -}; - -static void usage(void); - -/* Globals */ - -static struct rbcfg_ctx *rbcfg_ctx; -static char *rbcfg_name; - -#define CFG_U32(_name, _desc, _val) { \ - .name = (_name), \ - .desc = (_desc), \ - .val.u32 = (_val), \ -} - -static const struct rbcfg_value rbcfg_boot_delay[] = { - CFG_U32("1", "1 second", RB_BOOT_DELAY_1SEC), - CFG_U32("2", "2 seconds", RB_BOOT_DELAY_2SEC), - CFG_U32("3", "3 seconds", RB_BOOT_DELAY_3SEC), - CFG_U32("4", "4 seconds", RB_BOOT_DELAY_4SEC), - CFG_U32("5", "5 seconds", RB_BOOT_DELAY_5SEC), - CFG_U32("6", "6 seconds", RB_BOOT_DELAY_6SEC), - CFG_U32("7", "7 seconds", RB_BOOT_DELAY_7SEC), - CFG_U32("8", "8 seconds", RB_BOOT_DELAY_8SEC), - CFG_U32("9", "9 seconds", RB_BOOT_DELAY_9SEC), -}; - -static const struct rbcfg_value rbcfg_boot_device[] = { - CFG_U32("eth", "boot over Ethernet", - RB_BOOT_DEVICE_ETHER), - CFG_U32("nandeth", "boot from NAND, if fail then Ethernet", - RB_BOOT_DEVICE_NANDETH), - CFG_U32("ethnand", "boot Ethernet once, then NAND", - RB_BOOT_DEVICE_ETHONCE), - CFG_U32("nand", "boot from NAND only", - RB_BOOT_DEVICE_NANDONLY), -}; - -static const struct rbcfg_value rbcfg_boot_key[] = { - CFG_U32("any", "any key", RB_BOOT_KEY_ANY), - CFG_U32("del", "<Delete> key only", RB_BOOT_KEY_DEL), -}; - -static const struct rbcfg_value rbcfg_boot_protocol[] = { - CFG_U32("bootp", "BOOTP protocol", RB_BOOT_PROTOCOL_BOOTP), - CFG_U32("dhcp", "DHCP protocol", RB_BOOT_PROTOCOL_DHCP), -}; - -static const struct rbcfg_value rbcfg_uart_speed[] = { - CFG_U32("115200", "", RB_UART_SPEED_115200), - CFG_U32("57600", "", RB_UART_SPEED_57600), - CFG_U32("38400", "", RB_UART_SPEED_38400), - CFG_U32("19200", "", RB_UART_SPEED_19200), - CFG_U32("9600", "", RB_UART_SPEED_9600), - CFG_U32("4800", "", RB_UART_SPEED_4800), - CFG_U32("2400", "", RB_UART_SPEED_2400), - CFG_U32("1200", "", RB_UART_SPEED_1200), - CFG_U32("off", "disable console output", RB_UART_SPEED_OFF), -}; - -static const struct rbcfg_value rbcfg_cpu_mode[] = { - CFG_U32("powersave", "power save", RB_CPU_MODE_POWERSAVE), - CFG_U32("regular", "regular (better for -0c environment)", - RB_CPU_MODE_REGULAR), -}; - -static const struct rbcfg_value rbcfg_booter[] = { - CFG_U32("regular", "load regular booter", RB_BOOTER_REGULAR), - CFG_U32("backup", "force backup-booter loading", RB_BOOTER_BACKUP), -}; - -static const struct rbcfg_env rbcfg_envs[] = { - { - .name = "boot_delay", - .id = RB_ID_BOOT_DELAY, - .type = RBCFG_ENV_TYPE_U32, - .values = rbcfg_boot_delay, - .num_values = ARRAY_SIZE(rbcfg_boot_delay), - }, { - .name = "boot_device", - .id = RB_ID_BOOT_DEVICE, - .type = RBCFG_ENV_TYPE_U32, - .values = rbcfg_boot_device, - .num_values = ARRAY_SIZE(rbcfg_boot_device), - }, { - .name = "boot_key", - .id = RB_ID_BOOT_KEY, - .type = RBCFG_ENV_TYPE_U32, - .values = rbcfg_boot_key, - .num_values = ARRAY_SIZE(rbcfg_boot_key), - }, { - .name = "boot_protocol", - .id = RB_ID_BOOT_PROTOCOL, - .type = RBCFG_ENV_TYPE_U32, - .values = rbcfg_boot_protocol, - .num_values = ARRAY_SIZE(rbcfg_boot_protocol), - }, { - .name = "booter", - .id = RB_ID_BOOTER, - .type = RBCFG_ENV_TYPE_U32, - .values = rbcfg_booter, - .num_values = ARRAY_SIZE(rbcfg_booter), - }, { - .name = "cpu_mode", - .id = RB_ID_CPU_MODE, - .type = RBCFG_ENV_TYPE_U32, - .values = rbcfg_cpu_mode, - .num_values = ARRAY_SIZE(rbcfg_cpu_mode), - }, { - .name = "uart_speed", - .id = RB_ID_UART_SPEED, - .type = RBCFG_ENV_TYPE_U32, - .values = rbcfg_uart_speed, - .num_values = ARRAY_SIZE(rbcfg_uart_speed), - } -}; - -static inline uint16_t -get_u16(const void *buf) -{ - const uint8_t *p = buf; - - return ((uint16_t) p[1] + ((uint16_t) p[0] << 8)); -} - -static inline uint32_t -get_u32(const void *buf) -{ - const uint8_t *p = buf; - - return ((uint32_t) p[3] + ((uint32_t) p[2] << 8) + - ((uint32_t) p[1] << 16) + ((uint32_t) p[0] << 24)); -} - -static inline void -put_u32(void *buf, uint32_t val) -{ - uint8_t *p = buf; - - p[3] = val & 0xff; - p[2] = (val >> 8) & 0xff; - p[1] = (val >> 16) & 0xff; - p[0] = (val >> 24) & 0xff; -} - -static int -rbcfg_find_tag(struct rbcfg_ctx *ctx, uint16_t tag_id, uint16_t *tag_len, - void **tag_data) -{ - uint16_t id; - uint16_t len; - char *buf = ctx->buf; - unsigned int buflen = ctx->buflen; - int ret = RB_ERR_NOTFOUND; - - /* skip magic and CRC value */ - buf += 8; - buflen -= 8; - - while (buflen > 2) { - len = get_u16(buf); - buf += 2; - buflen -= 2; - - if (buflen < 2) - break; - - id = get_u16(buf); - buf += 2; - buflen -= 2; - - if (id == RB_ID_TERMINATOR) - break; - - if (buflen < len) - break; - - if (id == tag_id) { - *tag_len = len; - *tag_data = buf; - ret = 0; - break; - } - - buf += len; - buflen -= len; - } - - if (ret) - fprintf(stderr, "no tag found with id=%u\n", tag_id); - - return ret; -} - -static int -rbcfg_get_u32(struct rbcfg_ctx *ctx, uint16_t id, uint32_t *val) -{ - void *tag_data; - uint16_t tag_len; - int err; - - err = rbcfg_find_tag(ctx, id, &tag_len, &tag_data); - if (err) - return err; - - *val = get_u32(tag_data); - return 0; -} - -static int -rbcfg_set_u32(struct rbcfg_ctx *ctx, uint16_t id, uint32_t val) -{ - void *tag_data; - uint16_t tag_len; - int err; - - err = rbcfg_find_tag(ctx, id, &tag_len, &tag_data); - if (err) - return err; - - put_u32(tag_data, val); - return 0; -} - -char *rbcfg_find_mtd(const char *name, int *erase_size) -{ - FILE *f; - int mtd_num; - char dev[PATH_MAX]; - char *ret = NULL; - struct stat s; - int err; - - f = fopen("/proc/mtd", "r"); - if (!f) - return NULL; - - while (1) { - char *p; - p = fgets(dev, sizeof(dev), f); - if (!p) - break; - - if (!strstr(dev, name)) - continue; - - err = sscanf(dev, "mtd%d: %08x", &mtd_num, erase_size); - if (err != 2) - break; - - sprintf(dev, "/dev/mtdblock%d", mtd_num); - err = stat(dev, &s); - if (err < 0) - break; - - if ((s.st_mode & S_IFBLK) == 0) - break; - - ret = malloc(strlen(dev) + 1); - if (ret == NULL) - break; - - strncpy(ret, dev, strlen(dev) + 1); - break; - } - - fclose(f); - return ret; -} - -static int -rbcfg_check_tmp(struct rbcfg_ctx *ctx) -{ - struct stat s; - int err; - - err = stat(ctx->tmp_file, &s); - if (err < 0) - return 0; - - if ((s.st_mode & S_IFREG) == 0) - return 0; - - if (s.st_size != ctx->buflen) - return 0; - - return 1; -} - -static int -rbcfg_load(struct rbcfg_ctx *ctx) -{ - uint32_t magic; - uint32_t crc_orig, crc; - char *name; - int tmp; - int fd; - int err; - - tmp = rbcfg_check_tmp(ctx); - name = (tmp) ? ctx->tmp_file : ctx->mtd_device; - - fd = open(name, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "unable to open %s\n", name); - err = RB_ERR_IO; - goto err; - } - - err = read(fd, ctx->buf, ctx->buflen); - if (err != ctx->buflen) { - fprintf(stderr, "unable to read from %s\n", name); - err = RB_ERR_IO; - goto err_close; - } - - magic = get_u32(ctx->buf); - if (magic != RB_MAGIC_SOFT) { - fprintf(stderr, "invalid configuration\n"); - err = RB_ERR_INVALID; - goto err_close; - } - - crc_orig = get_u32(ctx->buf + 4); - put_u32(ctx->buf + 4, 0); - crc = cyg_ether_crc32((unsigned char *) ctx->buf, ctx->buflen); - if (crc != crc_orig) { - fprintf(stderr, "configuration has CRC error\n"); - err = RB_ERR_INVALID; - goto err_close; - } - - err = 0; - - err_close: - close(fd); - err: - return err; -} - -static int -rbcfg_open() -{ - char *mtd_device; - struct rbcfg_ctx *ctx; - int buflen; - int err; - - mtd_device = rbcfg_find_mtd(RBCFG_MTD_NAME, &buflen); - if (!mtd_device) { - fprintf(stderr, "unable to find configuration\n"); - return RB_ERR_NOTFOUND; - } - - ctx = malloc(sizeof(struct rbcfg_ctx) + buflen); - if (ctx == NULL) { - err = RB_ERR_NOMEM; - goto err_free_mtd; - } - - ctx->mtd_device = mtd_device; - ctx->tmp_file = RBCFG_TMP_FILE; - ctx->buflen = buflen; - ctx->buf = (char *) &ctx[1]; - - err = rbcfg_load(ctx); - if (err) - goto err_free_ctx; - - rbcfg_ctx = ctx; - return 0; - - err_free_ctx: - free(ctx); - err_free_mtd: - free(mtd_device); - return err; -} - -static int -rbcfg_update(int tmp) -{ - struct rbcfg_ctx *ctx = rbcfg_ctx; - char *name; - uint32_t crc; - int fd; - int err; - - put_u32(ctx->buf, RB_MAGIC_SOFT); - put_u32(ctx->buf + 4, 0); - crc = cyg_ether_crc32((unsigned char *) ctx->buf, ctx->buflen); - put_u32(ctx->buf + 4, crc); - - name = (tmp) ? ctx->tmp_file : ctx->mtd_device; - fd = open(name, O_WRONLY | O_CREAT); - if (fd < 0) { - fprintf(stderr, "unable to open %s for writing\n", name); - err = RB_ERR_IO; - goto out; - } - - err = write(fd, ctx->buf, ctx->buflen); - if (err != ctx->buflen) { - err = RB_ERR_IO; - goto out_close; - } - - fsync(fd); - err = 0; - - out_close: - close(fd); - out: - return err; -} - -static void -rbcfg_close(void) -{ - struct rbcfg_ctx *ctx; - - ctx = rbcfg_ctx; - free(ctx->mtd_device); - free(ctx); -} - -static const struct rbcfg_value * -rbcfg_env_find(const struct rbcfg_env *env, const char *name) -{ - unsigned i; - - for (i = 0; i < env->num_values; i++) { - const struct rbcfg_value *v = &env->values[i]; - - if (strcmp(v->name, name) == 0) - return v; - } - - return NULL; -} - -static const struct rbcfg_value * -rbcfg_env_find_u32(const struct rbcfg_env *env, uint32_t val) -{ - unsigned i; - - for (i = 0; i < env->num_values; i++) { - const struct rbcfg_value *v = &env->values[i]; - - if (v->val.u32 == val) - return v; - } - - return NULL; -} - -static const char * -rbcfg_env_get_u32(const struct rbcfg_env *env) -{ - const struct rbcfg_value *v; - uint32_t val; - int err; - - err = rbcfg_get_u32(rbcfg_ctx, env->id, &val); - if (err) - return NULL; - - v = rbcfg_env_find_u32(env, val); - if (v == NULL) { - fprintf(stderr, "unknown value %08x found for %s\n", - val, env->name); - return NULL; - } - - return v->name; -} - -static int -rbcfg_env_set_u32(const struct rbcfg_env *env, const char *data) -{ - const struct rbcfg_value *v; - int err; - - v = rbcfg_env_find(env, data); - if (v == NULL) { - fprintf(stderr, "invalid value '%s'\n", data); - return RB_ERR_INVALID; - } - - err = rbcfg_set_u32(rbcfg_ctx, env->id, v->val.u32); - return err; -} - -static const char * -rbcfg_env_get(const struct rbcfg_env *env) -{ - const char *ret = NULL; - - switch (env->type) { - case RBCFG_ENV_TYPE_U32: - ret = rbcfg_env_get_u32(env); - break; - } - - return ret; -} - -static int -rbcfg_env_set(const struct rbcfg_env *env, const char *data) -{ - int ret = 0; - - switch (env->type) { - case RBCFG_ENV_TYPE_U32: - ret = rbcfg_env_set_u32(env, data); - break; - } - - return ret; -} - -static int -rbcfg_cmd_apply(int argc, const char *argv[]) -{ - return rbcfg_update(0); -} - -static int -rbcfg_cmd_help(int argc, const char *argv[]) -{ - usage(); - return 0; -} - -static int -rbcfg_cmd_get(int argc, const char *argv[]) -{ - int err = RB_ERR_NOTFOUND; - int i; - - if (argc != 1) { - usage(); - return RB_ERR_INVALID; - } - - for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) { - const struct rbcfg_env *env = &rbcfg_envs[i]; - const char *value; - - if (strcmp(env->name, argv[0])) - continue; - - value = rbcfg_env_get(env); - if (value) { - fprintf(stdout, "%s\n", value); - err = 0; - } - break; - } - - return err; -} - -static int -rbcfg_cmd_set(int argc, const char *argv[]) -{ - int err = RB_ERR_INVALID; - int i; - - if (argc != 2) { - /* not enough parameters */ - usage(); - return RB_ERR_INVALID; - } - - for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) { - const struct rbcfg_env *env = &rbcfg_envs[i]; - - if (strcmp(env->name, argv[0])) - continue; - - err = rbcfg_env_set(env, argv[1]); - if (err == 0) - err = rbcfg_update(1); - break; - } - - return err; -} - -static int -rbcfg_cmd_show(int argc, const char *argv[]) -{ - int i; - - if (argc != 0) { - usage(); - return RB_ERR_INVALID; - } - - for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) { - const struct rbcfg_env *env = &rbcfg_envs[i]; - const char *value; - - value = rbcfg_env_get(env); - if (value) - fprintf(stdout, "%s=%s\n", env->name, value); - } - - return 0; -} - -static const struct rbcfg_command rbcfg_commands[] = { - { - .command = "apply", - .usage = "apply\n" - "\t- write configuration to the mtd device", - .flags = CMD_FLAG_USES_CFG, - .exec = rbcfg_cmd_apply, - }, { - .command = "help", - .usage = "help\n" - "\t- show this screen", - .exec = rbcfg_cmd_help, - }, { - .command = "get", - .usage = "get <name>\n" - "\t- get value of the configuration option <name>", - .flags = CMD_FLAG_USES_CFG, - .exec = rbcfg_cmd_get, - }, { - .command = "set", - .usage = "set <name> <value>\n" - "\t- set value of the configuration option <name> to <value>", - .flags = CMD_FLAG_USES_CFG, - .exec = rbcfg_cmd_set, - }, { - .command = "show", - .usage = "show\n" - "\t- show value of all configuration options", - .flags = CMD_FLAG_USES_CFG, - .exec = rbcfg_cmd_show, - } -}; - -static void -usage(void) -{ - char buf[255]; - int len; - int i; - - fprintf(stderr, "Usage: %s <command>\n", rbcfg_name); - - fprintf(stderr, "\nCommands:\n"); - for (i = 0; i < ARRAY_SIZE(rbcfg_commands); i++) { - const struct rbcfg_command *cmd; - cmd = &rbcfg_commands[i]; - - len = snprintf(buf, sizeof(buf), cmd->usage); - buf[len] = '\0'; - fprintf(stderr, "%s\n", buf); - } - - fprintf(stderr, "\nConfiguration options:\n"); - for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) { - const struct rbcfg_env *env; - int j; - - env = &rbcfg_envs[i]; - fprintf(stderr, "\n%s:\n", env->name); - for (j = 0; j < env->num_values; j++) { - const struct rbcfg_value *v = &env->values[j]; - fprintf(stderr, "\t%-12s %s\n", v->name, v->desc); - } - } - fprintf(stderr, "\n"); -} - -int main(int argc, const char *argv[]) -{ - const struct rbcfg_command *cmd = NULL; - int ret; - int i; - - rbcfg_name = (char *) argv[0]; - - if (argc < 2) { - usage(); - return EXIT_FAILURE; - } - - for (i = 0; i < ARRAY_SIZE(rbcfg_commands); i++) { - if (strcmp(rbcfg_commands[i].command, argv[1]) == 0) { - cmd = &rbcfg_commands[i]; - break; - } - } - - if (cmd == NULL) { - fprintf(stderr, "unknown command '%s'\n", argv[1]); - usage(); - return EXIT_FAILURE; - } - - argc -= 2; - argv += 2; - - if (cmd->flags & CMD_FLAG_USES_CFG) { - ret = rbcfg_open(); - if (ret) - return EXIT_FAILURE; - } - - ret = cmd->exec(argc, argv); - - if (cmd->flags & CMD_FLAG_USES_CFG) - rbcfg_close(); - - if (ret) - return EXIT_FAILURE; - - return EXIT_SUCCESS; -} |