Skip to content
Snippets Groups Projects
cmd_bootm.c 41.8 KiB
Newer Older
Wolfgang Denk's avatar
Wolfgang Denk committed
/*
 * (C) Copyright 2000-2006
Wolfgang Denk's avatar
Wolfgang Denk committed
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

/*
 * Boot support
 */
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <image.h>
#include <malloc.h>
#include <zlib.h>
#include <bzlib.h>
#include <environment.h>
Wolfgang Denk's avatar
Wolfgang Denk committed
#include <asm/byteorder.h>
Wolfgang Denk's avatar
Wolfgang Denk committed

#if defined(CONFIG_OF_LIBFDT)
#include <fdt.h>
#include <libfdt.h>
#include <fdt_support.h>
#if defined(CONFIG_OF_FLAT_TREE)
#include <ft_build.h>
#endif

/*cmd_boot.c*/
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
Wolfgang Denk's avatar
Wolfgang Denk committed

#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
Wolfgang Denk's avatar
Wolfgang Denk committed
#include <rtc.h>
#endif

#ifdef CFG_HUSH_PARSER
#include <hush.h>
#endif

#ifdef CFG_INIT_RAM_LOCK
#include <asm/cache.h>
#endif

#ifdef CONFIG_LOGBUFFER
#include <logbuff.h>
#endif

#ifdef CONFIG_HAS_DATAFLASH
#include <dataflash.h>
#endif

Wolfgang Denk's avatar
Wolfgang Denk committed
/*
 * Some systems (for example LWMON) have very short watchdog periods;
 * we must make sure to split long operations like memmove() or
 * crc32() into reasonable chunks.
 */
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
# define CHUNKSZ (64 * 1024)
#endif

int  gunzip (void *, int, unsigned char *, unsigned long *);
Wolfgang Denk's avatar
Wolfgang Denk committed

static void *zalloc(void *, unsigned, unsigned);
static void zfree(void *, void *, unsigned);

Wolfgang Denk's avatar
Wolfgang Denk committed
static int image_info (unsigned long addr);
#endif
#if defined(CONFIG_CMD_IMLS)
extern flash_info_t flash_info[]; /* info for FLASH chips */
static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#endif

Wolfgang Denk's avatar
Wolfgang Denk committed
static void print_type (image_header_t *hdr);

#ifdef __I386__
image_header_t *fake_header(image_header_t *hdr, void *ptr, int size);
#endif

Wolfgang Denk's avatar
Wolfgang Denk committed
/*
 *  Continue booting an OS image; caller already has:
 *  - copied image header to global variable `header'
 *  - checked header magic number, checksums (both header & image),
 *  - verified image architecture (PPC) and type (KERNEL or MULTI),
 *  - loaded (first part of) image to header load address,
 *  - disabled interrupts.
 */
typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag,
			  int	argc, char *argv[],
			  ulong	addr,		/* of image to boot */
			  ulong	*len_ptr,	/* multi-file image length table */
			  int	verify);	/* getenv("verify")[0] != 'n' */

Wolfgang Denk's avatar
Wolfgang Denk committed
#ifdef	DEBUG
extern int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#endif

#ifdef CONFIG_PPC
Wolfgang Denk's avatar
Wolfgang Denk committed
static boot_os_Fcn do_bootm_linux;
#else
extern boot_os_Fcn do_bootm_linux;
#endif
#ifdef CONFIG_SILENT_CONSOLE
static void fixup_silent_linux (void);
#endif
Wolfgang Denk's avatar
Wolfgang Denk committed
static boot_os_Fcn do_bootm_netbsd;
static boot_os_Fcn do_bootm_rtems;
Wolfgang Denk's avatar
Wolfgang Denk committed
static boot_os_Fcn do_bootm_vxworks;
static boot_os_Fcn do_bootm_qnxelf;
int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
static boot_os_Fcn do_bootm_artos;
#endif
#ifdef CONFIG_LYNXKDI
static boot_os_Fcn do_bootm_lynxkdi;
extern void lynxkdi_boot( image_header_t * );
#endif
Wolfgang Denk's avatar
Wolfgang Denk committed

#ifndef CFG_BOOTM_LEN
#define CFG_BOOTM_LEN	0x800000	/* use 8MByte as default max gunzip size */
#endif

Wolfgang Denk's avatar
Wolfgang Denk committed
image_header_t header;

ulong load_addr = CFG_LOAD_ADDR;		/* Default Load Address */

int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	ulong	iflag;
	ulong	addr;
	ulong	data, len, checksum;
	ulong  *len_ptr;
	uint	unc_len = CFG_BOOTM_LEN;
Wolfgang Denk's avatar
Wolfgang Denk committed
	int	i, verify;
	char	*name, *s;
Wolfgang Denk's avatar
Wolfgang Denk committed
	image_header_t *hdr = &header;

	s = getenv ("verify");
	verify = (s && (*s == 'n')) ? 0 : 1;

	if (argc < 2) {
		addr = load_addr;
	} else {
		addr = simple_strtoul(argv[1], NULL, 16);
	}

	show_boot_progress (1);
Wolfgang Denk's avatar
Wolfgang Denk committed
	printf ("## Booting image at %08lx ...\n", addr);

	/* Copy header so we can blank CRC field for re-calculation */
#ifdef CONFIG_HAS_DATAFLASH
	if (addr_dataflash(addr)){
		read_dataflash(addr, sizeof(image_header_t), (char *)&header);
	} else
#endif
Wolfgang Denk's avatar
Wolfgang Denk committed
	memmove (&header, (char *)addr, sizeof(image_header_t));

	if (ntohl(hdr->ih_magic) != IH_MAGIC) {
#ifdef __I386__	/* correct image format not implemented yet - fake it */
		if (fake_header(hdr, (void*)addr, -1) != NULL) {
			/* to compensate for the addition below */
			addr -= sizeof(image_header_t);
			/* turnof verify,
			 * fake_header() does not fake the data crc
			 */
			verify = 0;
		} else
#endif	/* __I386__ */
	    {
		puts ("Bad Magic Number\n");
		show_boot_progress (-1);
Wolfgang Denk's avatar
Wolfgang Denk committed
		return 1;
Wolfgang Denk's avatar
Wolfgang Denk committed
	}
	show_boot_progress (2);
Loading
Loading full blame...