RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / main / cfe_ldr_raw.c
blob1041dd8fd5072f97453afda80a65f4ce67daa5ad
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * RAW Program Loader File: cfe_ldr_raw.c
5 *
6 * This program reads raw binaries into memory.
7 *
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
9 *
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
48 #include "lib_types.h"
49 #include "lib_string.h"
50 #include "lib_queue.h"
51 #include "lib_malloc.h"
52 #include "lib_printf.h"
54 #include "cfe_iocb.h"
55 #include "cfe_device.h"
56 #include "cfe_error.h"
57 #include "cfe_devfuncs.h"
59 #include "cfe.h"
60 #include "cfe_fileops.h"
62 #include "cfe_boot.h"
63 #include "cfe_bootblock.h"
65 #include "cfe_loader.h"
67 /* *********************************************************************
68 * Externs
69 ********************************************************************* */
71 static int cfe_rawload(cfe_loadargs_t *la);
73 const cfe_loader_t rawloader = {
74 "raw",
75 cfe_rawload,
76 0};
78 /* *********************************************************************
79 * cfe_findbootblock(la,fsctx,ref)
81 * Find the boot block on the specified device.
83 * Input parameters:
84 * la - loader args (to be filled in)
85 * ops - file operations
86 * ref - reference for open file handle
88 * Return value:
89 * 0 if ok
90 * else error code
91 ********************************************************************* */
92 static int cfe_findbootblock(cfe_loadargs_t *la,
93 fileio_ctx_t *fsctx,
94 void *ref,
95 struct boot_block *bootblock)
97 uint32_t checksum = 0;
98 uint32_t calcsum = 0;
99 uint32_t secsize = 0;
100 uint64_t secoffset = 0;
101 int res;
102 int curblk;
105 * Search for the boot block. Stop when we find
106 * something with a matching checksum and magic
107 * number.
110 fs_seek(fsctx,ref,0,FILE_SEEK_BEGINNING);
112 for (curblk = 0; curblk < BOOT_BLOCK_MAXLOC; curblk++) {
115 /* Read a block */
117 res = fs_read(fsctx,ref,
118 (unsigned char *) bootblock,
119 sizeof(struct boot_block));
121 if (res != sizeof(struct boot_block)) {
122 return CFE_ERR_IOERR;
125 /* Verify magic number */
127 if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) {
128 continue;
131 /* Extract fields from block */
133 checksum = ((uint32_t) (bootblock->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK));
134 bootblock->bb_hdrinfo &= ~BOOT_HDR_CHECKSUM_MASK;
135 secsize = ((uint32_t) (bootblock->bb_secsize & BOOT_SECSIZE_MASK));
136 secoffset = bootblock->bb_secstart;
138 /* Verify block's checksum */
140 CHECKSUM_BOOT_DATA(&(bootblock->bb_magic),BOOT_BLOCK_SIZE,&calcsum);
142 if (checksum == calcsum) {
143 break;
148 * Okay, determine if we were successful.
151 if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) {
152 return CFE_ERR_INVBOOTBLOCK;
155 if (checksum != calcsum) {
156 return CFE_ERR_BBCHECKSUM;
160 * If we get here, we had a valid boot block.
163 return 0;
167 /* *********************************************************************
168 * cfe_rawload(la)
170 * Read a raw (unformatted) boot file
172 * Input parameters:
173 * la - loader args
175 * Return value:
176 * 0 if ok, else error code
177 ********************************************************************* */
178 static int cfe_rawload(cfe_loadargs_t *la)
180 int res;
181 fileio_ctx_t *fsctx;
182 const fileio_dispatch_t *ops;
183 void *ref;
184 int ttlcopy = 0;
185 int findbb;
186 int devinfo;
187 struct boot_block bootblock;
188 uint8_t *ptr;
189 uint8_t *bootcode;
190 uint32_t checksum,calcsum;
191 uint64_t secoffset = 0;
192 int32_t maxsize;
193 int amtcopy;
194 int thisamt;
195 uint32_t loadflags;
196 int onedot;
198 loadflags = la->la_flags;
201 * Set starting address and maximum size. You can either
202 * explicitly set this (with LOADFLG_SPECADDR) or
203 * let CFE decide. If CFE decides, the load address
204 * will be BOOT_START_ADDRESS in all cases.
205 * The size is dependant on the device type: block and flash
206 * devices will get this info from the boot block,
207 * and network devices will get the info by reaching EOF
208 * on reads, up to the maximum size of the boot area.
211 if (loadflags & LOADFLG_SPECADDR) {
212 bootcode = (uint8_t *) la->la_address;
213 maxsize = la->la_maxsize;
214 findbb = FALSE; /* don't find a boot block */
216 else {
217 bootcode = (uint8_t *) BOOT_START_ADDRESS;
218 maxsize = BOOT_AREA_SIZE;
219 findbb = FALSE;
220 devinfo = la->la_device ? cfe_getdevinfo(la->la_device) : 0;
223 * If the device is either a disk or a flash device,
224 * we will expect to find a boot block.
225 * Serial and network devices do not have boot blocks.
227 if ((devinfo >= 0) &&
228 ( ((devinfo & CFE_DEV_MASK) == CFE_DEV_DISK) ||
229 ((devinfo & CFE_DEV_MASK) == CFE_DEV_FLASH) )) {
230 findbb = TRUE;
236 * merge in any filesystem-specific flags
239 ops = cfe_findfilesys(la->la_filesys);
240 if (!ops) return CFE_ERR_FSNOTAVAIL;
241 loadflags |= ops->loadflags;
244 * turn off the boot block if requested.
247 if (loadflags & LOADFLG_NOBB) findbb = FALSE;
250 * Create a file system context
253 res = fs_init(la->la_filesys,&fsctx,la->la_device);
254 if (res != 0) {
255 return res;
259 * Turn on compression if we're doing that.
262 if (!findbb && (la->la_flags & LOADFLG_COMPRESSED)) {
263 uint8_t c[2];
264 int len;
265 char *zh = "z";
268 * Check compression method
270 res = fs_open(fsctx, &ref, la->la_filename, FILE_MODE_READ);
271 if (res != 0)
272 goto errout;
274 len = fs_read(fsctx, ref, c, 2);
275 fs_close(fsctx, ref);
276 if (len != 2) {
277 res = CFE_ERR_IOERR;
278 goto errout;
281 #ifdef CFG_ZLIB
282 if (memcmp(c, "\x1f\x8b", 2) == 0)
283 zh = "z";
284 else
285 #endif
286 #ifdef CFG_LZMA
287 if (memcmp(c, "\x5d\x00", 2) == 0)
288 zh = "lzma";
289 else
290 #endif
292 xprintf("Image compressed with unsupported method\n");
293 res = CFE_ERR_UNSUPPORTED;
294 goto errout;
297 res = fs_hook(fsctx, zh);
298 if (res != 0)
299 goto errout;
303 * Open the boot device
306 res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
307 if (res != 0)
308 goto errout;
311 * If we need to find a boot block, do it now.
314 if (findbb) {
315 res = cfe_findbootblock(la,fsctx,ref,&bootblock);
318 * If we found the boot block, seek to the part of the
319 * disk where the boot code is.
320 * Otherwise, get out now, since the disk has no boot block.
323 if (res == 0) {
324 maxsize = (int) ((uint32_t) (bootblock.bb_secsize & BOOT_SECSIZE_MASK));
325 secoffset = bootblock.bb_secstart;
326 fs_seek(fsctx,ref,secoffset,FILE_SEEK_BEGINNING);
328 else {
329 fs_close(fsctx,ref);
330 goto errout;
336 * Okay, go load the boot file.
339 ptr = bootcode;
340 amtcopy = maxsize;
341 ttlcopy = 0;
343 onedot = amtcopy / 10; /* ten dots for entire load */
344 if (onedot < 4096) onedot = 4096; /* but minimum 4096 bytes per dot */
345 onedot = (onedot + 1) & ~4095; /* round to multiple of 4096 */
347 while (amtcopy > 0) {
348 thisamt = onedot;
349 if (thisamt > amtcopy) thisamt = amtcopy;
351 res = fs_read(fsctx,ref,ptr,thisamt);
352 if (la->la_flags & LOADFLG_NOISY) {
353 xprintf(".");
355 if (res <= 0) break;
356 ptr += res;
357 amtcopy -= res;
358 ttlcopy += res;
362 * We're done with the file.
365 fs_close(fsctx,ref);
366 fs_uninit(fsctx);
369 * Verify the boot loader checksum if we were reading
370 * the disk.
373 if (findbb) {
374 CHECKSUM_BOOT_DATA(bootcode,maxsize,&calcsum);
375 checksum = (uint32_t) ((bootblock.bb_secsize & BOOT_DATA_CHECKSUM_MASK)
376 >> BOOT_DATA_CHECKSUM_SHIFT);
378 if (checksum != calcsum) {
379 return CFE_ERR_BOOTPROGCHKSUM;
383 la->la_entrypt = (uintptr_t) bootcode;
385 if (la->la_flags & LOADFLG_NOISY) xprintf(" %d bytes read\n",ttlcopy);
387 return (res < 0) ? res : ttlcopy;
389 errout:
390 fs_uninit(fsctx);
391 return res;