OpenWrt – Blame information for rev 4

Subversion Repositories:
Rev:
Rev Author Line No. Line
4 office 1 /*
2 * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
3 *
4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * Some parts of this code was based on the OpenWrt specific lzma-loader
7 * for the BCM47xx and ADM5120 based boards:
8 * Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
9 * Copyright (C) 2005 Mineharu Takahara <mtakahar@yahoo.com>
10 * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
11 *
12 * The image_header structure has been taken from the U-Boot project.
13 * (C) Copyright 2008 Semihalf
14 * (C) Copyright 2000-2005
15 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License version 2 as published
19 * by the Free Software Foundation.
20 */
21  
22 #include <stddef.h>
23 #include <stdint.h>
24 #include <sys/types.h>
25  
26 #include "config.h"
27 #include "cache.h"
28 #include "printf.h"
29 #include "LzmaDecode.h"
30  
31 #define AR71XX_FLASH_START 0x1f000000
32 #define AR71XX_FLASH_END 0x1fe00000
33  
34 #define KSEG0 0x80000000
35 #define KSEG1 0xa0000000
36  
37 #define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
38  
39 #undef LZMA_DEBUG
40  
41 #ifdef LZMA_DEBUG
42 # define DBG(f, a...) printf(f, ## a)
43 #else
44 # define DBG(f, a...) do {} while (0)
45 #endif
46  
47 #define IH_MAGIC_OKLI 0x4f4b4c49 /* 'OKLI' */
48  
49 #define IH_NMLEN 32 /* Image Name Length */
50  
51 typedef struct image_header {
52 uint32_t ih_magic; /* Image Header Magic Number */
53 uint32_t ih_hcrc; /* Image Header CRC Checksum */
54 uint32_t ih_time; /* Image Creation Timestamp */
55 uint32_t ih_size; /* Image Data Size */
56 uint32_t ih_load; /* Data Load Address */
57 uint32_t ih_ep; /* Entry Point Address */
58 uint32_t ih_dcrc; /* Image Data CRC Checksum */
59 uint8_t ih_os; /* Operating System */
60 uint8_t ih_arch; /* CPU architecture */
61 uint8_t ih_type; /* Image Type */
62 uint8_t ih_comp; /* Compression Type */
63 uint8_t ih_name[IH_NMLEN]; /* Image Name */
64 } image_header_t;
65  
66 /* beyond the image end, size not known in advance */
67 extern unsigned char workspace[];
68 extern void board_init(void);
69  
70 static CLzmaDecoderState lzma_state;
71 static unsigned char *lzma_data;
72 static unsigned long lzma_datasize;
73 static unsigned long lzma_outsize;
74 static unsigned long kernel_la;
75  
76 #ifdef CONFIG_KERNEL_CMDLINE
77 #define kernel_argc 2
78 static const char kernel_cmdline[] = CONFIG_KERNEL_CMDLINE;
79 static const char *kernel_argv[] = {
80 NULL,
81 kernel_cmdline,
82 NULL,
83 };
84 #endif /* CONFIG_KERNEL_CMDLINE */
85  
86 static void halt(void)
87 {
88 printf("\nSystem halted!\n");
89 for(;;);
90 }
91  
92 static __inline__ unsigned long get_be32(void *buf)
93 {
94 unsigned char *p = buf;
95  
96 return (((unsigned long) p[0] << 24) +
97 ((unsigned long) p[1] << 16) +
98 ((unsigned long) p[2] << 8) +
99 (unsigned long) p[3]);
100 }
101  
102 static __inline__ unsigned char lzma_get_byte(void)
103 {
104 unsigned char c;
105  
106 lzma_datasize--;
107 c = *lzma_data++;
108  
109 return c;
110 }
111  
112 static int lzma_init_props(void)
113 {
114 unsigned char props[LZMA_PROPERTIES_SIZE];
115 int res;
116 int i;
117  
118 /* read lzma properties */
119 for (i = 0; i < LZMA_PROPERTIES_SIZE; i++)
120 props[i] = lzma_get_byte();
121  
122 /* read the lower half of uncompressed size in the header */
123 lzma_outsize = ((SizeT) lzma_get_byte()) +
124 ((SizeT) lzma_get_byte() << 8) +
125 ((SizeT) lzma_get_byte() << 16) +
126 ((SizeT) lzma_get_byte() << 24);
127  
128 /* skip rest of the header (upper half of uncompressed size) */
129 for (i = 0; i < 4; i++)
130 lzma_get_byte();
131  
132 res = LzmaDecodeProperties(&lzma_state.Properties, props,
133 LZMA_PROPERTIES_SIZE);
134 return res;
135 }
136  
137 static int lzma_decompress(unsigned char *outStream)
138 {
139 SizeT ip, op;
140 int ret;
141  
142 lzma_state.Probs = (CProb *) workspace;
143  
144 ret = LzmaDecode(&lzma_state, lzma_data, lzma_datasize, &ip, outStream,
145 lzma_outsize, &op);
146  
147 if (ret != LZMA_RESULT_OK) {
148 int i;
149  
150 DBG("LzmaDecode error %d at %08x, osize:%d ip:%d op:%d\n",
151 ret, lzma_data + ip, lzma_outsize, ip, op);
152  
153 for (i = 0; i < 16; i++)
154 DBG("%02x ", lzma_data[ip + i]);
155  
156 DBG("\n");
157 }
158  
159 return ret;
160 }
161  
162 #if (LZMA_WRAPPER)
163 static void lzma_init_data(void)
164 {
165 extern unsigned char _lzma_data_start[];
166 extern unsigned char _lzma_data_end[];
167  
168 kernel_la = LOADADDR;
169 lzma_data = _lzma_data_start;
170 lzma_datasize = _lzma_data_end - _lzma_data_start;
171 }
172 #else
173 static void lzma_init_data(void)
174 {
175 struct image_header *hdr = NULL;
176 unsigned char *flash_base;
177 unsigned long flash_ofs;
178 unsigned long kernel_ofs;
179 unsigned long kernel_size;
180  
181 flash_base = (unsigned char *) KSEG1ADDR(AR71XX_FLASH_START);
182  
183 printf("Looking for OpenWrt image... ");
184  
185 for (flash_ofs = CONFIG_FLASH_OFFS;
186 flash_ofs <= (CONFIG_FLASH_OFFS + CONFIG_FLASH_MAX);
187 flash_ofs += CONFIG_FLASH_STEP) {
188 unsigned long magic;
189 unsigned char *p;
190  
191 p = flash_base + flash_ofs;
192 magic = get_be32(p);
193 if (magic == IH_MAGIC_OKLI) {
194 hdr = (struct image_header *) p;
195 break;
196 }
197 }
198  
199 if (hdr == NULL) {
200 printf("not found!\n");
201 halt();
202 }
203  
204 printf("found at 0x%08x\n", flash_base + flash_ofs);
205  
206 kernel_ofs = sizeof(struct image_header);
207 kernel_size = get_be32(&hdr->ih_size);
208 kernel_la = get_be32(&hdr->ih_load);
209  
210 lzma_data = flash_base + flash_ofs + kernel_ofs;
211 lzma_datasize = kernel_size;
212 }
213 #endif /* (LZMA_WRAPPER) */
214  
215 void loader_main(unsigned long reg_a0, unsigned long reg_a1,
216 unsigned long reg_a2, unsigned long reg_a3)
217 {
218 void (*kernel_entry) (unsigned long, unsigned long, unsigned long,
219 unsigned long);
220 int res;
221  
222 board_init();
223  
224 printf("\n\nOpenWrt kernel loader for MIPS based SoC\n");
225 printf("Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>\n");
226  
227 lzma_init_data();
228  
229 res = lzma_init_props();
230 if (res != LZMA_RESULT_OK) {
231 printf("Incorrect LZMA stream properties!\n");
232 halt();
233 }
234  
235 printf("Decompressing kernel... ");
236  
237 res = lzma_decompress((unsigned char *) kernel_la);
238 if (res != LZMA_RESULT_OK) {
239 printf("failed, ");
240 switch (res) {
241 case LZMA_RESULT_DATA_ERROR:
242 printf("data error!\n");
243 break;
244 default:
245 printf("unknown error %d!\n", res);
246 }
247 halt();
248 } else {
249 printf("done!\n");
250 }
251  
252 flush_cache(kernel_la, lzma_outsize);
253  
254 printf("Starting kernel at %08x...\n\n", kernel_la);
255  
256 #ifdef CONFIG_KERNEL_CMDLINE
257 reg_a0 = kernel_argc;
258 reg_a1 = (unsigned long) kernel_argv;
259 reg_a2 = 0;
260 reg_a3 = 0;
261 #endif
262  
263 kernel_entry = (void *) kernel_la;
264 kernel_entry(reg_a0, reg_a1, reg_a2, reg_a3);
265 }