2 * Initialization and support routines for self-booting
5 * Copyright (C) 2012, 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 368663 2012-11-14 09:42:37Z $
35 extern void cpu_inv_cache_all(void);
37 void c_main(unsigned long ra
);
39 extern unsigned char text_start
[], text_end
[];
40 extern unsigned char data_start
[], data_end
[];
41 extern char bss_start
[], bss_end
[];
43 #define INBUFSIZ 4096 /* Buffer size */
44 #define WSIZE 0x8000 /* window size--must be a power of two, and */
45 /* at least 32K for zip's deflate method */
47 static uchar
*inbuf
; /* input buffer */
48 #if !defined(USE_LZMA)
49 static ulong insize
; /* valid bytes in inbuf */
50 static ulong inptr
; /* index of next byte to be processed in inbuf */
53 static uchar
*outbuf
; /* output buffer */
54 static ulong bytes_out
; /* valid bytes in outbuf */
56 static uint32
*inbase
; /* input data from flash */
58 #if !defined(USE_LZMA)
62 for (insize
= 0; insize
< INBUFSIZ
; insize
+= sizeof(uint32
), inbase
++)
63 *((uint32
*)&inbuf
[insize
]) = *inbase
;
69 /* Defines for gzip/bzip */
70 #define malloc(size) MALLOC(NULL, size)
71 #define free(addr) MFREE(NULL, addr, 0)
76 printf("\n\n%s\n\n -- System halted", x
);
91 #define memzero(s, n) memset ((s), 0, (n))
93 typedef unsigned char uch
;
94 typedef unsigned short ush
;
95 typedef unsigned long ulg
;
97 #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
99 /* Diagnostic functions (stubbed out) */
101 #define Assert(cond, msg)
106 #define Tracecv(c, x)
108 static uchar
*window
; /* Sliding window buffer */
109 static unsigned outcnt
; /* bytes in window buffer */
112 gzip_mark(void **ptr
)
114 /* I'm not sure what the pourpose of this is, there are no malloc
115 * calls without free's in the gunzip code.
120 gzip_release(void **ptr
)
124 static void flush_window(void);
126 #include "gzip_inflate.c"
128 /* ===========================================================================
129 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
130 * (Used for the decompressed data only.)
140 out
= &outbuf
[bytes_out
];
141 for (n
= 0; n
< outcnt
; n
++) {
143 c
= crc_32_tab
[((int)c
^ ch
) & 0xff] ^ (c
>> 8);
146 bytes_out
+= (ulg
)outcnt
;
151 #elif defined(USE_BZIP2)
153 #include "bzip2_inflate.c"
159 void bz_internal_error(int i
)
163 sprintf(msg
, "Bzip2 internal error: %d", i
);
173 bzstream
.bzalloc
= 0;
176 bzstream
.avail_in
= 0;
178 if ((ret
= BZ2_bzDecompressInit(&bzstream
, 0, 1)) != BZ_OK
)
182 if (bzstream
.avail_in
== 0) {
184 bzstream
.next_in
= inbuf
;
185 bzstream
.avail_in
= insize
;
187 bzstream
.next_out
= &outbuf
[bytes_out
];
188 bzstream
.avail_out
= WSIZE
;
189 if ((ret
= BZ2_bzDecompress(&bzstream
)) != BZ_OK
)
191 bytes_out
= bzstream
.total_out_lo32
;
195 if (ret
== BZ_STREAM_END
)
196 ret
= BZ2_bzDecompressEnd(&bzstream
);
203 #elif defined(USE_LZMA)
206 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
208 static void *SzAlloc(void *p
, size_t size
) { p
= p
; return malloc(size
); }
209 static void SzFree(void *p
, void *address
) { p
= p
; free(address
); }
210 static ISzAlloc g_Alloc
= { SzAlloc
, SzFree
};
214 * call LZMA decoder to decompress a LZMA block
217 decompressLZMA(unsigned char *src
, unsigned int srcLen
, unsigned char *dest
, unsigned int destLen
)
224 if (srcLen
< LZMA_HEADER_SIZE
)
225 return SZ_ERROR_INPUT_EOF
;
227 inSizePure
= srcLen
- LZMA_HEADER_SIZE
;
229 res
= LzmaDecode(dest
, &outSize
, src
+ LZMA_HEADER_SIZE
, &inSizePure
,
230 src
, LZMA_PROPS_SIZE
, LZMA_FINISH_ANY
, &status
, &g_Alloc
);
231 srcLen
= inSizePure
+ LZMA_HEADER_SIZE
;
233 if ((res
== SZ_OK
) ||
234 ((res
== SZ_ERROR_INPUT_EOF
) && (srcLen
== inSizePure
+ LZMA_HEADER_SIZE
)))
241 #endif /* defined(USE_GZIP) */
243 extern char input_data
[], input_data_end
[];
244 extern int input_len
;
254 inoff
= ((ulong
)text_end
- (ulong
)text_start
) + ((ulong
)input_data
- (ulong
)data_start
);
255 if (sih
->ccrev
== 12)
256 inbase
= OSL_UNCACHED(SI_FLASH2
+ inoff
);
258 inbase
= OSL_CACHED(SI_FLASH2
+ inoff
);
259 image_len
= input_len
;
261 #if defined(CFG_SHMOO)
265 inoff
= (ulong
)input_data
- (ulong
)text_start
;
266 bootdev
= soc_boot_dev((void *)sih
);
267 if (bootdev
== SOC_BOOTDEV_NANDFLASH
)
268 inbase
= (uint32
*)(SI_NS_NANDFLASH
+ inoff
);
270 inbase
= (uint32
*)(SI_NS_NORFLASH
+ inoff
);
271 image_len
= *(uint32
*)((ulong
)inbase
- 4);
273 inbase
= (uint32
*)input_data
;
274 image_len
= input_len
;
275 #endif /* CFG_SHMOO */
276 #endif /* CONFIG_XIP */
278 outbuf
= (uchar
*)LOADADDR
;
280 inbuf
= malloc(INBUFSIZ
); /* input buffer */
282 #if defined(USE_GZIP)
283 window
= malloc(WSIZE
);
284 printf("Decompressing...");
287 #elif defined(USE_BZIP2)
288 /* Small decompression algorithm uses up to 2300k of memory */
289 printf("Decompressing...");
291 #elif defined(USE_LZMA)
292 printf("Decompressing...");
293 bytes_out
= (ulong
)_memsize
- (ulong
)PHYSADDR(outbuf
);
294 ret
= decompressLZMA((unsigned char *)inbase
, image_len
, outbuf
, bytes_out
);
296 printf("Copying...");
297 while (bytes_out
< image_len
) {
299 memcpy(&outbuf
[bytes_out
], inbuf
, insize
);
302 #endif /* defined(USE_GZIP) */
304 printf("error %d\n", ret
);
310 set_sflash_div(si_t
*sih
)
314 struct nvram_header
*nvh
= NULL
;
316 uint32 fltype
, off
, clkdiv
, bpclock
, sflmaxclk
, sfldiv
;
318 /* Check for sflash */
319 idx
= si_coreidx(sih
);
320 cc
= si_setcoreidx(sih
, SI_CC_IDX
);
323 #ifdef NFLASH_SUPPORT
324 if ((sih
->ccrev
== 38) && ((sih
->chipst
& (1 << 4)) != 0))
326 #endif /* NFLASH_SUPPORT */
327 fltype
= sih
->cccaps
& CC_CAP_FLASH_MASK
;
328 if ((fltype
!= SFLASH_ST
) && (fltype
!= SFLASH_AT
))
331 flbase
= (uintptr
)OSL_UNCACHED((void *)SI_FLASH2
);
333 while (off
<= 16 * 1024 * 1024) {
334 nvh
= (struct nvram_header
*)(flbase
+ off
- MAX_NVRAM_SPACE
);
335 if (R_REG(osh
, &nvh
->magic
) == NVRAM_MAGIC
)
337 off
+= DEF_NVRAM_SPACE
;
342 nvh
= (struct nvram_header
*)(flbase
+ 1024);
343 if (R_REG(osh
, &nvh
->magic
) != NVRAM_MAGIC
) {
348 sflmaxclk
= R_REG(osh
, &nvh
->crc_ver_init
) >> 16;
349 if ((sflmaxclk
== 0xffff) || (sflmaxclk
== 0x0419))
356 bpclock
= si_clock(sih
);
357 sflmaxclk
*= 10000000;
358 for (sfldiv
= 2; sfldiv
< 16; sfldiv
+= 2) {
359 if ((bpclock
/ sfldiv
) < sflmaxclk
)
365 clkdiv
= R_REG(osh
, &cc
->clkdiv
);
366 if (((clkdiv
& CLKD_SFLASH
) >> CLKD_SFLASH_SHIFT
) != sfldiv
) {
367 clkdiv
= (clkdiv
& ~CLKD_SFLASH
) | (sfldiv
<< CLKD_SFLASH_SHIFT
);
368 W_REG(osh
, &cc
->clkdiv
, clkdiv
);
372 si_setcoreidx(sih
, idx
);
377 c_main(unsigned long ra
)
381 BCMDBG_TRACE(0x4c4400);
384 /* Discover cache configuration and if not already on,
385 * initialize and turn them on.
390 #endif /* CFG_UNCACHED */
392 BCMDBG_TRACE(0x4c4401);
394 /* Basic initialization */
395 sih
= (si_t
*)osl_init();
397 BCMDBG_TRACE(0x4c4402);
399 /* Only do this for 4716, we need to reuse the
400 * space in the nvram header for TREF on 5357.
402 if ((CHIPID(sih
->chip
) == BCM4716_CHIP_ID
) ||
403 (CHIPID(sih
->chip
) == BCM4748_CHIP_ID
) ||
404 (CHIPID(sih
->chip
) == BCM47162_CHIP_ID
))
407 BCMDBG_TRACE(0x4c4403);
412 BCMDBG_TRACE(0x4c4404);
414 /* Flush all caches */
418 BCMDBG_TRACE(0x4c4405);
420 /* Jump to load address */
421 ((void (*)(void))LOADADDR
)();