5853b157f3f14710209235d3774848a330ae2724
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>
18 #include <linux/lzo.h>
20 #include "routerboot.h"
22 #define RB_BLOCK_SIZE 0x1000
23 #define RB_ART_SIZE 0x10000
24 #define RB_MAGIC_ERD 0x00455244 /* extended radio data */
26 static struct rb_info rb_info
;
28 static u32
get_u32(void *buf
)
32 return ((u32
) p
[3] + ((u32
) p
[2] << 8) + ((u32
) p
[1] << 16) +
36 static u16
get_u16(void *buf
)
40 return (u16
) p
[1] + ((u16
) p
[0] << 8);
44 routerboot_find_magic(u8
*buf
, unsigned int buflen
, u32
*offset
, bool hard
)
46 u32 magic_ref
= hard
? RB_MAGIC_HARD
: RB_MAGIC_SOFT
;
50 while (cur
< buflen
) {
51 magic
= get_u32(buf
+ cur
);
52 if (magic
== magic_ref
) {
64 routerboot_find_tag(u8
*buf
, unsigned int buflen
, u16 tag_id
,
65 u8
**tag_data
, u16
*tag_len
)
80 /* skip magic value */
89 /* skip magic and CRC value */
115 if (id
== RB_ID_TERMINATOR
)
141 rb_find_hard_cfg_tag(u16 tag_id
, u8
**tag_data
, u16
*tag_len
)
143 if (!rb_info
.hard_cfg_data
||
144 !rb_info
.hard_cfg_size
)
147 return routerboot_find_tag(rb_info
.hard_cfg_data
,
148 rb_info
.hard_cfg_size
,
149 tag_id
, tag_data
, tag_len
);
153 rb_get_board_name(void)
159 err
= rb_find_hard_cfg_tag(RB_ID_BOARD_NAME
, &tag
, &tag_len
);
167 rb_get_hw_options(void)
173 err
= rb_find_hard_cfg_tag(RB_ID_HW_OPTIONS
, &tag
, &tag_len
);
181 __rb_get_wlan_data(u16 id
)
191 err
= rb_find_hard_cfg_tag(RB_ID_WLAN_DATA
, &tag
, &tag_len
);
193 pr_err("no calibration data found\n");
197 buf
= kmalloc(RB_ART_SIZE
, GFP_KERNEL
);
199 pr_err("no memory for calibration data\n");
203 magic
= get_u32(tag
);
204 if (magic
== RB_MAGIC_ERD
) {
211 err
= routerboot_find_tag(tag
, tag_len
, id
,
212 &erd_data
, &erd_len
);
214 pr_err("no ERD data found for id %u\n", id
);
218 dst_done
= RB_ART_SIZE
;
219 err
= lzo1x_decompress_safe(erd_data
, erd_len
, buf
, &dst_done
);
221 pr_err("unable to decompress calibration data %d\n",
229 err
= rle_decode((char *) tag
, tag_len
, buf
, RB_ART_SIZE
,
230 &src_done
, &dst_done
);
232 pr_err("unable to decode calibration data\n");
246 rb_get_wlan_data(void)
248 return __rb_get_wlan_data(0);
252 rb_get_ext_wlan_data(u16 id
)
254 return __rb_get_wlan_data(id
);
257 __init
const struct rb_info
*
258 rb_init_info(void *data
, unsigned int size
)
262 if (size
== 0 || (size
% RB_BLOCK_SIZE
) != 0)
265 for (offset
= 0; offset
< size
; offset
+= RB_BLOCK_SIZE
) {
268 magic
= get_u32(data
+ offset
);
271 rb_info
.hard_cfg_offs
= offset
;
275 rb_info
.soft_cfg_offs
= offset
;
280 if (!rb_info
.hard_cfg_offs
) {
281 pr_err("could not find a valid RouterBOOT hard config\n");
285 if (!rb_info
.soft_cfg_offs
) {
286 pr_err("could not find a valid RouterBOOT soft config\n");
290 rb_info
.hard_cfg_size
= RB_BLOCK_SIZE
;
291 rb_info
.hard_cfg_data
= kmemdup(data
+ rb_info
.hard_cfg_offs
,
292 RB_BLOCK_SIZE
, GFP_KERNEL
);
293 if (!rb_info
.hard_cfg_data
)
296 rb_info
.board_name
= rb_get_board_name();
297 rb_info
.hw_options
= rb_get_hw_options();