X-Git-Url: https://git.archive.openwrt.org/?p=openwrt.git;a=blobdiff_plain;f=target%2Flinux%2Far71xx%2Ffiles%2Farch%2Fmips%2Fath79%2Frouterboot.c;h=dbdec02056a0e869fa8403589edd92db09ae3b01;hp=1cb1f9d4ebdf3702897c7ee09e2f2e7d83afa876;hb=25c6fad2b7ec877b10f09b32a0ce0f36bd8ce3f8;hpb=78b43e814f2410abbe87bd7e493dd24578b0adca diff --git a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c index 1cb1f9d4eb..dbdec02056 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c @@ -8,12 +8,21 @@ * by the Free Software Foundation. */ +#define pr_fmt(fmt) "rb: " fmt + #include +#include #include #include +#include #include "routerboot.h" +#define RB_BLOCK_SIZE 0x1000 +#define RB_ART_SIZE 0x10000 + +static struct rb_info rb_info; + static u32 get_u32(void *buf) { u8 *p = buf; @@ -118,3 +127,123 @@ routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id, return ret; } + +static inline int +rb_find_hard_cfg_tag(u16 tag_id, u8 **tag_data, u16 *tag_len) +{ + if (!rb_info.hard_cfg_data || + !rb_info.hard_cfg_size) + return -ENOENT; + + return routerboot_find_tag(rb_info.hard_cfg_data, + rb_info.hard_cfg_size, + tag_id, tag_data, tag_len); +} + +__init const char * +rb_get_board_name(void) +{ + u16 tag_len; + u8 *tag; + int err; + + err = rb_find_hard_cfg_tag(RB_ID_BOARD_NAME, &tag, &tag_len); + if (err) + return NULL; + + return tag; +} + +__init u32 +rb_get_hw_options(void) +{ + u16 tag_len; + u8 *tag; + int err; + + err = rb_find_hard_cfg_tag(RB_ID_HW_OPTIONS, &tag, &tag_len); + if (err) + return 0; + + return get_u32(tag); +} + +__init void * +rb_get_wlan_data(void) +{ + u16 tag_len; + u8 *tag; + void *buf; + int err; + + err = rb_find_hard_cfg_tag(RB_ID_WLAN_DATA, &tag, &tag_len); + if (err) { + pr_err("no calibration data found\n"); + goto err; + } + + buf = kmalloc(RB_ART_SIZE, GFP_KERNEL); + if (buf == NULL) { + pr_err("no memory for calibration data\n"); + goto err; + } + + err = rle_decode((char *) tag, tag_len, buf, RB_ART_SIZE, + NULL, NULL); + if (err) { + pr_err("unable to decode calibration data\n"); + goto err_free; + } + + return buf; + +err_free: + kfree(buf); +err: + return NULL; +} + +__init const struct rb_info * +rb_init_info(void *data, unsigned int size) +{ + unsigned int offset; + + if (size == 0 || (size % RB_BLOCK_SIZE) != 0) + return NULL; + + for (offset = 0; offset < size; offset += RB_BLOCK_SIZE) { + u32 magic; + + magic = get_u32(data + offset); + switch (magic) { + case RB_MAGIC_HARD: + rb_info.hard_cfg_offs = offset; + break; + + case RB_MAGIC_SOFT: + rb_info.soft_cfg_offs = offset; + break; + } + } + + if (!rb_info.hard_cfg_offs) { + pr_err("could not find a valid RouterBOOT hard config\n"); + return NULL; + } + + if (!rb_info.soft_cfg_offs) { + pr_err("could not find a valid RouterBOOT soft config\n"); + return NULL; + } + + rb_info.hard_cfg_size = RB_BLOCK_SIZE; + rb_info.hard_cfg_data = kmemdup(data + rb_info.hard_cfg_offs, + RB_BLOCK_SIZE, GFP_KERNEL); + if (!rb_info.hard_cfg_data) + return NULL; + + rb_info.board_name = rb_get_board_name(); + rb_info.hw_options = rb_get_hw_options(); + + return &rb_info; +}