2 * Initialization and support routines for self-booting
5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * $Id: load.c,v 1.24.10.1 2010-10-13 04:00:32 Exp $
35 void c_main(unsigned long ra
);
37 extern unsigned char text_start
[], text_end
[];
38 extern unsigned char data_start
[], data_end
[];
39 extern char bss_start
[], bss_end
[];
41 #define INBUFSIZ 4096 /* Buffer size */
42 #define WSIZE 0x8000 /* window size--must be a power of two, and */
43 /* at least 32K for zip's deflate method */
45 static uchar
*inbuf
; /* input buffer */
46 #if !defined(USE_LZMA)
47 static ulong insize
; /* valid bytes in inbuf */
48 static ulong inptr
; /* index of next byte to be processed in inbuf */
51 static uchar
*outbuf
; /* output buffer */
52 static ulong bytes_out
; /* valid bytes in outbuf */
54 static uint32
*inbase
; /* input data from flash */
56 #if !defined(USE_LZMA)
60 for (insize
= 0; insize
< INBUFSIZ
; insize
+= sizeof(uint32
), inbase
++)
61 *((uint32
*)&inbuf
[insize
]) = *inbase
;
67 /* Defines for gzip/bzip */
68 #define malloc(size) MALLOC(NULL, size)
69 #define free(addr) MFREE(NULL, addr, 0)
74 printf("\n\n%s\n\n -- System halted", x
);
89 #define memzero(s, n) memset ((s), 0, (n))
91 typedef unsigned char uch
;
92 typedef unsigned short ush
;
93 typedef unsigned long ulg
;
95 #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
97 /* Diagnostic functions (stubbed out) */
99 #define Assert(cond, msg)
104 #define Tracecv(c, x)
106 static uchar
*window
; /* Sliding window buffer */
107 static unsigned outcnt
; /* bytes in window buffer */
110 gzip_mark(void **ptr
)
112 /* I'm not sure what the pourpose of this is, there are no malloc
113 * calls without free's in the gunzip code.
118 gzip_release(void **ptr
)
122 static void flush_window(void);
124 #include "gzip_inflate.c"
126 /* ===========================================================================
127 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
128 * (Used for the decompressed data only.)
138 out
= &outbuf
[bytes_out
];
139 for (n
= 0; n
< outcnt
; n
++) {
141 c
= crc_32_tab
[((int)c
^ ch
) & 0xff] ^ (c
>> 8);
144 bytes_out
+= (ulg
)outcnt
;
149 #elif defined(USE_BZIP2)
151 #include "bzip2_inflate.c"
157 void bz_internal_error(int i
)
161 sprintf(msg
, "Bzip2 internal error: %d", i
);
171 bzstream
.bzalloc
= 0;
174 bzstream
.avail_in
= 0;
176 if ((ret
= BZ2_bzDecompressInit(&bzstream
, 0, 1)) != BZ_OK
)
180 if (bzstream
.avail_in
== 0) {
182 bzstream
.next_in
= inbuf
;
183 bzstream
.avail_in
= insize
;
185 bzstream
.next_out
= &outbuf
[bytes_out
];
186 bzstream
.avail_out
= WSIZE
;
187 if ((ret
= BZ2_bzDecompress(&bzstream
)) != BZ_OK
)
189 bytes_out
= bzstream
.total_out_lo32
;
193 if (ret
== BZ_STREAM_END
)
194 ret
= BZ2_bzDecompressEnd(&bzstream
);
201 #elif defined(USE_LZMA)
204 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
206 static void *SzAlloc(void *p
, size_t size
) { p
= p
; return malloc(size
); }
207 static void SzFree(void *p
, void *address
) { p
= p
; free(address
); }
208 static ISzAlloc g_Alloc
= { SzAlloc
, SzFree
};
212 * call LZMA decoder to decompress a LZMA block
215 decompressLZMA(unsigned char *src
, unsigned int srcLen
, unsigned char *dest
, unsigned int destLen
)
222 if (srcLen
< LZMA_HEADER_SIZE
)
223 return SZ_ERROR_INPUT_EOF
;
225 inSizePure
= srcLen
- LZMA_HEADER_SIZE
;
227 res
= LzmaDecode(dest
, &outSize
, src
+ LZMA_HEADER_SIZE
, &inSizePure
,
228 src
, LZMA_PROPS_SIZE
, LZMA_FINISH_ANY
, &status
, &g_Alloc
);
229 srcLen
= inSizePure
+ LZMA_HEADER_SIZE
;
231 if ((res
== SZ_OK
) ||
232 ((res
== SZ_ERROR_INPUT_EOF
) && (srcLen
== inSizePure
+ LZMA_HEADER_SIZE
)))
237 #endif /* defined(USE_GZIP) */
239 extern char input_data
[];
240 extern int input_len
;
246 #ifdef NFLASH_SUPPORT
248 struct nflash
*nfl_info
;
249 uchar
*copy_buf
, *nand_ptr
;
250 int copy_len
, offset
, len
;
253 /* Offset from beginning of flash */
255 inoff
= ((ulong
)text_end
- (ulong
)text_start
) + ((ulong
)input_data
- (ulong
)data_start
);
257 inoff
= (ulong
)input_data
- (ulong
)text_start
;
258 #endif /* CONFIG_XIP */
259 #ifdef NFLASH_SUPPORT
260 if ((sih
->ccrev
== 38) && ((sih
->chipst
& (1 << 4)) != 0)) {
261 cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
262 nfl_info
= nflash_init(sih
, cc
);
264 nand_ptr
= OSL_CACHED(SI_FLASH1
);
265 /* 512KB of buffer ahead of LOADADDR */
266 copy_buf
= (unsigned char *)(LOADADDR
- 0x80000);
267 inbase
= (uint32
*)(copy_buf
+ inoff
);
268 copy_len
= inoff
+ input_len
;
270 while (copy_len
> 0) {
271 if (nflash_checkbadb(sih
, cc
, offset
) != 0) {
272 offset
+= nfl_info
->blocksize
;
275 len
= (copy_len
< nfl_info
->blocksize
)?
276 copy_len
: nfl_info
->blocksize
;
277 memcpy(copy_buf
, nand_ptr
+ offset
, len
);
284 #endif /* NFLASH_SUPPORT */
285 if (sih
->ccrev
== 12)
286 inbase
= OSL_UNCACHED(SI_FLASH2
+ inoff
);
288 inbase
= OSL_CACHED(SI_FLASH2
+ inoff
);
290 outbuf
= (uchar
*)LOADADDR
;
292 inbuf
= malloc(INBUFSIZ
); /* input buffer */
294 #if defined(USE_GZIP)
295 window
= malloc(WSIZE
);
296 printf("Decompressing...");
299 #elif defined(USE_BZIP2)
300 /* Small decompression algorithm uses up to 2300k of memory */
301 printf("Decompressing...");
303 #elif defined(USE_LZMA)
304 printf("Decompressing...");
305 bytes_out
= (ulong
)_memsize
- (ulong
)PHYSADDR(outbuf
);
306 ret
= decompressLZMA((unsigned char *)inbase
, input_len
, outbuf
, bytes_out
);
308 printf("Copying...");
309 while (bytes_out
< input_len
) {
311 memcpy(&outbuf
[bytes_out
], inbuf
, insize
);
314 #endif /* defined(USE_GZIP) */
316 printf("error %d\n", ret
);
322 set_sflash_div(si_t
*sih
)
326 struct nvram_header
*nvh
= NULL
;
328 uint32 fltype
, off
, clkdiv
, bpclock
, sflmaxclk
, sfldiv
;
330 /* Check for sflash */
331 idx
= si_coreidx(sih
);
332 cc
= si_setcoreidx(sih
, SI_CC_IDX
);
335 #ifdef NFLASH_SUPPORT
336 if ((sih
->ccrev
== 38) && ((sih
->chipst
& (1 << 4)) != 0))
338 #endif /* NFLASH_SUPPORT */
339 fltype
= sih
->cccaps
& CC_CAP_FLASH_MASK
;
340 if ((fltype
!= SFLASH_ST
) && (fltype
!= SFLASH_AT
))
343 flbase
= (uintptr
)OSL_UNCACHED((void *)SI_FLASH2
);
345 while (off
<= 16 * 1024 * 1024) {
346 nvh
= (struct nvram_header
*)(flbase
+ off
- NVRAM_SPACE
);
347 if (R_REG(osh
, &nvh
->magic
) == NVRAM_MAGIC
)
354 nvh
= (struct nvram_header
*)(flbase
+ 1024);
355 if (R_REG(osh
, &nvh
->magic
) != NVRAM_MAGIC
) {
360 sflmaxclk
= R_REG(osh
, &nvh
->crc_ver_init
) >> 16;
361 if ((sflmaxclk
== 0xffff) || (sflmaxclk
== 0x0419))
368 bpclock
= si_clock(sih
);
369 sflmaxclk
*= 10000000;
370 for (sfldiv
= 2; sfldiv
< 16; sfldiv
+= 2) {
371 if ((bpclock
/ sfldiv
) < sflmaxclk
)
377 clkdiv
= R_REG(osh
, &cc
->clkdiv
);
378 if (((clkdiv
& CLKD_SFLASH
) >> CLKD_SFLASH_SHIFT
) != sfldiv
) {
379 clkdiv
= (clkdiv
& ~CLKD_SFLASH
) | (sfldiv
<< CLKD_SFLASH_SHIFT
);
380 W_REG(osh
, &cc
->clkdiv
, clkdiv
);
384 si_setcoreidx(sih
, idx
);
389 c_main(unsigned long ra
)
393 BCMDBG_TRACE(0x4c4400);
396 /* Discover cache configuration and if not already on,
397 * initialize and turn them on.
400 #endif /* CFG_UNCACHED */
402 BCMDBG_TRACE(0x4c4401);
404 /* Basic initialization */
405 sih
= (si_t
*)osl_init();
407 BCMDBG_TRACE(0x4c4402);
409 /* Only do this for newer chips, since the SB ones did not have
410 * space in the nvram header for the sflash divider.
412 if (sih
->socitype
== SOCI_AI
)
415 BCMDBG_TRACE(0x4c4403);
420 BCMDBG_TRACE(0x4c4404);
422 /* Flush all caches */
426 BCMDBG_TRACE(0x4c4405);
428 /* Jump to load address */
429 ((void (*)(void))LOADADDR
)();