//==========================================================================
//
-// redboot_linux_boot.c
+// redboot_linux_boot.c
//
-// RedBoot command to boot Linux on ARM platforms
+// RedBoot command to boot Linux on ARM platforms
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
//####ECOSGPLCOPYRIGHTEND####
//####OTHERCOPYRIGHTBEGIN####
//
-// The structure definitions below are taken from include/asm-arm/setup.h in
-// the Linux kernel, Copyright (C) 1997-1999 Russell King. Their presence
-// here is for the express purpose of communication with the Linux kernel
-// being booted and is considered 'fair use' by the original author and
-// are included with his permission.
+// The structure definitions below are taken from include/asm-arm/setup.h in
+// the Linux kernel, Copyright (C) 1997-1999 Russell King. Their presence
+// here is for the express purpose of communication with the Linux kernel
+// being booted and is considered 'fair use' by the original author and
+// are included with his permission.
//
//####OTHERCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
-// Author(s): gthomas
+// Author(s): gthomas
// Contributors: gthomas, jskov,
-// Russell King <rmk@arm.linux.org.uk>
-// Date: 2001-02-20
-// Purpose:
-// Description:
-//
+// Russell King <rmk@arm.linux.org.uk>
+// Date: 2001-02-20
+// Purpose:
+// Description:
+//
// This code is part of RedBoot (tm).
//
//####DESCRIPTIONEND####
#include <redboot.h>
#ifdef CYGPKG_IO_ETH_DRIVERS
-#include <cyg/io/eth/eth_drv.h> // Logical driver interfaces
+#include <cyg/io/eth/eth_drv.h> // Logical driver interfaces
#endif
#include <cyg/hal/hal_intr.h>
#endif
// FIXME: This should be a CDL variable, and CYGSEM_REDBOOT_ARM_LINUX_BOOT
-// active_if CYGHWR_HAL_ARM_REDBOOT_MACHINE_TYPE>0
+// active_if CYGHWR_HAL_ARM_REDBOOT_MACHINE_TYPE>0
#ifdef HAL_PLATFORM_MACHINE_TYPE
#define CYGHWR_REDBOOT_ARM_MACHINE_TYPE HAL_PLATFORM_MACHINE_TYPE
// Exported CLI function(s)
static void do_exec(int argc, char *argv[]);
RedBoot_cmd("exec",
- "Execute an image - with MMU off",
- "[-w timeout] [-b <load addr> [-l <length>]]\n"
- " [-r <ramdisk addr> [-s <ramdisk length>]]\n"
- " [-c \"kernel command line\"] [-t <target> ] [<entry_point>]",
- do_exec
- );
+ "Execute an image - with MMU off",
+ "[-w timeout] [-b <load addr> [-l <length>]]\n"
+ " [-r <ramdisk addr> [-s <ramdisk length>]]\n"
+ " [-c \"kernel command line\"] [-t <target> ] [<entry_point>]",
+ do_exec
+ );
// CYGARC_HAL_MMU_OFF inserts code to turn off MMU and jump to a physical
// address. Some ARM implementations may need special handling and define
#ifndef CYGARC_HAL_MMU_OFF
#define __CYGARC_GET_CTLREG \
- " mrc p15,0,r0,c1,c0,0\n"
+ " mrc p15,0,r0,c1,c0,0\n"
-#define __CYGARC_CLR_MMU_BITS \
- " bic r0,r0,#0xd\n" \
- " bic r0,r0,#0x1000\n" \
+#define __CYGARC_CLR_MMU_BITS \
+ " bic r0,r0,#0xd\n" \
+ " bic r0,r0,#0x1000\n" \
#ifdef CYGHWR_HAL_ARM_BIGENDIAN
-#define __CYGARC_CLR_MMU_BITS_X \
- " bic r0,r0,#0x8d\n" \
- " bic r0,r0,#0x1000\n"
+#define __CYGARC_CLR_MMU_BITS_X \
+ " bic r0,r0,#0x8d\n" \
+ " bic r0,r0,#0x1000\n"
#else
-#define __CYGARC_CLR_MMU_BITS_X \
- " bic r0,r0,#0xd\n" \
- " bic r0,r0,#0x1000\n" \
- " orr r0,r0,#0x80\n"
+#define __CYGARC_CLR_MMU_BITS_X \
+ " bic r0,r0,#0xd\n" \
+ " bic r0,r0,#0x1000\n" \
+ " orr r0,r0,#0x80\n"
#endif
#define __CYGARC_SET_CTLREG(__paddr__) \
- " mcr p15,0,r0,c1,c0,0\n" \
- " mov pc," #__paddr__ "\n"
+ " mcr p15,0,r0,c1,c0,0\n" \
+ " mov pc," #__paddr__ "\n"
#define CYGARC_HAL_MMU_OFF(__paddr__) \
- " mcr p15,0,r0,c7,c10,4\n" \
- " mcr p15,0,r0,c7,c7,0\n" \
- __CYGARC_GET_CTLREG \
- __CYGARC_CLR_MMU_BITS \
+ " mcr p15,0,r0,c7,c10,4\n" \
+ " mcr p15,0,r0,c7,c7,0\n" \
+ __CYGARC_GET_CTLREG \
+ __CYGARC_CLR_MMU_BITS \
__CYGARC_SET_CTLREG(__paddr__)
-#define CYGARC_HAL_MMU_OFF_X(__paddr__) \
- " mcr p15,0,r0,c7,c10,4\n" \
- " mcr p15,0,r0,c7,c7,0\n" \
- __CYGARC_GET_CTLREG \
- __CYGARC_CLR_MMU_BITS_X \
+#define CYGARC_HAL_MMU_OFF_X(__paddr__) \
+ " mcr p15,0,r0,c7,c10,4\n" \
+ " mcr p15,0,r0,c7,c7,0\n" \
+ __CYGARC_GET_CTLREG \
+ __CYGARC_CLR_MMU_BITS_X \
__CYGARC_SET_CTLREG(__paddr__)
-#endif // CYGARC_HAL_MMU_OFF
+#endif // CYGARC_HAL_MMU_OFF
+#ifndef CYGARC_HAL_EXEC_FIXUP
+#define CYGARC_HAL_EXEC_FIXUP() ""
+#endif
//
// Parameter info for Linux kernel
-// ** C A U T I O N ** This setup must match "asm-arm/setup.h"
+// ** C A U T I O N ** This setup must match "asm-arm/setup.h"
//
// Info is passed at a fixed location, using a sequence of tagged
// data entries.
typedef unsigned char u8;
//=========================================================================
-// From Linux <asm-arm/setup.h>
+// From Linux <asm-arm/setup.h>
#define ATAG_NONE 0x00000000
struct tag_header {
- u32 size; // Size of tag (hdr+data) in *longwords*
- u32 tag;
+ u32 size; // Size of tag (hdr+data) in *longwords*
+ u32 tag;
};
#define ATAG_CORE 0x54410001
struct tag_core {
- u32 flags; /* bit 0 = read-only */
- u32 pagesize;
- u32 rootdev;
+ u32 flags; /* bit 0 = read-only */
+ u32 pagesize;
+ u32 rootdev;
};
#define ATAG_MEM 0x54410002
struct tag_mem32 {
- u32 size;
- u32 start;
+ u32 size;
+ u32 start;
};
#define ATAG_VIDEOTEXT 0x54410003
struct tag_videotext {
- u8 x;
- u8 y;
- u16 video_page;
- u8 video_mode;
- u8 video_cols;
- u16 video_ega_bx;
- u8 video_lines;
- u8 video_isvga;
- u16 video_points;
+ u8 x;
+ u8 y;
+ u16 video_page;
+ u8 video_mode;
+ u8 video_cols;
+ u16 video_ega_bx;
+ u8 video_lines;
+ u8 video_isvga;
+ u16 video_points;
};
#define ATAG_RAMDISK 0x54410004
struct tag_ramdisk {
- u32 flags; /* b0 = load, b1 = prompt */
- u32 size;
- u32 start;
+ u32 flags; /* b0 = load, b1 = prompt */
+ u32 size;
+ u32 start;
};
/*
/* describes where the compressed ramdisk image lives (physical address) */
#define ATAG_INITRD2 0x54420005
struct tag_initrd {
- u32 start;
- u32 size;
+ u32 start;
+ u32 size;
};
#define ATAG_SERIAL 0x54410006
struct tag_serialnr {
- u32 low;
- u32 high;
+ u32 low;
+ u32 high;
};
#define ATAG_REVISION 0x54410007
struct tag_revision {
- u32 rev;
+ u32 rev;
};
#define ATAG_VIDEOLFB 0x54410008
struct tag_videolfb {
- u16 lfb_width;
- u16 lfb_height;
- u16 lfb_depth;
- u16 lfb_linelength;
- u32 lfb_base;
- u32 lfb_size;
- u8 red_size;
- u8 red_pos;
- u8 green_size;
- u8 green_pos;
- u8 blue_size;
- u8 blue_pos;
- u8 rsvd_size;
- u8 rsvd_pos;
+ u16 lfb_width;
+ u16 lfb_height;
+ u16 lfb_depth;
+ u16 lfb_linelength;
+ u32 lfb_base;
+ u32 lfb_size;
+ u8 red_size;
+ u8 red_pos;
+ u8 green_size;
+ u8 green_pos;
+ u8 blue_size;
+ u8 blue_pos;
+ u8 rsvd_size;
+ u8 rsvd_pos;
};
#define ATAG_CMDLINE 0x54410009
struct tag_cmdline {
- char cmdline[1];
+ char cmdline[1];
};
#define ATAG_ACORN 0x41000101
struct tag_acorn {
- u32 memc_control_reg;
- u32 vram_pages;
- u8 sounddefault;
- u8 adfsdrives;
+ u32 memc_control_reg;
+ u32 vram_pages;
+ u8 sounddefault;
+ u8 adfsdrives;
};
#define ATAG_MEMCLK 0x41000402
struct tag_memclk {
- u32 fmemclk;
+ u32 fmemclk;
};
struct tag {
- struct tag_header hdr;
- union {
- struct tag_core core;
- struct tag_mem32 mem;
- struct tag_videotext videotext;
- struct tag_ramdisk ramdisk;
- struct tag_initrd initrd;
- struct tag_serialnr serialnr;
- struct tag_revision revision;
- struct tag_videolfb videolfb;
- struct tag_cmdline cmdline;
-
- /*
- * Acorn specific
- */
- struct tag_acorn acorn;
-
- /*
- * DC21285 specific
- */
- struct tag_memclk memclk;
- } u;
+ struct tag_header hdr;
+ union {
+ struct tag_core core;
+ struct tag_mem32 mem;
+ struct tag_videotext videotext;
+ struct tag_ramdisk ramdisk;
+ struct tag_initrd initrd;
+ struct tag_serialnr serialnr;
+ struct tag_revision revision;
+ struct tag_videolfb videolfb;
+ struct tag_cmdline cmdline;
+
+ /*
+ * Acorn specific
+ */
+ struct tag_acorn acorn;
+
+ /*
+ * DC21285 specific
+ */
+ struct tag_memclk memclk;
+ } u;
};
// End of inclusion from <asm-arm/setup.h>
// Default memory layout - can be overridden by platform, typically in
// <cyg/hal/plf_io.h>
#ifndef CYGHWR_REDBOOT_LINUX_ATAG_MEM
-#define CYGHWR_REDBOOT_LINUX_ATAG_MEM(_p_) \
- CYG_MACRO_START \
- /* Next ATAG_MEM. */ \
- _p_->hdr.size = (sizeof(struct tag_mem32) + sizeof(struct tag_header))/sizeof(long); \
- _p_->hdr.tag = ATAG_MEM; \
- /* Round up so there's only one bit set in the memory size. \
- * Don't double it if it's already a power of two, though. \
- */ \
- _p_->u.mem.size = 1<<hal_msbindex(CYGMEM_REGION_ram_SIZE); \
- if (_p_->u.mem.size < CYGMEM_REGION_ram_SIZE) \
- _p_->u.mem.size <<= 1; \
- _p_->u.mem.start = CYGARC_PHYSICAL_ADDRESS(CYGMEM_REGION_ram); \
- CYG_MACRO_END
+#define CYGHWR_REDBOOT_LINUX_ATAG_MEM(_p_) \
+ CYG_MACRO_START \
+ /* Next ATAG_MEM. */ \
+ _p_->hdr.size = (sizeof(struct tag_mem32) + sizeof(struct tag_header))/sizeof(long); \
+ _p_->hdr.tag = ATAG_MEM; \
+ /* Round up so there's only one bit set in the memory size. \
+ * Don't double it if it's already a power of two, though. \
+ */ \
+ _p_->u.mem.size = 1<<hal_msbindex(CYGMEM_REGION_ram_SIZE); \
+ if (_p_->u.mem.size < CYGMEM_REGION_ram_SIZE) \
+ _p_->u.mem.size <<= 1; \
+ _p_->u.mem.start = CYGARC_PHYSICAL_ADDRESS(CYGMEM_REGION_ram); \
+ CYG_MACRO_END
#endif
// Round up a quantity to a longword (32 bit) length
-#define ROUNDUP(n) (((n)+3)&~3)
+#define ROUNDUP(n) (((n) + 3) & ~3)
static void
do_exec(int argc, char *argv[])
{
- unsigned long entry;
- unsigned long target;
- unsigned long oldints;
- bool wait_time_set;
- int wait_time, res, num_opts;
- bool base_addr_set, length_set, cmd_line_set;
- bool ramdisk_addr_set, ramdisk_size_set;
- unsigned long base_addr, length;
- unsigned long ramdisk_addr, ramdisk_size;
- struct option_info opts[7];
- char line[8];
- char *cmd_line;
- struct tag *params = (struct tag *)CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS;
+ unsigned long entry;
+ unsigned long target;
+ unsigned long oldints;
+ bool wait_time_set;
+ int wait_time, res, num_opts;
+ bool base_addr_set, length_set, cmd_line_set;
+ bool ramdisk_addr_set, ramdisk_size_set;
+ unsigned long base_addr, length;
+ unsigned long ramdisk_addr, ramdisk_size;
+ struct option_info opts[7];
+ char line[8];
+ char *cmd_line;
+ struct tag *params = (struct tag *)CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS;
#ifdef CYGHWR_REDBOOT_LINUX_EXEC_X_SWITCH
- bool swap_endian;
- extern char __xtramp_start__[], __xtramp_end__[];
+ bool swap_endian;
+ extern char __xtramp_start__[], __xtramp_end__[];
#endif
- extern char __tramp_start__[], __tramp_end__[];
-
- // Check to see if a valid image has been loaded
- if (entry_address == (unsigned long)NO_MEMORY) {
- diag_printf("Can't execute Linux - invalid entry address\n");
- return;
- }
- // Default physical entry point for Linux is kernel base.
- entry = (unsigned long)CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS;
- target = (unsigned long)CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS;
-
- base_addr = load_address;
- length = load_address_end - load_address;
- // Round length up to the next quad word
- length = (length + 3) & ~0x3;
-
- ramdisk_size = 4096*1024;
- init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
- &wait_time, (bool *)&wait_time_set, "wait timeout");
- init_opts(&opts[1], 'b', true, OPTION_ARG_TYPE_NUM,
- &base_addr, (bool *)&base_addr_set, "base address");
- init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
- &length, (bool *)&length_set, "length");
- init_opts(&opts[3], 'c', true, OPTION_ARG_TYPE_STR,
- &cmd_line, (bool *)&cmd_line_set, "kernel command line");
- init_opts(&opts[4], 'r', true, OPTION_ARG_TYPE_NUM,
- &ramdisk_addr, (bool *)&ramdisk_addr_set, "ramdisk_addr");
- init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM,
- &ramdisk_size, (bool *)&ramdisk_size_set, "ramdisk_size");
- init_opts(&opts[6], 't', true, OPTION_ARG_TYPE_NUM,
- &target, 0, "[physical] target address");
- num_opts = 7;
+ extern char __tramp_start__[], __tramp_end__[];
+
+ // Check to see if a valid image has been loaded
+ if (entry_address == (unsigned long)NO_MEMORY) {
+ diag_printf("Can't execute Linux - invalid entry address\n");
+ return;
+ }
+ // Default physical entry point for Linux is kernel base.
+ entry = (unsigned long)CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS;
+ target = (unsigned long)CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS;
+
+ base_addr = load_address;
+ length = load_address_end - load_address;
+ // Round length up to the next quad word
+ length = (length + 3) & ~0x3;
+
+ ramdisk_size = 4096*1024;
+ init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
+ &wait_time, &wait_time_set, "wait timeout");
+ init_opts(&opts[1], 'b', true, OPTION_ARG_TYPE_NUM,
+ &base_addr, &base_addr_set, "base address");
+ init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
+ &length, &length_set, "length");
+ init_opts(&opts[3], 'c', true, OPTION_ARG_TYPE_STR,
+ &cmd_line, &cmd_line_set, "kernel command line");
+ init_opts(&opts[4], 'r', true, OPTION_ARG_TYPE_NUM,
+ &ramdisk_addr, &ramdisk_addr_set, "ramdisk_addr");
+ init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM,
+ &ramdisk_size, &ramdisk_size_set, "ramdisk_size");
+ init_opts(&opts[6], 't', true, OPTION_ARG_TYPE_NUM,
+ &target, 0, "[physical] target address");
+ num_opts = 7;
#ifdef CYGHWR_REDBOOT_LINUX_EXEC_X_SWITCH
- init_opts(&opts[num_opts], 'x', false, OPTION_ARG_TYPE_FLG,
- &swap_endian, 0, "swap endianess");
- ++num_opts;
+ init_opts(&opts[num_opts], 'x', false, OPTION_ARG_TYPE_FLG,
+ &swap_endian, 0, "swap endianess");
+ ++num_opts;
#endif
- if (!scan_opts(argc, argv, 1, opts, num_opts, &entry, OPTION_ARG_TYPE_NUM, "[physical] starting address"))
- {
- return;
- }
-
- // Set up parameters to pass to kernel
-
- // CORE tag must be present & first
- params->hdr.size = (sizeof(struct tag_core) + sizeof(struct tag_header))/sizeof(long);
- params->hdr.tag = ATAG_CORE;
- params->u.core.flags = 0;
- params->u.core.pagesize = 0;
- params->u.core.rootdev = 0;
- params = (struct tag *)((long *)params + params->hdr.size);
-
- // Fill in the details of the memory layout
- CYGHWR_REDBOOT_LINUX_ATAG_MEM(params);
-
- params = (struct tag *)((long *)params + params->hdr.size);
- if (ramdisk_addr_set) {
- params->hdr.size = (sizeof(struct tag_initrd) + sizeof(struct tag_header))/sizeof(long);
- params->hdr.tag = ATAG_INITRD2;
- params->u.initrd.start = CYGARC_PHYSICAL_ADDRESS(ramdisk_addr);
- params->u.initrd.size = ramdisk_size;
- params = (struct tag *)((long *)params + params->hdr.size);
- }
- if (cmd_line_set) {
- params->hdr.size = (ROUNDUP(strlen(cmd_line)) + sizeof(struct tag_header))/sizeof(long);
- params->hdr.tag = ATAG_CMDLINE;
- strcpy(params->u.cmdline.cmdline, cmd_line);
- params = (struct tag *)((long *)params + params->hdr.size);
- }
- // Mark end of parameter list
- params->hdr.size = 0;
- params->hdr.tag = ATAG_NONE;
-
- if (wait_time_set) {
- int script_timeout_ms = wait_time * 1000;
+ if (!scan_opts(argc, argv, 1, opts, num_opts, &entry,
+ OPTION_ARG_TYPE_NUM, "[physical] starting address")) {
+ return;
+ }
+
+ // Set up parameters to pass to kernel
+
+ // CORE tag must be present & first
+ params->hdr.size = (sizeof(struct tag_core) + sizeof(struct tag_header))/sizeof(long);
+ params->hdr.tag = ATAG_CORE;
+ params->u.core.flags = 0;
+ params->u.core.pagesize = 0;
+ params->u.core.rootdev = 0;
+ params = (struct tag *)((long *)params + params->hdr.size);
+
+ // Fill in the details of the memory layout
+ CYGHWR_REDBOOT_LINUX_ATAG_MEM(params);
+
+ params = (struct tag *)((long *)params + params->hdr.size);
+ if (ramdisk_addr_set) {
+ params->hdr.size = (sizeof(struct tag_initrd) + sizeof(struct tag_header))/sizeof(long);
+ params->hdr.tag = ATAG_INITRD2;
+ params->u.initrd.start = CYGARC_PHYSICAL_ADDRESS(ramdisk_addr);
+ params->u.initrd.size = ramdisk_size;
+ params = (struct tag *)((long *)params + params->hdr.size);
+ }
+ if (cmd_line_set) {
+ params->hdr.size = (ROUNDUP(strlen(cmd_line)) + sizeof(struct tag_header))/sizeof(long);
+ params->hdr.tag = ATAG_CMDLINE;
+ strcpy(params->u.cmdline.cmdline, cmd_line);
+ params = (struct tag *)((long *)params + params->hdr.size);
+ }
+ // Mark end of parameter list
+ params->hdr.size = 0;
+ params->hdr.tag = ATAG_NONE;
+
+ if (wait_time_set) {
+ int script_timeout_ms = wait_time * 1000;
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
- unsigned char *hold_script = script;
- script = (unsigned char *)0;
+ unsigned char *hold_script = script;
+ script = NULL;
#endif
- diag_printf("About to start execution of image at %p, entry point %p - abort with ^C within %d seconds\n",
- (void *)target, (void *)entry, wait_time);
- while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
- res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
- if (res == _GETS_CTRLC) {
+ diag_printf("About to start execution of image at %p, entry point %p - abort with ^C within %d seconds\n",
+ (void *)target, (void *)entry, wait_time);
+ while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
+ res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
+ if (res == _GETS_CTRLC) {
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
- script = hold_script; // Re-enable script
+ script = hold_script; // Re-enable script
#endif
- return;
- }
- script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
- }
- }
- if (!base_addr_set) {
- if ((base_addr == 0) || (length == 0)) {
- // Probably not valid - don't try it
- diag_printf("Base address unknown - use \"-b\" option\n");
- return;
- }
- diag_printf("Using base address %p and length %p\n",
- (void*)base_addr, (void*)length);
- } else if (base_addr_set && !length_set) {
- diag_printf("Length required for non-standard base address\n");
- return;
- }
+ return;
+ }
+ script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
+ }
+ }
+ if (!base_addr_set) {
+ if ((base_addr == 0) || (length == 0)) {
+ // Probably not valid - don't try it
+ diag_printf("Base address unknown - use \"-b\" option\n");
+ return;
+ }
+ diag_printf("Using base address %p and length %p\n",
+ (void*)base_addr, (void*)length);
+ } else if (base_addr_set && !length_set) {
+ diag_printf("Length required for non-standard base address\n");
+ return;
+ }
#ifdef CYGPKG_IO_ETH_DRIVERS
- eth_drv_stop();
+ eth_drv_stop();
#endif
- HAL_DISABLE_INTERRUPTS(oldints);
- HAL_DCACHE_SYNC();
- HAL_ICACHE_DISABLE();
- HAL_DCACHE_DISABLE();
- HAL_DCACHE_SYNC();
- HAL_ICACHE_INVALIDATE_ALL();
- HAL_DCACHE_INVALIDATE_ALL();
-
- // Tricky code. We are currently running with the MMU on and the
- // memory map possibly convoluted from 1-1. The trampoline code
- // between labels __tramp_start__ and __tramp_end__ must be copied
- // to RAM and then executed at the non-mapped address.
- //
- // This magic was created in order to be able to execute standard
- // Linux kernels with as little change/perturberance as possible.
+ HAL_DISABLE_INTERRUPTS(oldints);
+ HAL_DCACHE_SYNC();
+ HAL_ICACHE_DISABLE();
+ HAL_DCACHE_DISABLE();
+ HAL_DCACHE_SYNC();
+ HAL_ICACHE_INVALIDATE_ALL();
+ HAL_DCACHE_INVALIDATE_ALL();
+
+ // Tricky code. We are currently running with the MMU on and the
+ // memory map possibly convoluted from 1-1. The trampoline code
+ // between labels __tramp_start__ and __tramp_end__ must be copied
+ // to RAM and then executed at the non-mapped address.
+ //
+ // This magic was created in order to be able to execute standard
+ // Linux kernels with as little change/perturberance as possible.
#ifdef CYGHWR_REDBOOT_LINUX_EXEC_X_SWITCH
- if (swap_endian) {
- // copy the trampline code
+ if (swap_endian) {
+ // copy the trampoline code
+ memcpy((char *)CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS,
+ __xtramp_start__,
+ __xtramp_end__ - __xtramp_start__);
+
+ asm volatile (
+ CYGARC_HAL_MMU_OFF_X(%5)
+ "__xtramp_start__:\n"
+ " cmp %1,%4;\n" // Default kernel load address. Relocate
+ " beq 2f;\n" // kernel image there if necessary, and
+ " cmp %2,#0;\n" // if size is non-zero
+ " beq 2f;\n"
+ "1:\n"
+ " ldr r0,[%1],#4;\n"
+ " eor %5, r0, r0, ror #16;\n"
+ " bic %5, %5, #0x00ff0000;\n"
+ " mov r0, r0, ror #8;\n"
+ " eor r0, r0, %5, lsr #8;\n"
+ " str r0,[%4],#4;\n"
+ " subs %2,%2,#4;\n"
+ " bne 1b;\n"
+ "2:\n"
+ " mov r0,#0;\n" // Set board type
+ " mov r1,%3;\n" // Machine type
+ " mov r2,%6;\n" // Kernel parameters
+ " mov pc,%0;\n" // Jump to kernel
+ "__xtramp_end__:\n"
+ : :
+ "r"(entry),
+ "r"(CYGARC_PHYSICAL_ADDRESS(base_addr)),
+ "r"(length),
+ "r"(CYGHWR_REDBOOT_ARM_MACHINE_TYPE),
+ "r"(CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS),
+ "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS)),
+ "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS))
+ : "r0", "r1"
+ );
+ }
+#endif // CYGHWR_REDBOOT_LINUX_EXEC_X_SWITCH
+
+ // copy the trampoline code
memcpy((char *)CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS,
- __xtramp_start__,
- __xtramp_end__ - __xtramp_start__);
+ __tramp_start__,
+ __tramp_end__ - __tramp_start__);
asm volatile (
- CYGARC_HAL_MMU_OFF_X(%5)
- "__xtramp_start__:\n"
- " cmp %1,%4;\n" // Default kernel load address. Relocate
- " beq 2f;\n" // kernel image there if necessary, and
- " cmp %2,#0;\n" // if size is non-zero
- " beq 2f;\n"
- "1:\n"
- " ldr r0,[%1],#4;\n"
- " eor %5, r0, r0, ror #16;\n"
- " bic %5, %5, #0x00ff0000;\n"
- " mov r0, r0, ror #8;\n"
- " eor r0, r0, %5, lsr #8;\n"
- " str r0,[%4],#4;\n"
- " subs %2,%2,#4;\n"
- " bne 1b;\n"
- "2:\n"
- " mov r0,#0;\n" // Set board type
- " mov r1,%3;\n" // Machine type
- " mov r2,%6;\n" // Kernel parameters
- " mov pc,%0;\n" // Jump to kernel
- "__xtramp_end__:\n"
- : :
- "r"(entry),
- "r"(CYGARC_PHYSICAL_ADDRESS(base_addr)),
- "r"(length),
- "r"(CYGHWR_REDBOOT_ARM_MACHINE_TYPE),
- "r"(CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS),
- "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS)),
- "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS))
- : "r0", "r1"
- );
- }
-#endif // CYGHWR_REDBOOT_LINUX_EXEC_X_SWITCH
-
- // copy the trampline code
- memcpy((char *)CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS,
- __tramp_start__,
- __tramp_end__ - __tramp_start__);
-
- asm volatile (
- CYGARC_HAL_MMU_OFF(%5)
- "__tramp_start__:\n"
- " cmp %1,%4;\n" // Default kernel load address. Relocate
- " beq 2f;\n" // kernel image there if necessary, and
- " cmp %2,#0;\n" // if size is non-zero
- " beq 2f;\n"
- "1:\n"
- " ldr r0,[%1],#4;\n"
- " str r0,[%4],#4;\n"
- " subs %2,%2,#4;\n"
- " bne 1b;\n"
- "2:\n"
- " mov r0,#0;\n" // Set board type
- " mov r1,%3;\n" // Machine type
- " mov r2,%6;\n" // Kernel parameters
- " mov pc,%0;\n" // Jump to kernel
- "__tramp_end__:\n"
- : :
- "r"(entry),
- "r"(CYGARC_PHYSICAL_ADDRESS(base_addr)),
- "r"(length),
- "r"(CYGHWR_REDBOOT_ARM_MACHINE_TYPE),
- "r"(target),
- "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS)),
- "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS))
- : "r0", "r1"
- );
+ CYGARC_HAL_MMU_OFF(%5)
+ "__tramp_start__:\n"
+ " cmp %1,%4;\n" // Default kernel load address. Relocate
+ " beq 2f;\n" // kernel image there if necessary, and
+ " cmp %2,#0;\n" // if size is non-zero
+ " beq 2f;\n"
+ "1:\n"
+ " ldr r0,[%1],#4;\n"
+ " str r0,[%4],#4;\n"
+ " subs %2,%2,#4;\n"
+ " bne 1b;\n"
+ "2:\n"
+ CYGARC_HAL_EXEC_FIXUP()
+ " mov r0,#0;\n" // Set board type
+ " mov r1,%3;\n" // Machine type
+ " mov r2,%6;\n" // Kernel parameters
+ " mov pc,%0;\n" // Jump to kernel
+ "__tramp_end__:\n"
+ : :
+ "r"(entry),
+ "r"(CYGARC_PHYSICAL_ADDRESS(base_addr)),
+ "r"(length),
+ "r"(CYGHWR_REDBOOT_ARM_MACHINE_TYPE),
+ "r"(target),
+ "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS)),
+ "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS))
+ : "r0", "r1"
+ );
}
-
+
#endif // HAL_PLATFORM_MACHINE_TYPE - otherwise we do not support this stuff...
// EOF redboot_linux_exec.c