2 * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
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>
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.
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.
28 #include "LzmaDecode.h"
30 #define KSEG0 0x80000000
31 #define KSEG1 0xa0000000
33 #define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
38 # define DBG(f, a...) printf(f, ## a)
40 # define DBG(f, a...) do {} while (0)
43 /* beyond the image end, size not known in advance */
44 extern unsigned char workspace
[];
47 extern void board_init(void);
49 static CLzmaDecoderState lzma_state
;
50 static unsigned char *lzma_data
;
51 static unsigned long lzma_datasize
;
52 static unsigned long lzma_outsize
;
53 static unsigned long kernel_la
;
55 static void halt(void)
57 printf("\nSystem halted!\n");
61 static __inline__
unsigned char lzma_get_byte(void)
71 static int lzma_init_props(void)
73 unsigned char props
[LZMA_PROPERTIES_SIZE
];
77 /* read lzma properties */
78 for (i
= 0; i
< LZMA_PROPERTIES_SIZE
; i
++)
79 props
[i
] = lzma_get_byte();
81 /* read the lower half of uncompressed size in the header */
82 lzma_outsize
= ((SizeT
) lzma_get_byte()) +
83 ((SizeT
) lzma_get_byte() << 8) +
84 ((SizeT
) lzma_get_byte() << 16) +
85 ((SizeT
) lzma_get_byte() << 24);
87 /* skip rest of the header (upper half of uncompressed size) */
88 for (i
= 0; i
< 4; i
++)
91 res
= LzmaDecodeProperties(&lzma_state
.Properties
, props
,
92 LZMA_PROPERTIES_SIZE
);
96 static int lzma_decompress(unsigned char *outStream
)
101 lzma_state
.Probs
= (CProb
*) workspace
;
103 ret
= LzmaDecode(&lzma_state
, lzma_data
, lzma_datasize
, &ip
, outStream
,
106 if (ret
!= LZMA_RESULT_OK
) {
109 DBG("LzmaDecode error %d at %08x, osize:%d ip:%d op:%d\n",
110 ret
, lzma_data
+ ip
, lzma_outsize
, ip
, op
);
112 for (i
= 0; i
< 16; i
++)
113 DBG("%02x ", lzma_data
[ip
+ i
]);
121 static void lzma_init_data(void)
123 extern unsigned char _lzma_data_start
[];
124 extern unsigned char _lzma_data_end
[];
126 kernel_la
= LOADADDR
;
127 lzma_data
= _lzma_data_start
;
128 lzma_datasize
= _lzma_data_end
- _lzma_data_start
;
131 void loader_main(unsigned long reg_a0
, unsigned long reg_a1
,
132 unsigned long reg_a2
, unsigned long reg_a3
)
134 void (*kernel_entry
) (unsigned long, unsigned long, unsigned long,
140 printf("\n\nOpenWrt kernel loader for BCM63XX\n");
141 printf("Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>\n");
142 printf("Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>\n");
146 res
= lzma_init_props();
147 if (res
!= LZMA_RESULT_OK
) {
148 printf("Incorrect LZMA stream properties!\n");
152 printf("Decompressing kernel... ");
154 res
= lzma_decompress((unsigned char *) kernel_la
);
155 if (res
!= LZMA_RESULT_OK
) {
158 case LZMA_RESULT_DATA_ERROR
:
159 printf("data error!\n");
162 printf("unknown error %d!\n", res
);
169 flush_cache(kernel_la
, lzma_outsize
);
171 printf("Starting kernel at %08x...\n\n", kernel_la
);
173 kernel_entry
= (void *) kernel_la
;
174 kernel_entry(reg_a0
, reg_a1
, reg_a2
, reg_a3
);