2 * RouterBoot helper routines
4 * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
11 #define pr_fmt(fmt) "rb: " fmt
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/errno.h>
16 #include <linux/routerboot.h>
17 #include <linux/rle.h>
19 #include "routerboot.h"
21 #define RB_BLOCK_SIZE 0x1000
22 #define RB_ART_SIZE 0x10000
24 static struct rb_info rb_info
;
26 static u32
get_u32(void *buf
)
30 return ((u32
) p
[3] + ((u32
) p
[2] << 8) + ((u32
) p
[1] << 16) +
34 static u16
get_u16(void *buf
)
38 return (u16
) p
[1] + ((u16
) p
[0] << 8);
42 routerboot_find_magic(u8
*buf
, unsigned int buflen
, u32
*offset
, bool hard
)
44 u32 magic_ref
= hard
? RB_MAGIC_HARD
: RB_MAGIC_SOFT
;
48 while (cur
< buflen
) {
49 magic
= get_u32(buf
+ cur
);
50 if (magic
== magic_ref
) {
62 routerboot_find_tag(u8
*buf
, unsigned int buflen
, u16 tag_id
,
63 u8
**tag_data
, u16
*tag_len
)
74 /* skip magic value */
83 /* skip magic and CRC value */
109 if (id
== RB_ID_TERMINATOR
)
132 rb_find_hard_cfg_tag(u16 tag_id
, u8
**tag_data
, u16
*tag_len
)
134 if (!rb_info
.hard_cfg_data
||
135 !rb_info
.hard_cfg_size
)
138 return routerboot_find_tag(rb_info
.hard_cfg_data
,
139 rb_info
.hard_cfg_size
,
140 tag_id
, tag_data
, tag_len
);
144 rb_get_board_name(void)
150 err
= rb_find_hard_cfg_tag(RB_ID_BOARD_NAME
, &tag
, &tag_len
);
158 rb_get_hw_options(void)
164 err
= rb_find_hard_cfg_tag(RB_ID_HW_OPTIONS
, &tag
, &tag_len
);
172 rb_get_wlan_data(void)
179 err
= rb_find_hard_cfg_tag(RB_ID_WLAN_DATA
, &tag
, &tag_len
);
181 pr_err("no calibration data found\n");
185 buf
= kmalloc(RB_ART_SIZE
, GFP_KERNEL
);
187 pr_err("no memory for calibration data\n");
191 err
= rle_decode((char *) tag
, tag_len
, buf
, RB_ART_SIZE
,
194 pr_err("unable to decode calibration data\n");
206 __init
const struct rb_info
*
207 rb_init_info(void *data
, unsigned int size
)
211 if (size
== 0 || (size
% RB_BLOCK_SIZE
) != 0)
214 for (offset
= 0; offset
< size
; offset
+= RB_BLOCK_SIZE
) {
217 magic
= get_u32(data
+ offset
);
220 rb_info
.hard_cfg_offs
= offset
;
224 rb_info
.soft_cfg_offs
= offset
;
229 if (!rb_info
.hard_cfg_offs
) {
230 pr_err("could not find a valid RouterBOOT hard config\n");
234 if (!rb_info
.soft_cfg_offs
) {
235 pr_err("could not find a valid RouterBOOT soft config\n");
239 rb_info
.hard_cfg_size
= RB_BLOCK_SIZE
;
240 rb_info
.hard_cfg_data
= kmemdup(data
+ rb_info
.hard_cfg_offs
,
241 RB_BLOCK_SIZE
, GFP_KERNEL
);
242 if (!rb_info
.hard_cfg_data
)
245 rb_info
.board_name
= rb_get_board_name();
246 rb_info
.hw_options
= rb_get_hw_options();