/*
- * (C) Copyright 2000
+ * (C) Copyright 2000, 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
#endif
static void print_type (image_header_t *hdr);
+/*
+ * 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, bd_t *bd, int flag, int argc, char *argv[],
+ ulong addr, /* of image to boot */
+ ulong *len_ptr, /* multi-file image length table */
+ ulong data, /* points to first image */
+ int verify); /* getenv("verify")[0] != 'n' */
+
+static boot_os_Fcn do_bootm_linux;
+static boot_os_Fcn do_bootm_netbsd;
+
image_header_t header;
ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */
{
ulong iflag;
ulong addr;
- ulong sp;
ulong data, len, checksum;
- ulong initrd_start, initrd_end;
- ulong cmd_start, cmd_end;
ulong *len_ptr;
- ulong initrd_high;
int i, verify;
- char *cmdline;
char *name, *s;
- bd_t *kbd;
int (*appl)(cmd_tbl_t *, bd_t *, int, int, char *[]);
- void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
image_header_t *hdr = &header;
s = getenv ("verify");
verify = (s && (*s == 'n')) ? 0 : 1;
- if ((s = getenv ("initrd_high")) != NULL) {
- /* a value of "no" or a similar string will act like 0,
- * turning the "load high" feature off. This is intentional.
- */
- initrd_high = simple_strtoul(s, NULL, 16);
- } else { /* not set, no restrictions to load high */
- initrd_high = ~0;
- }
-
if (argc < 2) {
addr = load_addr;
} else {
#ifdef CONFIG_HERMES
hermes_set_led (1);
#endif
- printf ("## Booting Linux kernel at %08lx ...\n", addr);
+ printf ("## Booting image at %08lx ...\n", addr);
/* Copy header so we can blank CRC field for re-calculation */
memcpy (&header, (char *)addr, sizeof(image_header_t));
hermes_set_led (8);
#endif
+ switch (hdr->ih_os)
+ {
+ default: /* handled by (original) Linux case */
+ case IH_OS_LINUX:
+ do_bootm_linux (cmdtp, bd, flag, argc, argv,
+ addr, len_ptr, data, verify);
+ break;
+ case IH_OS_NETBSD:
+ do_bootm_netbsd (cmdtp, bd, flag, argc, argv,
+ addr, len_ptr, data, verify);
+ break;
+ }
+
+#ifdef DEBUG
+ printf ("\n## Control returned to monitor - resetting...\n");
+ do_reset (cmdtp, bd, flag, argc, argv);
+#endif
+}
+
+static void
+do_bootm_linux (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[],
+ ulong addr,
+ ulong *len_ptr,
+ ulong data,
+ int verify)
+{
+ ulong sp;
+ ulong len, checksum;
+ ulong initrd_start, initrd_end;
+ ulong cmd_start, cmd_end;
+ ulong initrd_high;
+ char *cmdline;
+ char *s;
+ bd_t *kbd;
+ void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
+ image_header_t *hdr = &header;
+
+ if ((s = getenv ("initrd_high")) != NULL) {
+ /* a value of "no" or a similar string will act like 0,
+ * turning the "load high" feature off. This is intentional.
+ */
+ initrd_high = simple_strtoul(s, NULL, 16);
+ } else { /* not set, no restrictions to load high */
+ initrd_high = ~0;
+ }
+
/*
* Booting a (Linux) kernel image
*
* r7: End of command line string
*/
(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
+}
-#ifdef DEBUG
- printf ("\n## Control returned to monitor - resetting...\n");
- do_reset (cmdtp, bd, flag, argc, argv);
+static void
+do_bootm_netbsd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[],
+ ulong addr,
+ ulong *len_ptr,
+ ulong data,
+ int verify)
+{
+ image_header_t *hdr = &header;
+
+ void (*loader)(bd_t *, image_header_t *, char *, char *);
+ image_header_t *img_addr;
+ char *consdev;
+ char *cmdline;
+
+
+ /*
+ * Booting a (NetBSD) kernel image
+ *
+ * This process is pretty similar to a standalone application:
+ * The (first part of an multi-) image must be a stage-2 loader,
+ * which in turn is responsible for loading & invoking the actual
+ * kernel. The only differences are the parameters being passed:
+ * besides the board info strucure, the loader expects a command
+ * line, the name of the console device, and (optionally) the
+ * address of the original image header.
+ */
+
+ img_addr = 0;
+ if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]))
+ img_addr = (image_header_t *) addr;
+
+
+ consdev = "";
+#if defined (CONFIG_8xx_CONS_SMC1)
+ consdev = "smc1";
+#elif defined (CONFIG_8xx_CONS_SMC2)
+ consdev = "smc2";
+#elif defined (CONFIG_8xx_CONS_SCC2)
+ consdev = "scc2";
+#elif defined (CONFIG_8xx_CONS_SCC3)
+ consdev = "scc3";
#endif
-}
+ if (argc > 2) {
+ ulong len;
+ int i;
+
+ for (i=2, len=0 ; i<argc ; i+=1)
+ len += strlen (argv[i]) + 1;
+ cmdline = malloc (len);
+
+ for (i=2, len=0 ; i<argc ; i+=1)
+ {
+ if (i > 2)
+ cmdline[len++] = ' ';
+ strcpy (&cmdline[len], argv[i]);
+ len += strlen (argv[i]);
+ }
+ } else if ((cmdline = getenv("bootargs")) == NULL) {
+ cmdline = "";
+ }
+
+ loader = (void (*)(bd_t *, image_header_t *, char *, char *)) hdr->ih_ep;
+
+ printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
+ (ulong)loader);
+
+#ifdef CONFIG_HERMES
+ hermes_set_led (15);
+#endif
+
+ /*
+ * NetBSD Stage-2 Loader Parameters:
+ * r3: ptr to board info data
+ * r4: image address
+ * r5: console device
+ * r6: boot args string
+ */
+ (*loader) (bd, img_addr, consdev, cmdline);
+}
#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
void do_bootd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
printf (" Image Name: %.*s\n", IH_NMLEN, hdr->ih_name);
#if (CONFIG_COMMANDS & CFG_CMD_DATE)
to_tm (timestamp, &tm);
- printf (" Created: %4d-%02d-%02d %2d:%02d:%02d\n",
+ printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
#endif /* CFG_CMD_DATE */
switch (hdr->ih_os) {
case IH_OS_INVALID: os = "Invalid OS"; break;
+ case IH_OS_NETBSD: os = "NetBSD"; break;
case IH_OS_LINUX: os = "Linux"; break;
default: os = "Unknown OS"; break;
}
PLATFORM_RELFLAGS=
PLATFORM_CPPFLAGS=
+# When cross-compiling on NetBSD, we have to define __PPC__ or else we
+# will pick up a va_list declaration that is incompatible with the
+# actual argument lists emitted by the compiler.
+#
+# [Tested on NetBSD/i386 1.5 + cross-powerpc-netbsd-1.3]
+
+ifeq ($(CROSS_COMPILE),powerpc-netbsd-)
+PLATFORM_CPPFLAGS+= -D__PPC__
+endif
+
+
ifdef ARCH
sinclude $(TOPDIR)/$(ARCH)/config.mk # include architecture dependend rules
endif
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE)
-#OBJCFLAGS = --remove-section=.stab \
-# --remove-section=.comment \
-# --remove-section=.stabstr \
-# --change-section-lma=.data+$(TEXT_BASE) \
-# --change-section-lma=__ex_table+$(TEXT_BASE) \
-# --change-section-lma=.bss+$(TEXT_BASE) \
-# --set-section-flags=.bss=contents,alloc,load,data
+# Location of a usable BFD library, where we define "usable" as
+# "built for ${HOST}, supports ${TARGET}". Sensible values are
+# - When cross-compiling: the root of the cross-environment
+# - Linux/ppc (native): /usr
+# - NetBSD/ppc (native): you lose ... (must extract these from the
+# binutils build directory, plus the native and ppcboot include
+# files don't like each other)
+#
+# So far, this is used only by tools/gdb/Makefile.
+
+#BFD_ROOT_DIR = /LinuxPPC/CDK # Linux/i386
+#BFD_ROOT_DIR = /usr/pkg/cross # NetBSD/i386
+#BFD_ROOT_DIR = /usr # native
+BFD_ROOT_DIR = /opt/powerpc
#########################################################################