1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * RAW Program Loader File: cfe_ldr_raw.c
6 * This program reads raw binaries into memory.
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
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"
55 #include "cfe_device.h"
56 #include "cfe_error.h"
57 #include "cfe_devfuncs.h"
60 #include "cfe_fileops.h"
63 #include "cfe_bootblock.h"
65 #include "cfe_loader.h"
67 /* *********************************************************************
69 ********************************************************************* */
71 static int cfe_rawload(cfe_loadargs_t
*la
);
73 const cfe_loader_t rawloader
= {
78 /* *********************************************************************
79 * cfe_findbootblock(la,fsctx,ref)
81 * Find the boot block on the specified device.
84 * la - loader args (to be filled in)
85 * ops - file operations
86 * ref - reference for open file handle
91 ********************************************************************* */
92 static int cfe_findbootblock(cfe_loadargs_t
*la
,
95 struct boot_block
*bootblock
)
97 uint32_t checksum
= 0;
100 uint64_t secoffset
= 0;
105 * Search for the boot block. Stop when we find
106 * something with a matching checksum and magic
110 fs_seek(fsctx
,ref
,0,FILE_SEEK_BEGINNING
);
112 for (curblk
= 0; curblk
< BOOT_BLOCK_MAXLOC
; curblk
++) {
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
) {
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
) {
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.
167 /* *********************************************************************
170 * Read a raw (unformatted) boot file
176 * 0 if ok, else error code
177 ********************************************************************* */
178 static int cfe_rawload(cfe_loadargs_t
*la
)
182 const fileio_dispatch_t
*ops
;
187 struct boot_block bootblock
;
190 uint32_t checksum
,calcsum
;
191 uint64_t secoffset
= 0;
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 */
217 bootcode
= (uint8_t *) BOOT_START_ADDRESS
;
218 maxsize
= BOOT_AREA_SIZE
;
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
) )) {
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
);
259 * Turn on compression if we're doing that.
262 if (!findbb
&& (la
->la_flags
& LOADFLG_COMPRESSED
)) {
268 * Check compression method
270 res
= fs_open(fsctx
, &ref
, la
->la_filename
, FILE_MODE_READ
);
274 len
= fs_read(fsctx
, ref
, c
, 2);
275 fs_close(fsctx
, ref
);
282 if (memcmp(c
, "\x1f\x8b", 2) == 0)
287 if (memcmp(c
, "\x5d\x00", 2) == 0)
292 xprintf("Image compressed with unsupported method\n");
293 res
= CFE_ERR_UNSUPPORTED
;
297 res
= fs_hook(fsctx
, zh
);
303 * Open the boot device
306 res
= fs_open(fsctx
,&ref
,la
->la_filename
,FILE_MODE_READ
);
311 * If we need to find a boot block, do it now.
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.
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
);
336 * Okay, go load the boot file.
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) {
349 if (thisamt
> amtcopy
) thisamt
= amtcopy
;
351 res
= fs_read(fsctx
,ref
,ptr
,thisamt
);
352 if (la
->la_flags
& LOADFLG_NOISY
) {
362 * We're done with the file.
369 * Verify the boot loader checksum if we were reading
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
;