#include <malloc.h>
#include <net.h>
#include <ide.h>
+#include <serial.h>
#include <asm/u-boot-i386.h>
#include <elf.h>
DECLARE_GLOBAL_DATA_PTR;
/* Exports from the Linker Script */
-extern ulong _i386boot_text_start;
-extern ulong _i386boot_rel_dyn_start;
-extern ulong _i386boot_rel_dyn_end;
-extern ulong _i386boot_bss_start;
-extern ulong _i386boot_bss_size;
-void ram_bootstrap (void *);
+extern ulong __text_start;
+extern ulong __data_end;
+extern ulong __rel_dyn_start;
+extern ulong __rel_dyn_end;
+extern ulong __bss_start;
+extern ulong __bss_end;
+
const char version_string[] =
U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")";
static int init_baudrate (void)
{
char tmp[64]; /* long enough for environment variables */
- int i = getenv_r("baudrate", tmp, 64);
+ int i = getenv_f("baudrate", tmp, 64);
gd->baudrate = (i != 0)
? (int) simple_strtoul (tmp, NULL, 10)
typedef int (init_fnc_t) (void);
init_fnc_t *init_sequence[] = {
- serial_init,
cpu_init_r, /* basic cpu dependent setup */
board_early_init_r, /* basic board dependent setup */
dram_init, /* configure available RAM banks */
/*
* Load U-Boot into RAM, initialize BSS, perform relocation adjustments
*/
-void board_init_f (ulong stack_limit)
+void board_init_f (ulong gdp)
{
- void *text_start = &_i386boot_text_start;
- void *u_boot_cmd_end = &__u_boot_cmd_end;
- Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&_i386boot_rel_dyn_start;
- Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&_i386boot_rel_dyn_end;
- void *bss_start = &_i386boot_bss_start;
- void *bss_size = &_i386boot_bss_size;
-
- size_t uboot_size;
- void *ram_start;
+ void *text_start = &__text_start;
+ void *data_end = &__data_end;
+ void *rel_dyn_start = &__rel_dyn_start;
+ void *rel_dyn_end = &__rel_dyn_end;
+ void *bss_start = &__bss_start;
+ void *bss_end = &__bss_end;
+
+ ulong *dst_addr;
+ ulong *src_addr;
+ ulong *end_addr;
+
+ void *dest_addr;
ulong rel_offset;
- Elf32_Rel *re;
-
- void (*start_func)(void *);
-
- /* compiler optimization barrier needed for GCC >= 3.4 */
- __asm__ __volatile__("": : :"memory");
+ Elf32_Rel *re_src;
+ Elf32_Rel *re_end;
- uboot_size = (size_t)u_boot_cmd_end - (size_t)text_start;
- ram_start = (void *)stack_limit - (uboot_size + (ulong)bss_size);
- rel_offset = text_start - ram_start;
- start_func = ram_bootstrap - rel_offset;
+ /* Calculate destination RAM Address and relocation offset */
+ dest_addr = (void *)gdp - (bss_end - text_start);
+ rel_offset = text_start - dest_addr;
/* First stage CPU initialization */
if (cpu_init_f() != 0)
hang();
/* Copy U-Boot into RAM */
- memcpy(ram_start, text_start, (size_t)uboot_size);
+ dst_addr = (ulong *)dest_addr;
+ src_addr = (ulong *)text_start;
+ end_addr = (ulong *)data_end;
+
+ while (src_addr < end_addr)
+ *dst_addr++ = *src_addr++;
/* Clear BSS */
- memset(bss_start - rel_offset, 0, (size_t)bss_size);
+ dst_addr = (ulong *)(bss_start - rel_offset);
+ end_addr = (ulong *)(bss_end - rel_offset);
+
+ while (dst_addr < end_addr)
+ *dst_addr++ = 0x00000000;
/* Perform relocation adjustments */
- for (re = rel_dyn_start; re < rel_dyn_end; re++)
- {
- if (re->r_offset >= TEXT_BASE)
- if (*(ulong *)re->r_offset >= TEXT_BASE)
- *(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset;
- }
+ re_src = (Elf32_Rel *)rel_dyn_start;
+ re_end = (Elf32_Rel *)rel_dyn_end;
- start_func(ram_start);
+ do {
+ if (re_src->r_offset >= TEXT_BASE)
+ if (*(Elf32_Addr *)(re_src->r_offset - rel_offset) >= TEXT_BASE)
+ *(Elf32_Addr *)(re_src->r_offset - rel_offset) -= rel_offset;
+ } while (re_src++ < re_end);
- /* NOTREACHED - relocate_code() does not return */
- while(1);
-}
-
-/*
- * All attempts to jump straight from board_init_f() to board_init_r()
- * have failed, hence this special 'bootstrap' function.
- */
-void ram_bootstrap (void *ram_start)
-{
- static gd_t gd_data;
+ ((gd_t *)gdp)->reloc_off = rel_offset;
+ ((gd_t *)gdp)->flags |= GD_FLG_RELOC;
- /* compiler optimization barrier needed for GCC >= 3.4 */
- __asm__ __volatile__("": : :"memory");
+ /* Enter the relocated U-Boot! */
+ (board_init_r - rel_offset)((gd_t *)gdp, (ulong)dest_addr);
- board_init_r(&gd_data, (ulong)ram_start);
+ /* NOTREACHED - board_init_f() does not return */
+ while(1);
}
-void board_init_r(gd_t *id, ulong ram_start)
+void board_init_r(gd_t *id, ulong dest_addr)
{
char *s;
int i;
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");
- memset (gd, 0, sizeof (gd_t));
gd->bd = &bd_data;
memset (gd->bd, 0, sizeof (bd_t));
show_boot_progress(0x22);
gd->baudrate = CONFIG_BAUDRATE;
- gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
-
- mem_malloc_init((((ulong)ram_start - CONFIG_SYS_MALLOC_LEN)+3)&~3,
+ mem_malloc_init((((ulong)dest_addr - CONFIG_SYS_MALLOC_LEN)+3)&~3,
CONFIG_SYS_MALLOC_LEN);
for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) {
}
show_boot_progress(0x23);
+#ifdef CONFIG_SERIAL_MULTI
+ serial_initialize();
+#endif
/* configure available FLASH banks */
size = flash_init();
display_flash_config(size);
show_boot_progress(0x26);
+#ifdef CONFIG_CMD_NET
/* IP Address */
bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr");
+#endif
#if defined(CONFIG_PCI)
/*
enable_interrupts();
show_boot_progress(0x28);
- /* Must happen after interrupts are initialized since
- * an irq handler gets installed
- */
-#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
- serial_buffered_init();
-#endif
-
#ifdef CONFIG_STATUS_LED
status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
#endif
for (;;);
}
-unsigned long do_go_exec (ulong (*entry)(int, char *[]), int argc, char *argv[])
+unsigned long do_go_exec (ulong (*entry)(int, char * const []), int argc, char * const argv[])
{
+ unsigned long ret = 0;
+ char **argv_tmp;
+
/*
- * TODO: Test this function - changed to fix compiler error.
- * Original code was:
- * return (entry >> 1) (argc, argv);
- * with a comment about Nios function pointers are address >> 1
+ * x86 does not use a dedicated register to pass the pointer to
+ * the global_data, so it is instead passed as argv[-1]. By using
+ * argv[-1], the called 'Application' can use the contents of
+ * argv natively. However, to safely use argv[-1] a new copy of
+ * argv is needed with the extra element
*/
- return (entry) (argc, argv);
+ argv_tmp = malloc(sizeof(char *) * (argc + 1));
+
+ if (argv_tmp) {
+ argv_tmp[0] = (char *)gd;
+
+ memcpy(&argv_tmp[1], argv, (size_t)(sizeof(char *) * argc));
+
+ ret = (entry) (argc, &argv_tmp[1]);
+ free(argv_tmp);
+ }
+
+ return ret;
+}
+
+void setup_pcat_compatibility(void)
+ __attribute__((weak, alias("__setup_pcat_compatibility")));
+
+void __setup_pcat_compatibility(void)
+{
}