[U-Boot] [PATCH 12/26] ARM: add relocation support

!! This breaks support for all arm boards !!
To compile in old style, you must define CONFIG_SYS_ARM_WITHOUT_RELOC or you can compile with "CONFIG_SYS_ARM_WITHOUT_RELOC=1 ./MAKEALL board"
!! This define will be removed soon, so convert your board to use relocation support
Signed-off-by: Heiko Schocher hs@denx.de --- - changes since previous patch set - as introducing CONFIG_SYS_ARM_WITHOUT_RELOC, seperate common arm changes in this patch
arch/arm/config.mk | 8 + arch/arm/include/asm/config.h | 3 +- arch/arm/include/asm/global_data.h | 11 + arch/arm/include/asm/u-boot-arm.h | 14 +- arch/arm/lib/board.c | 468 +++++++++++++++++++++++++++++++++++- arch/arm/lib/cache-cp15.c | 37 +++- arch/arm/lib/interrupts.c | 19 ++- common/cmd_bdinfo.c | 11 +- common/cmd_bmp.c | 6 + common/cmd_i2c.c | 6 + doc/README.arm-relocation | 321 ++++++++++++++++++++++++ nand_spl/nand_boot.c | 7 + nand_spl/nand_boot_fsl_nfc.c | 7 + 13 files changed, 910 insertions(+), 8 deletions(-) create mode 100644 doc/README.arm-relocation
diff --git a/arch/arm/config.mk b/arch/arm/config.mk index e10dafc..6923f6d 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -33,6 +33,14 @@ STANDALONE_LOAD_ADDR = 0xc100000 endif endif
+ifndef CONFIG_SYS_ARM_WITHOUT_RELOC +# needed for relocation +PLATFORM_RELFLAGS += -fPIC +endif + +ifdef CONFIG_SYS_ARM_WITHOUT_RELOC +PLATFORM_CPPFLAGS += -DCONFIG_SYS_ARM_WITHOUT_RELOC +endif PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h index b76fd8e..4e8dfd7 100644 --- a/arch/arm/include/asm/config.h +++ b/arch/arm/include/asm/config.h @@ -21,7 +21,8 @@ #ifndef _ASM_CONFIG_H_ #define _ASM_CONFIG_H_
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) /* Relocation to SDRAM works on all ARM boards */ #define CONFIG_RELOC_FIXUP_WORKS - +#endif #endif diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 02cfe45..488bae7 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -53,6 +53,17 @@ typedef struct global_data { phys_size_t ram_size; /* RAM size */ unsigned long reset_status; /* reset status register at boot */ #endif +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) + unsigned long relocaddr; /* Start address of U-Boot in RAM */ + phys_size_t ram_size; /* RAM size */ + unsigned long mon_len; /* monitor len */ + unsigned long irq_sp; /* irq stack pointer */ + unsigned long start_addr_sp; /* start_addr_stackpointer */ + unsigned long reloc_off; +#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE)) + unsigned long tlb_addr; +#endif +#endif void **jt; /* jump table */ } gd_t;
diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h index 6d2f8bc..faf800a 100644 --- a/arch/arm/include/asm/u-boot-arm.h +++ b/arch/arm/include/asm/u-boot-arm.h @@ -30,11 +30,20 @@ #define _U_BOOT_ARM_H_ 1
/* for the following variables, see start.S */ -extern ulong _armboot_start; /* code start */ extern ulong _bss_start; /* code + data end == BSS start */ extern ulong _bss_end; /* BSS end */ extern ulong IRQ_STACK_START; /* top of IRQ stack */ extern ulong FIQ_STACK_START; /* top of FIQ stack */ +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +extern ulong _armboot_start; /* code start */ +#else +extern ulong _TEXT_BASE; /* code start */ +extern ulong _datarel_start; +extern ulong _datarelrolocal_start; +extern ulong _datarellocal_start; +extern ulong _datarelro_start; +extern ulong IRQ_STACK_START_IN; /* 8 bytes in IRQ stack */ +#endif
/* cpu/.../cpu.c */ int cpu_init(void); @@ -47,6 +56,9 @@ int arch_misc_init(void); /* board/.../... */ int board_init(void); int dram_init (void); +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +void dram_init_banksize (void); +#endif void setup_serial_tag (struct tag **params); void setup_revision_tag (struct tag **params);
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 54519b0..88c6427 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -126,7 +126,12 @@ static int init_baudrate (void) { char tmp[64]; /* long enough for environment variables */ int i = getenv_f("baudrate", tmp, sizeof (tmp)); + +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) + gd->baudrate = (i > 0) +#else gd->bd->bi_baudrate = gd->baudrate = (i > 0) +#endif ? (int) simple_strtoul (tmp, NULL, 10) : CONFIG_BAUDRATE;
@@ -137,7 +142,12 @@ static int display_banner (void) { printf ("\n\n%s\n\n", version_string); debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", - _armboot_start, _bss_start, _bss_end); +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) + _TEXT_BASE, +#else + _armboot_start, +#endif + _bss_start, _bss_end); #ifdef CONFIG_MODEM_SUPPORT debug ("Modem Support enabled\n"); #endif @@ -180,6 +190,7 @@ static int display_dram_config (void) return (0); }
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) #ifndef CONFIG_SYS_NO_FLASH static void display_flash_config (ulong size) { @@ -187,6 +198,7 @@ static void display_flash_config (ulong size) print_size (size, "\n"); } #endif /* CONFIG_SYS_NO_FLASH */ +#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) static int init_func_i2c (void) @@ -234,6 +246,7 @@ typedef int (init_fnc_t) (void);
int print_cpuinfo (void);
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) init_fnc_t *init_sequence[] = { #if defined(CONFIG_ARCH_CPU_INIT) arch_cpu_init, /* basic arch cpu dependent setup */ @@ -444,6 +457,459 @@ extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
/* NOTREACHED - no way out of command loop except booting */ } +#else +void __dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = gd->ram_size; +} +void dram_init_banksize(void) + __attribute__((weak, alias("__dram_init_banksize"))); + +init_fnc_t *init_sequence[] = { +#if defined(CONFIG_ARCH_CPU_INIT) + arch_cpu_init, /* basic arch cpu dependent setup */ +#endif +#if defined(CONFIG_BOARD_EARLY_INIT_F) + board_early_init_f, +#endif + timer_init, /* initialize timer */ +#ifdef CONFIG_FSL_ESDHC + get_clocks, +#endif + env_init, /* initialize environment */ + init_baudrate, /* initialze baudrate settings */ + serial_init, /* serial communications setup */ + console_init_f, /* stage 1 init of console */ + display_banner, /* say that we are here */ +#if defined(CONFIG_DISPLAY_CPUINFO) + print_cpuinfo, /* display cpu info (and speed) */ +#endif +#if defined(CONFIG_DISPLAY_BOARDINFO) + checkboard, /* display board info */ +#endif +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) + init_func_i2c, +#endif + dram_init, /* configure available RAM banks */ +#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI) + arm_pci_init, +#endif + NULL, +}; + +void board_init_f (ulong bootflag) +{ + bd_t *bd; + init_fnc_t **init_fnc_ptr; + gd_t *id; + ulong addr, addr_sp; + + /* Pointer is writable since we allocated a register for it */ + gd = (gd_t *) (CONFIG_SYS_INIT_SP_ADDR); + /* compiler optimization barrier needed for GCC >= 3.4 */ + __asm__ __volatile__("": : :"memory"); + + memset ((void*)gd, 0, sizeof (gd_t)); + + gd->mon_len = _bss_end - _TEXT_BASE; + + for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { + if ((*init_fnc_ptr)() != 0) { + hang (); + } + } + + debug ("monitor len: %08lX\n", gd->mon_len); + /* + * Ram is setup, size stored in gd !! + */ + debug ("ramsize: %08lX\n", gd->ram_size); +#if defined(CONFIG_SYS_MEM_TOP_HIDE) + /* + * Subtract specified amount of memory to hide so that it won't + * get "touched" at all by U-Boot. By fixing up gd->ram_size + * the Linux kernel should now get passed the now "corrected" + * memory size and won't touch it either. This should work + * for arch/ppc and arch/powerpc. Only Linux board ports in + * arch/powerpc with bootwrapper support, that recalculate the + * memory size from the SDRAM controller setup will have to + * get fixed. + */ + gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE; +#endif + + addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; + +#ifdef CONFIG_LOGBUFFER +#ifndef CONFIG_ALT_LB_ADDR + /* reserve kernel log buffer */ + addr -= (LOGBUFF_RESERVE); + debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr); +#endif +#endif + +#ifdef CONFIG_PRAM + /* + * reserve protected RAM + */ + i = getenv_r ("pram", (char *)tmp, sizeof (tmp)); + reg = (i > 0) ? simple_strtoul ((const char *)tmp, NULL, 10) : CONFIG_PRAM; + addr -= (reg << 10); /* size is in kB */ + debug ("Reserving %ldk for protected RAM at %08lx\n", reg, addr); +#endif /* CONFIG_PRAM */ + +#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE)) + /* reserve TLB table */ + addr -= (4096 * 4); + + /* round down to next 64 kB limit */ + addr &= ~(0x10000 - 1); + + gd->tlb_addr = addr; + debug ("TLB table at: %08lx\n", addr); +#endif + + /* round down to next 4 kB limit */ + addr &= ~(4096 - 1); + debug ("Top of RAM usable for U-Boot at: %08lx\n", addr); + +#ifdef CONFIG_VFD +# ifndef PAGE_SIZE +# define PAGE_SIZE 4096 +# endif + /* + * reserve memory for VFD display (always full pages) + */ + addr -= vfd_setmem (addr); + gd->fb_base = addr; +#endif /* CONFIG_VFD */ + +#ifdef CONFIG_LCD + /* reserve memory for LCD display (always full pages) */ + addr = lcd_setmem (addr); + gd->fb_base = addr; +#endif /* CONFIG_LCD */ + + /* + * reserve memory for U-Boot code, data & bss + * round down to next 4 kB limit + */ + addr -= gd->mon_len; + addr &= ~(4096 - 1); + + debug ("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr); + +#ifndef CONFIG_PRELOADER + /* + * reserve memory for malloc() arena + */ + addr_sp = addr - TOTAL_MALLOC_LEN; + debug ("Reserving %dk for malloc() at: %08lx\n", + TOTAL_MALLOC_LEN >> 10, addr_sp); + /* + * (permanently) allocate a Board Info struct + * and a permanent copy of the "global" data + */ + addr_sp -= sizeof (bd_t); + bd = (bd_t *) addr_sp; + gd->bd = bd; + debug ("Reserving %zu Bytes for Board Info at: %08lx\n", + sizeof (bd_t), addr_sp); + addr_sp -= sizeof (gd_t); + id = (gd_t *) addr_sp; + debug ("Reserving %zu Bytes for Global Data at: %08lx\n", + sizeof (gd_t), addr_sp); + + /* setup stackpointer for exeptions */ + gd->irq_sp = addr_sp; +#ifdef CONFIG_USE_IRQ + addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ); + debug ("Reserving %zu Bytes for IRQ stack at: %08lx\n", + CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp); +#endif + /* leave 3 words for abort-stack */ + addr_sp -= 3; + + /* 8-byte alignment for ABI compliance */ + addr_sp &= ~0x07; +#else + addr_sp += 128; /* leave 32 words for abort-stack */ + gd->irq_sp = addr_sp; +#endif + + debug ("New Stack Pointer is: %08lx\n", addr_sp); + +#ifdef CONFIG_POST + post_bootmode_init(); + post_run (NULL, POST_ROM | post_bootmode_get(0)); +#endif + + gd->bd->bi_baudrate = gd->baudrate; + /* Ram ist board specific, so move it to board code ... */ + dram_init_banksize(); + display_dram_config(); /* and display it */ + + gd->relocaddr = addr; + gd->start_addr_sp = addr_sp; + gd->reloc_off = addr - _TEXT_BASE; + debug ("relocation Offset is: %08lx\n", gd->reloc_off); + memcpy (id, (void *)gd, sizeof (gd_t)); + + relocate_code (addr_sp, id, addr); + + /* NOTREACHED - relocate_code() does not return */ +} + +#if !defined(CONFIG_SYS_NO_FLASH) +static char *failed = "*** failed ***\n"; +#endif + +/************************************************************************ + * + * This is the next part if the initialization sequence: we are now + * running from RAM and have a "normal" C environment, i. e. global + * data can be written, BSS has been cleared, the stack size in not + * that critical any more, etc. + * + ************************************************************************ + */ +void board_init_r (gd_t *id, ulong dest_addr) +{ + char *s; + bd_t *bd; + ulong malloc_start; +#if !defined(CONFIG_SYS_NO_FLASH) + ulong flash_size; +#endif +#if !defined(CONFIG_RELOC_FIXUP_WORKS) + extern void malloc_bin_reloc (void); +#if defined(CONFIG_CMD_BMP) + extern void bmp_reloc(void); +#endif +#if defined(CONFIG_CMD_I2C) + extern void i2c_reloc(void); +#endif +#endif + + gd = id; + bd = gd->bd; + + gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ + + monitor_flash_len = _bss_start - _TEXT_BASE; + debug ("monitor flash len: %08lX\n", monitor_flash_len); + board_init(); /* Setup chipselects */ + +#ifdef CONFIG_SERIAL_MULTI + serial_initialize(); +#endif + + debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr); + +#if !defined(CONFIG_RELOC_FIXUP_WORKS) + /* + * We have to relocate the command table manually + */ + fixup_cmdtable(&__u_boot_cmd_start, + (ulong)(&__u_boot_cmd_end - &__u_boot_cmd_start)); +#if defined(CONFIG_CMD_BMP) + bmp_reloc(); +#endif +#if defined(CONFIG_CMD_I2C) + i2c_reloc(); +#endif +#endif /* !defined(CONFIG_RELOC_FIXUP_WORKS) */ + +#ifdef CONFIG_LOGBUFFER + logbuff_init_ptrs (); +#endif +#ifdef CONFIG_POST + post_output_backlog (); +#ifndef CONFIG_RELOC_FIXUP_WORKS + post_reloc (); +#endif +#endif + + /* The Malloc area is immediately below the monitor copy in DRAM */ + malloc_start = dest_addr - TOTAL_MALLOC_LEN; + mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN); +#if !defined(CONFIG_RELOC_FIXUP_WORKS) + malloc_bin_reloc (); +#endif + +#if !defined(CONFIG_SYS_NO_FLASH) + puts ("FLASH: "); + + if ((flash_size = flash_init ()) > 0) { +# ifdef CONFIG_SYS_FLASH_CHECKSUM + print_size (flash_size, ""); + /* + * Compute and print flash CRC if flashchecksum is set to 'y' + * + * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX + */ + s = getenv ("flashchecksum"); + if (s && (*s == 'y')) { + printf (" CRC: %08X", + crc32 (0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size) + ); + } + putc ('\n'); +# else /* !CONFIG_SYS_FLASH_CHECKSUM */ + print_size (flash_size, "\n"); +# endif /* CONFIG_SYS_FLASH_CHECKSUM */ + } else { + puts (failed); + hang (); + } +#endif + +#if defined(CONFIG_CMD_NAND) + puts ("NAND: "); + nand_init(); /* go init the NAND */ +#endif + +#if defined(CONFIG_CMD_ONENAND) + onenand_init(); +#endif + +#ifdef CONFIG_HAS_DATAFLASH + AT91F_DataflashInit(); + dataflash_print_info(); +#endif + + /* initialize environment */ + env_relocate (); + +#ifdef CONFIG_VFD + /* must do this after the framebuffer is allocated */ + drv_vfd_init(); +#endif /* CONFIG_VFD */ + + /* IP Address */ + gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); + + stdio_init (); /* get the devices list going. */ + + jumptable_init (); + +#if defined(CONFIG_API) + /* Initialize API */ + api_init (); +#endif + + console_init_r (); /* fully init console as a device */ + +#if defined(CONFIG_ARCH_MISC_INIT) + /* miscellaneous arch dependent initialisations */ + arch_misc_init (); +#endif +#if defined(CONFIG_MISC_INIT_R) + /* miscellaneous platform dependent initialisations */ + misc_init_r (); +#endif + + /* set up exceptions */ + interrupt_init (); + /* enable exceptions */ + enable_interrupts (); + + /* Perform network card initialisation if necessary */ +#ifdef CONFIG_DRIVER_TI_EMAC + /* XXX: this needs to be moved to board init */ +extern void davinci_eth_set_mac_addr (const u_int8_t *addr); + if (getenv ("ethaddr")) { + uchar enetaddr[6]; + eth_getenv_enetaddr("ethaddr", enetaddr); + davinci_eth_set_mac_addr(enetaddr); + } +#endif + +#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96) + /* XXX: this needs to be moved to board init */ + if (getenv ("ethaddr")) { + uchar enetaddr[6]; + eth_getenv_enetaddr("ethaddr", enetaddr); + smc_set_mac_addr(enetaddr); + } +#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */ + + /* Initialize from environment */ + if ((s = getenv ("loadaddr")) != NULL) { + load_addr = simple_strtoul (s, NULL, 16); + } +#if defined(CONFIG_CMD_NET) + if ((s = getenv ("bootfile")) != NULL) { + copy_filename (BootFile, s, sizeof (BootFile)); + } +#endif + +#ifdef BOARD_LATE_INIT + board_late_init (); +#endif + +#ifdef CONFIG_GENERIC_MMC + puts ("MMC: "); + mmc_initialize (gd->bd); +#endif + +#ifdef CONFIG_BITBANGMII + bb_miiphy_init(); +#endif +#if defined(CONFIG_CMD_NET) +#if defined(CONFIG_NET_MULTI) + puts ("Net: "); +#endif + eth_initialize(gd->bd); +#if defined(CONFIG_RESET_PHY_R) + debug ("Reset Ethernet PHY\n"); + reset_phy(); +#endif +#endif + +#ifdef CONFIG_POST + post_run (NULL, POST_RAM | post_bootmode_get(0)); +#endif + +#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) + /* + * Export available size of memory for Linux, + * taking into account the protected RAM at top of memory + */ + { + ulong pram; + uchar memsz[32]; +#ifdef CONFIG_PRAM + char *s; + + if ((s = getenv ("pram")) != NULL) { + pram = simple_strtoul (s, NULL, 10); + } else { + pram = CONFIG_PRAM; + } +#else + pram=0; +#endif +#ifdef CONFIG_LOGBUFFER +#ifndef CONFIG_ALT_LB_ADDR + /* Also take the logbuffer into account (pram is in kB) */ + pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024; +#endif +#endif + sprintf ((char *)memsz, "%ldk", (bd->bi_memsize / 1024) - pram); + setenv ("mem", (char *)memsz); + } +#endif + + /* main_loop() can return to retry autoboot, if so just run it again. */ + for (;;) { + main_loop (); + } + + /* NOTREACHED - no way out of command loop except booting */ +} +#endif /* defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
void hang (void) { diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c index b2811f3..fe6d459 100644 --- a/arch/arm/lib/cache-cp15.c +++ b/arch/arm/lib/cache-cp15.c @@ -44,17 +44,44 @@ static void cp_delay (void) asm volatile("" : : : "memory"); }
-/* to activate the MMU we need to set up virtual memory: use 1M areas in bss */ +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +static inline void dram_bank_mmu_setup(int bank) +{ + u32 *page_table = (u32 *)gd->tlb_addr; + bd_t *bd = gd->bd; + int i; + + debug("%s: bank: %d\n", __func__, bank); + for (i = bd->bi_dram[bank].start >> 20; + i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >> 20; + i++) { + page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP; + } +} +#endif + +/* to activate the MMU we need to set up virtual memory: use 1M areas */ static inline void mmu_setup(void) { +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) + u32 *page_table = (u32 *)gd->tlb_addr; +#else static u32 __attribute__((aligned(16384))) page_table[4096]; bd_t *bd = gd->bd; - int i, j; + int j; +#endif + int i; u32 reg;
/* Set up an identity-mapping for all 4GB, rw for everyone */ for (i = 0; i < 4096; i++) page_table[i] = i << 20 | (3 << 10) | 0x12; + +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + dram_bank_mmu_setup(i); + } +#else /* Then, enable cacheable and bufferable for RAM only */ for (j = 0; j < CONFIG_NR_DRAM_BANKS; j++) { for (i = bd->bi_dram[j].start >> 20; @@ -63,6 +90,7 @@ static inline void mmu_setup(void) page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP; } } +#endif
/* Copy the page table address to cp15 */ asm volatile("mcr p15, 0, %0, c2, c0, 0" @@ -74,7 +102,6 @@ static inline void mmu_setup(void) reg = get_cr(); /* get control reg. */ cp_delay(); set_cr(reg | CR_M); - }
/* cache_bit must be either CR_I or CR_C */ @@ -96,6 +123,10 @@ static void cache_disable(uint32_t cache_bit) uint32_t reg;
if (cache_bit == CR_C) { + /* if cache isn;t enabled no need to disable */ + reg = get_cr(); + if ((reg & CR_C) != CR_C) + return; /* if disabling data cache, disable mmu too */ cache_bit |= CR_M; flush_cache(0, ~0); diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c index 1f2b815..9a21e7b 100644 --- a/arch/arm/lib/interrupts.c +++ b/arch/arm/lib/interrupts.c @@ -38,15 +38,20 @@ #include <common.h> #include <asm/proc-armv/ptrace.h>
-#ifdef CONFIG_USE_IRQ DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_USE_IRQ int interrupt_init (void) { /* * setup up stacks if necessary */ +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) + IRQ_STACK_START = gd->irq_sp - 4; + IRQ_STACK_START_IN = gd->irq_sp + 8; +#else IRQ_STACK_START = _armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4; +#endif FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
return arch_interrupt_init(); @@ -81,6 +86,18 @@ int disable_interrupts (void) return (old & 0x80) == 0; } #else +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +int interrupt_init (void) +{ + /* + * setup up stacks if necessary + */ + IRQ_STACK_START_IN = gd->irq_sp + 8; + + return 0; +} +#endif + void enable_interrupts (void) { return; diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index cc81543..4c3040a 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -343,7 +343,16 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf ("ip_addr = %pI4\n", &bd->bi_ip_addr); #endif printf ("baudrate = %d bps\n", bd->bi_baudrate); - +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE)) + print_num ("TLB addr", gd->tlb_addr); +#endif + print_num ("relocaddr", gd->relocaddr); + print_num ("reloc off", gd->reloc_off); + print_num ("irq_sp", gd->irq_sp); /* irq stack pointer */ + print_num ("sp start ", gd->start_addr_sp); + print_num ("FB base ", gd->fb_base); +#endif return 0; }
diff --git a/common/cmd_bmp.c b/common/cmd_bmp.c index d51cc55..6fa8a15 100644 --- a/common/cmd_bmp.c +++ b/common/cmd_bmp.c @@ -137,6 +137,12 @@ static cmd_tbl_t cmd_bmp_sub[] = { U_BOOT_CMD_MKENT(display, 5, 0, do_bmp_display, "", ""), };
+#ifndef CONFIG_RELOC_FIXUP_WORKS +void bmp_reloc(void) { + fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub)); +} +#endif + /* * Subroutine: do_bmp * diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index 5e9135e..48de54b 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -1287,6 +1287,12 @@ static cmd_tbl_t cmd_i2c_sub[] = { U_BOOT_CMD_MKENT(speed, 1, 1, do_i2c_bus_speed, "", ""), };
+#ifndef CONFIG_RELOC_FIXUP_WORKS +void i2c_reloc(void) { + fixup_cmdtable(cmd_i2c_sub, ARRAY_SIZE(cmd_i2c_sub)); +} +#endif + static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { cmd_tbl_t *c; diff --git a/doc/README.arm-relocation b/doc/README.arm-relocation new file mode 100644 index 0000000..6be1a12 --- /dev/null +++ b/doc/README.arm-relocation @@ -0,0 +1,321 @@ +To make relocation on arm working, the following changes are done: + +Add new compilerflag: + +-fPIC + + -> compiler generates position independent code + +changes in board code: + +- dram_init: + - bd pointer is now at this point not accessible, so only + detect the real dramsize, and store it in gd->ram_size. + best detected with get_ram_size(); + ToDo: move there also the dram initialization on boards where + it is possible. + - setup the bd_t dram bank info in the new function + dram_init_banksize(). + +- board.c code is adapted from ppc code + +- undef CONFIG_RELOC_FIXUP_WORKS + + -> cmdtabl, and subcommand table must be handled from "hand" + collected in section "__datarellocal_start". + + - How To fixup the sections: + + __datarel_start, __datarelrolocal_start, __datarellocal_start and + __datarelro_start + + automatically? Then it should be possible to define again + CONFIG_RELOC_FIXUP_WORKS + +- irq stack setup is now not longer on a fix position, instead it is + calculated in board_init_f, and stored in gd->irq_sp + +------------------------------------------------------------------------------------- + +To compile a board without relocation, define CONFIG_SYS_ARM_WITHOUT_RELOC +This possibility will removed!! So please fix your board to compile without +CONFIG_SYS_ARM_WITHOUT_RELOC defined!!! + +------------------------------------------------------------------------------------- + +ToDo: + +- fill in bd_t infos (check) +- adapt all boards + +- maybe adapt TEXT_BASE (this must be checked from board maintainers) + This *must* be done for boards, which boot from NOR flash + + on other boards if TEXT_BASE = relocation baseaddr, this saves + one copying from u-boot code. + +- new function dram_init_banksize() is actual board specific. Maybe + we make a weak default function in arch/arm/lib/board.c ? + +------------------------------------------------------------------------------------- + +Relocation with NAND_SPL (example for the tx25): + +- cpu copies the first page from NAND to 0xbb000000 (IMX_NFC_BASE) + and start with code execution on this address. + +- The First page contains u-boot code from u-boot:nand_spl/nand_boot_fsl_nfc.c + which inits the dram, cpu registers, reloacte itself to TEXT_BASE and loads + the "real" u-boot to CONFIG_SYS_NAND_U_BOOT_DST and starts execution + @CONFIG_SYS_NAND_U_BOOT_START + +- This u-boot does no ram int, nor cpu register setup. Just looks + where it have to relocate and relocate itself to this address. + If relocate address = TEXT_BASE(not the same, as the TEXT_BASE + from the nand_spl code), no need to copy, just go on with bss clear + and jump to board_init_r. + +------------------------------------------------------------------------------------- + +Relocation: +How to translate flash addresses in GOT to ram addresses. +This is automagically done from code, but this example +shows, how this magic code works ;-) +(example on the qong board) + +Find a variable: + +a) search it in System.map +(for example flash_info) + +a005b4c0 B BootpID +a005b4c4 B BootpTry +a005b4c8 b slave +a005b4cc B flash_info +^^^^^^^^ +a005c908 b saved_sector.4002 +a005c910 b cfi_mtd_info +a005c9c0 b cfi_mtd_names +a005c9d0 B mtd_table + +--------------------------------------- + +b) create hexdump from u-boot code: + +hexdump -C u-boot > gnlmpfhex + +--------------------------------------- + +c) search the variables address in the hexdump + + +* +0005fc80 00 00 00 00 00 00 00 00 2c 06 01 a0 18 cd 05 a0 |........,.......| +0005fc90 9c d4 05 a0 bc b4 05 a0 1c 7f 05 a0 f0 05 01 a0 |................| +0005fca0 08 5a 04 a0 1c ab 05 a0 ec a4 05 a0 98 c3 01 a0 |.Z..............| +0005fcb0 a0 d6 05 a0 04 71 05 a0 c0 f9 00 a0 3c cd 05 a0 |.....q......<...| +0005fcc0 cc b4 05 a0 f0 fa 00 a0 f0 d6 05 a0 10 86 05 a0 |................| + ^^^^^^^^^^^ +0005fcd0 a4 16 06 a0 dc 64 05 a0 18 86 05 a0 52 48 05 a0 |.....d......RH..| +0005fce0 c0 86 05 a0 24 6e 02 a0 b4 6c 05 a0 b0 94 01 a0 |....$n...l......| +0005fcf0 1c 86 05 a0 50 85 05 a0 d4 0c 06 a0 bc 0b 06 a0 |....P...........| + + +-> 0005fcc0 + +---------------------------------------- + +d) know we calculate this address in RAM + + + 8ff08000 (new address of code in RAM *1) + ++ 0005fcc0 + +- 00008000 (offset of text *2) + +---------- + + 8ff5fcc0 -> Addr GOT in RAM + +*1: +activate debug and look for the line: +Now running in RAM - U-Boot at: 8ff08000 + ^^^^^^^^ + new address of u-boot code in RAM + +*2: +Section Headers: + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .text PROGBITS a0000000 008000 04599c 00 AX 0 0 32 + ^^^^^^ + Offset of text + +---------------------------------------- + +e) now we look in 8ff5fcc0 (RAM) + + +QongEVB>md 0x8ff5fcc0 +8ff5fcc0 : a005b4cc a000faf0 a005d6f0 a0058610 ................ + ^^^^^^^^ + Bingo, here we have the old flash address (when relocation + is working, here is the fixed ram address. see @ f, how + it gets calculated) + + +---------------------------------------- + +f) now translate it in the new RAM address + + a005b4cc + +- a0000000 TextBase + ++ 8ff08000 new address of u-boot in ram +---------- + 8ff634cc + +QongEVB>mm 0x8ff5fcc0 0x8ff634cc 1 +QongEVB>md 0x8ff5fcc0 +8ff5fcc0 : 8ff634cc a000faf0 a005d6f0 a0058610 .4.............. +8ff5fcd0 : a00616a4 a00564dc a0058618 a0054852 .....d......RH.. + +As this must be done for all address in the GOT, the u-boot +code did this automagically ... :-) + +---------------------------------------------- + +g) check if the new address is really in the bss section: + +bss start: +8ff6054c (8ff08000 + 0005854C monitorlen) + +bss end: +8ff698ac (8ff08000 + 618AC) + +8ff634cc is in bss :-) + +---------------------------------------------- + +h) u-boot prints: + +important addresses: + +U-Boot code: A0000000 -> A005854C BSS: -> A00618AC TextBase 0xa0000000 +Now running in RAM - U-Boot at: 8ff08000 relocBase 0x8ff08000 + + +--------- + +U-Boot 2010.06-rc2-00002-gf8fbb25-dirty (Jun 18 2010 - 17:07:19) + +U-Boot code: A0000000 -> A005854C BSS: -> A00618AC +CPU: Freescale i.MX31 at 398 MHz +Board: DAVE/DENX Qong +mon: FFFFFFFF gd->monLen: 000618AC +Top of RAM usable for U-Boot at: 90000000 +LCD panel info: 640 x 480, 16 bit/pix +Reserving 600k for LCD Framebuffer at: 8ff6a000 +Reserving 390k for U-Boot at: 8ff08000 +Reserving 1280k for malloc() at: 8fdc8000 +Reserving 28 Bytes for Board Info at: 8fdc7fe4 +Reserving 48 Bytes for Global Data at: 8fdc7fb4 +New Stack Pointer is: 8fdc7fb0 +RAM Configuration: +Bank #0: 80000000 256 MiB +mon: 0005854C gd->monLen: 000618AC +Now running in RAM - U-Boot at: 8ff08000 + +------------------------------------------------------------------------------------- + +Debugging u-boot in RAM: +(example on the qong board) + +a) add in config.mk: + +PLATFORM_CPPFLAGS += -DDEBUG + +----------------- + +b) start debugger + +arm-linux-gdb u-boot + +[hs@pollux u-boot]$ arm-linux-gdb u-boot +GNU gdb Red Hat Linux (6.7-2rh) +Copyright (C) 2007 Free Software Foundation, Inc. +License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. Type "show copying" +and "show warranty" for details. +This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux". +The target architecture is set automatically (currently arm) +.. +(gdb) + +----------------- + +c) connect to target + +target remote bdi10:2001 + +(gdb) target remote bdi10:2001 +Remote debugging using bdi10:2001 +0x8ff17f10 in ?? () +(gdb) + +----------------- + +d) discard symbol-file + +(gdb) symbol-file +Discard symbol table from `/home/hs/celf/u-boot/u-boot'? (y or n) y +No symbol file now. +(gdb) + +----------------- + +e) load new symbol table: + +(gdb) add-symbol-file u-boot 0x8ff08000 +add symbol table from file "u-boot" at + .text_addr = 0x8ff08000 +(y or n) y +Reading symbols from /home/hs/celf/u-boot/u-boot...done. +(gdb) c +Continuing. +^C +Program received signal SIGSTOP, Stopped (signal). +0x8ff17f18 in serial_getc () at serial_mxc.c:192 +192 while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY); +(gdb) + +add-symbol-file u-boot 0x8ff08000 + ^^^^^^^^^^ + get this address from u-boot debug printfs + +U-Boot 2010.06-rc2-00009-gf77b8b8-dirty (Jun 22 2010 - 09:43:46) + +U-Boot code: A0000000 -> A0058BAC BSS: -> A0061F10 +CPU: Freescale i.MX31 at 398 MHz +Board: DAVE/DENX Qong +mon: FFFFFFFF gd->monLen: 00061F10 +Top of RAM usable for U-Boot at: 90000000 +LCD panel info: 640 x 480, 16 bit/pix +Reserving 600k for LCD Framebuffer at: 8ff6a000 +Reserving 391k for U-Boot at: 8ff08000 + ^^^^^^^^ +Reserving 1280k for malloc() at: 8fdc8000 +Reserving 24 Bytes for Board Info at: 8fdc7fe8 +Reserving 52 Bytes for Global Data at: 8fdc7fb4 +New Stack Pointer is: 8fdc7fb0 +RAM Configuration: +Bank #0: 80000000 256 MiB +relocation Offset is: eff08000 +mon: 00058BAC gd->monLen: 00061F10 +Now running in RAM - U-Boot at: 8ff08000 + ^^^^^^^^ + +Now you can use gdb as usual :-) diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c index b9fd6f5..18ecbe1 100644 --- a/nand_spl/nand_boot.c +++ b/nand_spl/nand_boot.c @@ -221,6 +221,13 @@ static int nand_load(struct mtd_info *mtd, unsigned int offs, return 0; }
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +void board_init_f (ulong bootflag) +{ + relocate_code (TEXT_BASE - TOTAL_MALLOC_LEN, NULL, TEXT_BASE); +} +#endif + /* * The main entry for NAND booting. It's necessary that SDRAM is already * configured and available since this code loads the main U-Boot image diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index ea3566b..3105657 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -263,6 +263,13 @@ static int nand_load(unsigned int from, unsigned int size, unsigned char *buf) return 0; }
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +void board_init_f (ulong bootflag) +{ + relocate_code (TEXT_BASE - TOTAL_MALLOC_LEN, NULL, TEXT_BASE); +} +#endif + /* * The main entry for NAND booting. It's necessary that SDRAM is already * configured and available since this code loads the main U-Boot image

Le 11/08/2010 20:16, Heiko Schocher a écrit :
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 54519b0..88c6427 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c
+init_fnc_t *init_sequence[] = {
Tested this code tonight, and I noticed that if the image is run from another location than the one it was linked for, then access to init_sequence is not made at the right location. To get correct access regardless of the image location, init_sequence has to be defined const.
I suspect that the same applies to all globals used by any function called during board_init_f execution.
Amicalement,

Hello Albert,
Albert ARIBAUD wrote:
Le 11/08/2010 20:16, Heiko Schocher a écrit :
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 54519b0..88c6427 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c
+init_fnc_t *init_sequence[] = {
Tested this code tonight, and I noticed that if the image is run from another location than the one it was linked for, then access to init_sequence is not made at the right location. To get correct access regardless of the image location, init_sequence has to be defined const.
Hmm.. at this place code is not relocated! So it should be executed on the right address. Don;t know, if this would be the only problem, if you run this code from another address ...
I suspect that the same applies to all globals used by any function called during board_init_f execution.
bye Heiko

Hello Heiko.
Hmm.. at this place code is not relocated! So it should be executed on the right address.
May I say this is a huge step back from the non-relocation case?
One of the things I love(d) with u-boot (at least the ARM one) is that I could place it in flash at any address and it would just work. So when I have a new binary I first write it to another flash sector and "go" to it. Only if it works I flash at offset 0. Sure I test in RAM first, but since writing the ram image to flash is not uncommon, the final test for me has always been in flash -- also for other reasons.
I also think that simpler is better and I never understood the contorsions of relocation.... but I wouldn't argue if it wasn't a step back (I know the advantages, like going to end of ram, but they don't mean much to me).
Is there any chance we could go on testing on a different flash address without relinking in-between (with the risk of mismatching the two images?)
Thanks /alessandro

Dear Alessandro Rubini,
In message 20100916062347.GA25290@morgana.i.gnudd.com you wrote:
One of the things I love(d) with u-boot (at least the ARM one) is that I could place it in flash at any address and it would just work. So when I have a new binary I first write it to another flash sector and "go" to it. Only if it works I flash at offset 0. Sure I test in RAM
This may, or may not work. In general you have to be lucky if it does work. Many processors have steps in their initialization sequence which cannot be repeated easily, at least not without a reset.
first, but since writing the ram image to flash is not uncommon, the final test for me has always been in flash -- also for other reasons.
Even if it works, this is not, and cannot be, any guarantee that the image would run when started out of reset. On contrary, on many processors you will have to modify the code so that it can be started on an already running system.
Is there any chance we could go on testing on a different flash address without relinking in-between (with the risk of mismatching the two images?)
I don't understand why you think this could (or should) be working?
We have a static configuration with CONFIG_SKIP_LOWLEVEL_INIT (and CONFIG_SKIP_RELOCATE_UBOOT); if CONFIG_SKIP_LOWLEVEL_INIT is not set, starting another U-Boot instance with "go" would repeat the whole low-level initialization which _will_ break on many systems.
I agree that it would be nice to have U-Boot completely position- independent and completelky restartable, but this would be a new feature, which newer existed before.
Best regards,
Wolfgang Denk

On Thu, Sep 16, 2010 at 5:06 PM, Wolfgang Denk wd@denx.de wrote:
Dear Alessandro Rubini,
I agree that it would be nice to have U-Boot completely position- independent and completelky restartable, but this would be a new feature, which newer existed before.
x86 has a nice feature whereby I can build two images that differ only by TEXT_BASE. I can build using TEXT_BASE somewhere in low memory, tftp the image and the 'go' directly to the base address of the image
e.g.
tftp 6000000 u-boot.bin go 6000000
This works because the x86 reset vector is at top of memory (0xfffffff0), not bottom (0x00000000) so the very first bytes of u-boot.bin are not the reset vector, but rather where the reset vector jumps to after performing some very low-level hardware init
Both images, as a very first step, relocate to the highest available memory location and adjust all the relocation offsets in the image and jump into the relocated image.
As long as I do not mess with the low-level init code, I can be confident that an image that 'boots' using the 'go' command will boot from Flash
No, it is not a 'fully relocatable' image, but it is so close as to not make any real difference to me.
Regards,
Graeme

Dear Graeme Russ,
In message AANLkTimDxzWm9-sekLv60-zNDFmBKE3dc=kxiO+ZqZZn@mail.gmail.com you wrote:
I agree that it would be nice to have U-Boot completely position- independent and completelky restartable, but this would be a new feature, which newer existed before.
x86 has a nice feature whereby I can build two images that differ only by TEXT_BASE. I can build using TEXT_BASE somewhere in low memory, tftp the image and the 'go' directly to the base address of the image
You can build such images for any architecture, but usually they will not work.
The code assumes to be started at the reset vector, and to find a CPU with all peripherals and registers in virgine state which is only present after a reset.
On many processors there are certain steps that are irreversiable by software - there are write-once registers, there are memory controller registers which change the behaviour of the memory controller when the are written for the first time, etc.
This works because the x86 reset vector is at top of memory (0xfffffff0), not bottom (0x00000000) so the very first bytes of u-boot.bin are not the reset vector, but rather where the reset vector jumps to after performing some very low-level hardware init
The actual position of the reset vector in the address space has nothing to do with that isse. It's other things like register states or mode of operation of certain units (memory controller, MMU etc.) that are different when coming frash out of reset versus when coming from a running U-Boot systems.
As long as I do not mess with the low-level init code, I can be confident that an image that 'boots' using the 'go' command will boot from Flash
This _may_ work on certain boards and processors, but it does not (and I think it cannot) work in general.
Best regards,
Wolfgang Denk

On 16/09/10 18:23, Wolfgang Denk wrote:
Dear Graeme Russ,
In message AANLkTimDxzWm9-sekLv60-zNDFmBKE3dc=kxiO+ZqZZn@mail.gmail.com you wrote:
I agree that it would be nice to have U-Boot completely position- independent and completelky restartable, but this would be a new feature, which newer existed before.
x86 has a nice feature whereby I can build two images that differ only by TEXT_BASE. I can build using TEXT_BASE somewhere in low memory, tftp the image and the 'go' directly to the base address of the image
You can build such images for any architecture, but usually they will not work.
The code assumes to be started at the reset vector, and to find a CPU with all peripherals and registers in virgine state which is only present after a reset.
On many processors there are certain steps that are irreversiable by software - there are write-once registers, there are memory controller registers which change the behaviour of the memory controller when the are written for the first time, etc.
I have the same constraints. For example, I cannot reconfigure the DRAM controller or perform memory sizing after tftp'ing the new image as they are likely to destroy it.
This works because the x86 reset vector is at top of memory (0xfffffff0), not bottom (0x00000000) so the very first bytes of u-boot.bin are not the reset vector, but rather where the reset vector jumps to after performing some very low-level hardware init
The actual position of the reset vector in the address space has nothing to do with that isse. It's other things like register states
True, but it does make life easier to know the 'go' address is the same as the load address
or mode of operation of certain units (memory controller, MMU etc.) that are different when coming frash out of reset versus when coming from a running U-Boot systems.
I have a 'cold-boot' parameter which is set by the reset vector code. I can use this to selectively skip 'once-only' initialisation
As long as I do not mess with the low-level init code, I can be confident that an image that 'boots' using the 'go' command will boot from Flash
This _may_ work on certain boards and processors, but it does not (and I think it cannot) work in general.
I don't doubt that you are entirely correct. But there are many ways to skin a cat. My problem was to reduce the build->burn->boot development time where the burn phase was the longest. The low level boot and device initialisation all works and hasn't changed in quite a while, so I can rely on what is on my (nearly a year) old image.
I don't see what I am doing as very far removed from the 'ipl' framework. I have on my 'TODO' list to split the low-level init which always runs from flash from the higher level code which runs relocated. From there, I can create a fully position independent image which could be located anywhere (on the boot flash, on other on-board flash, NAND device etc)
A common framework (within the bounds of cross-architecture limitations) would be nice
Regards,
Graeme

On Thu, Sep 16, 2010 at 07:54:03PM +1000, Graeme Russ wrote: [...]
I have a 'cold-boot' parameter which is set by the reset vector code. I can use this to selectively skip 'once-only' initialisation
[...]
I don't doubt that you are entirely correct. But there are many ways to skin a cat. My problem was to reduce the build->burn->boot development time where the burn phase was the longest. The low level boot and device initialisation all works and hasn't changed in quite a while, so I can rely on what is on my (nearly a year) old image.
I see this feature not only nice to speed up development, sometimes it also comes in really handy for production, too - if you have to struggle with debugging tools that are either plain too stupid to program some flash devices or are much slower than U-Boot, you can simply run a specially built version from RAM and/or provide it with an environment in RAM to do all the actual flashing for the board production.
A common framework (within the bounds of cross-architecture limitations) would be nice
For some targets, there may be fragments present in the code when searching for CONFIG_MONITOR_IS_IN_RAM, which statically disables all the low-level initialization to allow U-Boot being loaded from a first-stage loader or debugger. But beware, it is not always functional out-of-the-box.
Regards, Wolfgang

Le 16/09/2010 12:18, Wolfgang Wegner a écrit :
On Thu, Sep 16, 2010 at 07:54:03PM +1000, Graeme Russ wrote: [...]
I have a 'cold-boot' parameter which is set by the reset vector code. I can use this to selectively skip 'once-only' initialisation
[...]
I don't doubt that you are entirely correct. But there are many ways to skin a cat. My problem was to reduce the build->burn->boot development time where the burn phase was the longest. The low level boot and device initialisation all works and hasn't changed in quite a while, so I can rely on what is on my (nearly a year) old image.
I see this feature not only nice to speed up development, sometimes it also comes in really handy for production, too - if you have to struggle with debugging tools that are either plain too stupid to program some flash devices or are much slower than U-Boot, you can simply run a specially built version from RAM and/or provide it with an environment in RAM to do all the actual flashing for the board production.
A common framework (within the bounds of cross-architecture limitations) would be nice
For some targets, there may be fragments present in the code when searching for CONFIG_MONITOR_IS_IN_RAM, which statically disables all the low-level initialization to allow U-Boot being loaded from a first-stage loader or debugger. But beware, it is not always functional out-of-the-box.
For ARM926, you can disable low level init stuff and run from RAM by defining CONFIG_SKIP_LOWLEVEL_INIT. This works and is actively used in kirkwood where low level init is done by a previous loader.
(independently you can disable relocation from FLASH to RAM with CONFIG_SKIP_RELOCATE_UBOOT.)
Maybe we could start by standardizing a single (set of) config option(s) for skipping inits and have all boards use that?
Amicalement,

Dear Wolfgang Wegner,
In message 20100916101810.GH25692@leila.ping.de you wrote:
I see this feature not only nice to speed up development, sometimes it also comes in really handy for production, too - if you have to
I think we all agree that this would be a nice-to-have feature.
struggle with debugging tools that are either plain too stupid to program some flash devices or are much slower than U-Boot, you can simply run a specially built version from RAM and/or provide it with an environment in RAM to do all the actual flashing for the board production.
Note the "specially built version". My understanding is that this "special building" cannot be avoided in general.
For some targets, there may be fragments present in the code when searching for CONFIG_MONITOR_IS_IN_RAM, which statically disables all the low-level initialization to allow U-Boot being loaded from a first-stage loader or debugger. But beware, it is not always functional out-of-the-box.
True. And the image configured that way is not the same binary image that you normally load into flash.
Best regards,
Wolfgang Denk

Dear Wolfgang Denk,
On Thu, Sep 16, 2010 at 01:06:01PM +0200, Wolfgang Denk wrote:
Dear Wolfgang Wegner,
In message 20100916101810.GH25692@leila.ping.de you wrote:
[...]
struggle with debugging tools that are either plain too stupid to program some flash devices or are much slower than U-Boot, you can simply run a specially built version from RAM and/or provide it with an environment in RAM to do all the actual flashing for the board production.
Note the "specially built version". My understanding is that this "special building" cannot be avoided in general.
I do not know if it can be avoided in general, but if it is architecture- dependent, maybe those architectures supporting such a boot procedure to allow doing this with a single image could be made to support it out-of-the-box. Then the other architectures could still benefit from more awareness of something like "CONFIG_MONITOR_IS_IN_RAM" or "CONFIG_SKIP_LOWLEVEL_INIT".
For some targets, there may be fragments present in the code when searching for CONFIG_MONITOR_IS_IN_RAM, which statically disables all the low-level initialization to allow U-Boot being loaded from a first-stage loader or debugger. But beware, it is not always functional out-of-the-box.
True. And the image configured that way is not the same binary image that you normally load into flash.
Currently it is not, and I do not know if it is possible at all for every architecture and worth the effort to make a single image for both cases, but as there seem to be already some architectures out there with (maybe somewhat limited) support, it looks like an interesting thought to me.
Best regards, Wolfgang

Le 16/09/2010 07:09, Heiko Schocher a écrit :
Hello Albert,
Albert ARIBAUD wrote:
Le 11/08/2010 20:16, Heiko Schocher a écrit :
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 54519b0..88c6427 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c
+init_fnc_t *init_sequence[] = {
Tested this code tonight, and I noticed that if the image is run from another location than the one it was linked for, then access to init_sequence is not made at the right location. To get correct access regardless of the image location, init_sequence has to be defined const.
Hmm.. at this place code is not relocated! So it should be executed on the right address. Don;t know, if this would be the only problem, if you run this code from another address ...
Well, the main goal of -fPIC is that the code should be able to run from anywhere, so it should be able to run from anywhere in FLASH. Besides, that can be useful for designs where two (possibly differently built) images of u-boot are located in FLASH and some mechanism allows booting from either.
(I personally have another motive for having at least the _f part of u-boot able to run fully PIC, as I want to implement direct-to-u-boot resetting on targets that have a reset vector rather far away from the end of the addressable space but too near to fit u-boot in, e.g. the orion5x which resets as 0xffff0000: 64 KB is too small for u-boot. I have submitted a patch for this then withdrawn it because of the relocation patches; however for this conversation, we can keep this point aside)
As for what would or would not work, ATM it boils down to 'access to const variables will be position-independent, access to others will not'. Non-initialized as well as initialized-but-not-const globals are always accessed at their link location before and after relocation, and thus will work only if you're running the image at its linked location.
This means that non-const data obviously can't work when the image is linked to FLASH; and they can even wreak havoc if the image linked for RAM and relocated near, but not exactly at, its linked location. The fact that it did not break so far in u-boot without reloc (and yes, several drivers do access globals during in-FLASH board init) is due to the fact that DRAM is already initialized when drivers access these globals at their linked location; this breaks when the image is linked for a location in FLASH.
Of course solving the init data issue (by making them const) will not solve the issue of rw data. For this one I see two solutions:
1) forbid using such data in drivers during _f phase if that is possible. For instance, in the timer.c driver of orion5x, the timer_init code accesses two writable variables because it wants to have a first reference for rollover detection; this can obviously be postponed to the _r init phase.
2) in case where the _f phase *has* to store data in globals, then this data should go to the globals space allocated below the stack, where gd also resides, and be later copied to usual globals if reqired.
BTW, the comments in board.c say that the _f init functions receive a pointer to gd; actually they dont, they're int (*) (void). Were the comments always out-of-sync with the code, or was there a removal of the gd argument for some reason?
Amicalement,

Dear Albert ARIBAUD,
In message 4C91F659.7020607@free.fr you wrote:
Well, the main goal of -fPIC is that the code should be able to run from anywhere, so it should be able to run from anywhere in FLASH. Besides,
You misread that. We actually make no attempts that the code can be run from any arbitrary address. On contrary - we explicitly link it for a fixed address map, which is defined by the location of the reset vector, which is the one and only defined entry point into U-Boot.
[I'm giving the generic, architecture independent view of U-Boot here. Actual implementations for some processors may behave differently, but this is nothing you should build on.]
that can be useful for designs where two (possibly differently built) images of u-boot are located in FLASH and some mechanism allows booting from either.
The only reasonable use cases for such a szenario that I am aware of would be best implemented in hardware, by being able to toggle between two banks of flash memory, selecting one or the other as boot device. Then you can even use the same U-Boot binary images, which is a good thing in such setups. [eventualkly you want to store the environment somewhere else, say in some storage device on the backplane, so all instances of U-Boot refer to the same data.]
(I personally have another motive for having at least the _f part of u-boot able to run fully PIC, as I want to implement direct-to-u-boot resetting on targets that have a reset vector rather far away from the end of the addressable space but too near to fit u-boot in, e.g. the orion5x which resets as 0xffff0000: 64 KB is too small for u-boot. I have submitted a patch for this then withdrawn it because of the relocation patches; however for this conversation, we can keep this point aside)
I do not understand this what you mean by that, or what the problem might be. It is trivial to arrange the code such that no significant gaps remain. This requires just a little tuning of the linker script.
As for what would or would not work, ATM it boils down to 'access to const variables will be position-independent, access to others will not'. Non-initialized as well as initialized-but-not-const globals are always accessed at their link location before and after relocation, and thus will work only if you're running the image at its linked location.
Again, please keep in mind that (1) this depends on the linker script, and (2) that before relocation to RAM _all_ access to global variables is extremely limited as we have only a read-only data segment and no BSS segment at all.
This means that non-const data obviously can't work when the image is linked to FLASH; and they can even wreak havoc if the image linked for RAM and relocated near, but not exactly at, its linked location. The
I don't understand what you mean. Are you aware of the restrictions of the execution environment before relocation to RAM?
fact that it did not break so far in u-boot without reloc (and yes, several drivers do access globals during in-FLASH board init) is due to the fact that DRAM is already initialized when drivers access these globals at their linked location; this breaks when the image is linked for a location in FLASH.
If any drivers do such things, and if these drivers are used before relocation to RAM, these are serious bugs that must be fixed.
If you are aware of such bugs please post this information, so people can start working on fixes.
Of course solving the init data issue (by making them const) will not solve the issue of rw data. For this one I see two solutions:
- forbid using such data in drivers during _f phase if that is
This is, and has always been, the case.
possible. For instance, in the timer.c driver of orion5x, the timer_init code accesses two writable variables because it wants to have a first reference for rollover detection; this can obviously be postponed to the _r init phase.
Hm... I don;t see global variables being used in timer_init() in "arch/arm/cpu/arm926ejs/orion5x/timer.c" - which exact code are you referring to?
- in case where the _f phase *has* to store data in globals, then this
data should go to the globals space allocated below the stack, where gd also resides, and be later copied to usual globals if reqired.
It seems you really minunderstand the excution environment before relocation. Ther eis also no steck there, and of course no "globals space allocated below the stack", because we don't even have the RAM initialized yet.
BTW, the comments in board.c say that the _f init functions receive a pointer to gd; actually they dont, they're int (*) (void). Were the comments always out-of-sync with the code, or was there a removal of the gd argument for some reason?
Please read the code, and the README. Please pay special attention to section "Initial Stack, Global Data:".
In short: the pointer to the global data is passed in a register, which we reserve for this purpose.
Best regards,
Wolfgang Denk

Le 16/09/2010 13:29, Wolfgang Denk a écrit :
Dear Albert ARIBAUD,
In message4C91F659.7020607@free.fr you wrote:
Well, the main goal of -fPIC is that the code should be able to run from anywhere, so it should be able to run from anywhere in FLASH. Besides,
You misread that. We actually make no attempts that the code can be run from any arbitrary address. On contrary - we explicitly link it for a fixed address map, which is defined by the location of the reset vector, which is the one and only defined entry point into U-Boot.
I did not write 'the goal of using fPIC in u-boot', I wrote 'the goal of fPIC', and as such, I think I read it right. I do agree though (and I think I made it clear further in my post) that u-boot images are linked for a fixed location and that their entry point is at the first address of this location.
However, I disagree with the fact that u-boot's link address would always be the reset vector location. This is not generally true, and this is especially not true for the orion5x, which is linked for its RAM location, not for its FLASH location, and for which the image is flashed so that _start does not end up at the reset address. And in that context, u-boot is designed to execute -- once jumped at from the reset vector -- to start running at a location (in FLASH) different from the one it was linked for (the RAM) until it has relocated itself to its intended RAM address, at which point it jumps there.
[I'm giving the generic, architecture independent view of U-Boot here. Actual implementations for some processors may behave differently, but this is nothing you should build on.]
[Except when working with these processors. :) ]
that can be useful for designs where two (possibly differently built) images of u-boot are located in FLASH and some mechanism allows booting from either.
The only reasonable use cases for such a szenario that I am aware of would be best implemented in hardware, by being able to toggle between two banks of flash memory, selecting one or the other as boot device. Then you can even use the same U-Boot binary images, which is a good thing in such setups. [eventualkly you want to store the environment somewhere else, say in some storage device on the backplane, so all instances of U-Boot refer to the same data.]
(I personally have another motive for having at least the _f part of u-boot able to run fully PIC, as I want to implement direct-to-u-boot resetting on targets that have a reset vector rather far away from the end of the addressable space but too near to fit u-boot in, e.g. the orion5x which resets as 0xffff0000: 64 KB is too small for u-boot. I have submitted a patch for this then withdrawn it because of the relocation patches; however for this conversation, we can keep this point aside)
I do not understand this what you mean by that, or what the problem might be. It is trivial to arrange the code such that no significant gaps remain. This requires just a little tuning of the linker script.
As for what I am trying to do: ironically, I am trying to find a way that the entry point of u-boot be at the reset vector location, just as it should.
As for you suggestion of arranging the code so that the entry point ends up at 0xffff0000, it requires much more than a little tuning of the linker script. This tuning is actually a long and suboptimal process akin to the bin packing problem, where you'd have to split sections, notably .text, and then shuffle sections in memory areas while hoping that no section is going to grow bigger than the memory region it was assigned to. And then, change one thing in the config, and you may need to solve the problem yet again.
This would be a huge inconvenience and a clumsy way of doing things, when another solution allows keeping the current linear, single-region, all-initialized-content-in-one-block mapping and requires only flashing the image in a clever way (although I'm saying it myself) and adding around twenty instructions to the existing start.S.
As for what would or would not work, ATM it boils down to 'access to const variables will be position-independent, access to others will not'. Non-initialized as well as initialized-but-not-const globals are always accessed at their link location before and after relocation, and thus will work only if you're running the image at its linked location.
Again, please keep in mind that (1) this depends on the linker script, and (2) that before relocation to RAM _all_ access to global variables is extremely limited as we have only a read-only data segment and no BSS segment at all.
I do have 2 in mind -- I thought that was clear from the rest of my post. For 1, well, yes that depends on the linker script, but here I am talking about only one linker script, that of the arm926ejs. I see an issue there with relocating while init_sequence is not const, but maybe it does not occur for other CPUs than ARM, and maybe it does not even occur on ARMs for compilers other than the one provided in ELDK42 -- that's the one I'm using. But I do think that it does happen with all gcc versions, because this is not a compiler bug, this is an overlook in board.c -- fundamentally, init_sequence *is* a const and should be qualified as such.
This means that non-const data obviously can't work when the image is linked to FLASH; and they can even wreak havoc if the image linked for RAM and relocated near, but not exactly at, its linked location. The
I don't understand what you mean. Are you aware of the restrictions of the execution environment before relocation to RAM?
I am. More precisely, I am more aware if it than some code in u-boot is. :)
fact that it did not break so far in u-boot without reloc (and yes, several drivers do access globals during in-FLASH board init) is due to the fact that DRAM is already initialized when drivers access these globals at their linked location; this breaks when the image is linked for a location in FLASH.
If any drivers do such things, and if these drivers are used before relocation to RAM, these are serious bugs that must be fixed.
Uhm... That's what I am implying here, and what I explicitely offer solutions for further in my post.
If you are aware of such bugs please post this information, so people can start working on fixes.
I will certainly.
Of course solving the init data issue (by making them const) will not solve the issue of rw data. For this one I see two solutions:
- forbid using such data in drivers during _f phase if that is
This is, and has always been, the case.
Then in at least two cases it was missed by reviews. See below (*).
possible. For instance, in the timer.c driver of orion5x, the timer_init code accesses two writable variables because it wants to have a first reference for rollover detection; this can obviously be postponed to the _r init phase.
Hm... I don;t see global variables being used in timer_init() in "arch/arm/cpu/arm926ejs/orion5x/timer.c" - which exact code are you referring to?
(*)
timer_init() ends up calling reset_timer_masked(), which writes into static variables timestamp and lastdec.
The second case where it was missed is in the kirkwood timer, which is quite logical as the orion5x code is based on the kirkwood one.
- in case where the _f phase *has* to store data in globals, then this
data should go to the globals space allocated below the stack, where gd also resides, and be later copied to usual globals if reqired.
It seems you really minunderstand the excution environment before relocation. Ther eis also no steck there, and of course no "globals space allocated below the stack", because we don't even have the RAM initialized yet.
I stand corrected--Indeed, we don't have RAM inittialized at this point. This makes my second suggestion inapplicable... And the first one, as you noted, is already a requirement.
BTW, the comments in board.c say that the _f init functions receive a pointer to gd; actually they dont, they're int (*) (void). Were the comments always out-of-sync with the code, or was there a removal of the gd argument for some reason?
Please read the code, and the README. Please pay special attention to section "Initial Stack, Global Data:".
In short: the pointer to the global data is passed in a register, which we reserve for this purpose.
This is true, and reinforces my point that the comment in board.c is out of sync with what is really going on, as it explicitely says the pointer is passed as an argument to the init functions (lines 241 and 242 in 'next') whereas it is not.
Best regards,
Wolfgang Denk
I still think that with -fPIC u-boot should be able to run until at least the end of board_init_f from anywhere in FLASH. And if all it takes to get there is making sure that board_init_f-called code uses only consts, then I think it would be worth asking board maintainers to go check this while they're testing Heiko's relocation patches.
Amicalement,

Dear Albert ARIBAUD,
In message 4C927C0C.1080007@free.fr you wrote:
I did not write 'the goal of using fPIC in u-boot', I wrote 'the goal of fPIC', and as such, I think I read it right. I do agree though (and I think I made it clear further in my post) that u-boot images are linked for a fixed location and that their entry point is at the first address of this location.
Wrong. Their entry point is whereever the reset vector happens to be, and this is usually NOT at offset 0 into the text segment.
However, I disagree with the fact that u-boot's link address would always be the reset vector location. This is not generally true, and this is especially not true for the orion5x, which is linked for its RAM location, not for its FLASH location, and for which the image is flashed
You are probably looking at old, obsolete code. Please check out the "next" branch, which has Heiko's ARM rework patches applied.
[I'm giving the generic, architecture independent view of U-Boot here. Actual implementations for some processors may behave differently, but this is nothing you should build on.]
[Except when working with these processors. :) ]
Not even then, because things might change under your feet - as just happened.
As for what I am trying to do: ironically, I am trying to find a way that the entry point of u-boot be at the reset vector location, just as it should.
There it is.
As for you suggestion of arranging the code so that the entry point ends up at 0xffff0000, it requires much more than a little tuning of the linker script. This tuning is actually a long and suboptimal process akin to the bin packing problem, where you'd have to split sections, notably .text, and then shuffle sections in memory areas while hoping that no section is going to grow bigger than the memory region it was assigned to. And then, change one thing in the config, and you may need to solve the problem yet again.
If you can live with the wasted 64 kB of empty space "behind" the reset vector, then it is not worse than counting the number of flash sectors needed for the image (which you have to do anyway to determine the TEXT_BASE). And moving a number of static, never-changing objects into that free area is no real rocket science either. Say, half an hour of efforts including basic testing.
Hm... I don;t see global variables being used in timer_init() in "arch/arm/cpu/arm926ejs/orion5x/timer.c" - which exact code are you referring to?
(*)
timer_init() ends up calling reset_timer_masked(), which writes into static variables timestamp and lastdec.
This is indeed broken and needs to be fixed.
This is true, and reinforces my point that the comment in board.c is out of sync with what is really going on, as it explicitely says the pointer is passed as an argument to the init functions (lines 241 and 242 in 'next') whereas it is not.
Patch welcome...
I still think that with -fPIC u-boot should be able to run until at least the end of board_init_f from anywhere in FLASH. And if all it takes to get there is making sure that board_init_f-called code uses only consts, then I think it would be worth asking board maintainers to go check this while they're testing Heiko's relocation patches.
We use PIC to make U-Boot relocatable to any RAM address, so we can auto-adjust to actual RAM sizes and always copy U-Boot to the (dynamically determined) end of RAM location. When running from flash, U-Boot is linked to a fixed address map, which includes the (fix) reset vector as single entry point.
Best regards,
Wolfgang Denk

Le 16/09/2010 23:26, Wolfgang Denk a écrit :
Dear Albert ARIBAUD,
In message4C927C0C.1080007@free.fr you wrote:
I did not write 'the goal of using fPIC in u-boot', I wrote 'the goal of fPIC', and as such, I think I read it right. I do agree though (and I think I made it clear further in my post) that u-boot images are linked for a fixed location and that their entry point is at the first address of this location.
Wrong. Their entry point is whereever the reset vector happens to be, and this is usually NOT at offset 0 into the text segment.
They key here is 'usually'; see the orion5x case for instance.
However, I disagree with the fact that u-boot's link address would always be the reset vector location. This is not generally true, and this is especially not true for the orion5x, which is linked for its RAM location, not for its FLASH location, and for which the image is flashed
You are probably looking at old, obsolete code. Please check out the "next" branch, which has Heiko's ARM rework patches applied.
I am looking at code which was in effect until Heiko's patches; this is barely 'old, obsolete code', and I am precisely discussing the fact that Heiko's patches break building this code for orion5x, and require replacing a simple process with quite a complicated one.
[I'm giving the generic, architecture independent view of U-Boot here. Actual implementations for some processors may behave differently, but this is nothing you should build on.]
[Except when working with these processors. :) ]
Not even then, because things might change under your feet - as just happened.
Things do change indeed, hence my attempt à 1) making sure I detect the change, 2) design things so that they are as resilient to change as possible. One example of such a resilience is making sure the u-boot code designed to run in FLASH can run *anywhere* in FLASH.
As for what I am trying to do: ironically, I am trying to find a way that the entry point of u-boot be at the reset vector location, just as it should.
There it is.
Yes. And you are opposing this, which I do not understand since I'm trying to make this SoC/board perform exactly as you specify while maintaining balance with the hardware's constraints.
As for you suggestion of arranging the code so that the entry point ends up at 0xffff0000, it requires much more than a little tuning of the linker script. This tuning is actually a long and suboptimal process akin to the bin packing problem, where you'd have to split sections, notably .text, and then shuffle sections in memory areas while hoping that no section is going to grow bigger than the memory region it was assigned to. And then, change one thing in the config, and you may need to solve the problem yet again.
If you can live with the wasted 64 kB of empty space "behind" the reset vector, then it is not worse than counting the number of flash sectors needed for the image (which you have to do anyway to determine the TEXT_BASE). And moving a number of static, never-changing objects into that free area is no real rocket science either. Say, half an hour of efforts including basic testing.
Precisely, I do not want to live with wasting 64 out of 512 KB of FLASH.
Regarding counting the flash sectors for mapping u-boot to flash to determine TEXT_BASE, I never had to, thanks to u-boot being (albeit accidentally) able to run from anywhere in FLASH (I can't help seeing irony in the fact that this ability was broken by adding a flag which is supposed to allow running from anywhere).
As for the half-hour of effort, the half-hour part is an assumption which would need supporting, and even if it is only half an hour, it is half an hours for each person configuring u-boot for arm; a burden that I am not willing to inflict on people who want to use u-boot on arm926ejs if I know a way to avoid it, and I know one which indeed requires a bit more effort but for me only, and will be just as (in)sensitive to things moving under feet.
Hm... I don;t see global variables being used in timer_init() in "arch/arm/cpu/arm926ejs/orion5x/timer.c" - which exact code are you referring to?
(*)
timer_init() ends up calling reset_timer_masked(), which writes into static variables timestamp and lastdec.
This is indeed broken and needs to be fixed.
This is true, and reinforces my point that the comment in board.c is out of sync with what is really going on, as it explicitely says the pointer is passed as an argument to the init functions (lines 241 and 242 in 'next') whereas it is not.
Patch welcome...
Patches for both timer and board.c coming in soon. :)
I still think that with -fPIC u-boot should be able to run until at least the end of board_init_f from anywhere in FLASH. And if all it takes to get there is making sure that board_init_f-called code uses only consts, then I think it would be worth asking board maintainers to go check this while they're testing Heiko's relocation patches.
We use PIC to make U-Boot relocatable to any RAM address, so we can auto-adjust to actual RAM sizes and always copy U-Boot to the (dynamically determined) end of RAM location. When running from flash, U-Boot is linked to a fixed address map, which includes the (fix) reset vector as single entry point.
This statement does not contradict the proposal that U-boot, despite being linked for some address in FLASH, should be able to run, from _start to relocation, at any FLASH location at least for architectures, CPUs, SoCs or boards which trivially allow this. I do believe this requirement is both reasonable and useful.
Anyway: there is a bottom line on which I think we agree now:
1) init_sequence is a constant array and should thus be qualified 'const';
2) any data accessed between _start and relocation should be const as well.
Since enforcing these two constaints will fix the problem I have with (wrongly) running u-boot from any FLASH location, I'll happily cease arguing for it if so ordered; but as long as I can, I'll continue making sure changes made to u-boot avoid breaking this if they can.
(and I'll be sure to address the requirement that u-boot be linked for an address in flash which contains its entry point in my upcoming patch for using the last 64 KB of flash on orion5x)
Amicalement,

Dear Albert ARIBAUD,
In message 4C9307C4.40208@free.fr you wrote:
Things do change indeed, hence my attempt à 1) making sure I detect the change, 2) design things so that they are as resilient to change as possible. One example of such a resilience is making sure the u-boot code designed to run in FLASH can run *anywhere* in FLASH.
As for 1), just follow the postings on this mailing list.
As for 2), you need to implement the following features (none of which are supported yet, AFAICT):
[This is based on the assumption that you want to use the very same binary image fom different addresses]
- The code must be completely position-independent. - You need a way to detect if you are running on a virgin CPU fresh out of reset or on a pre-initialized system. - You need to isolate parts in the initialization sequence that must not be repeated. - You must make sure such steps are not re-run on a pre-initialized system. - You need to implement a way with the different behaviour in terms of resources.
As for what I am trying to do: ironically, I am trying to find a way that the entry point of u-boot be at the reset vector location, just as it should.
There it is.
Yes. And you are opposing this, which I do not understand since I'm trying to make this SoC/board perform exactly as you specify while maintaining balance with the hardware's constraints.
I do not understand what you mean. Unless loaded by some other mechanism (like when booting from NAND flash etc.), the entry point to U-Boot *is* of course at the reset vector location - or how would the CPU be able to execute the code?
If you can live with the wasted 64 kB of empty space "behind" the reset vector, then it is not worse than counting the number of flash sectors needed for the image (which you have to do anyway to determine the TEXT_BASE). And moving a number of static, never-changing objects into that free area is no real rocket science either. Say, half an hour of efforts including basic testing.
Precisely, I do not want to live with wasting 64 out of 512 KB of FLASH.
OK, se put a few objects in that "hole" to fill it.
Regarding counting the flash sectors for mapping u-boot to flash to determine TEXT_BASE, I never had to, thanks to u-boot being (albeit accidentally) able to run from anywhere in FLASH (I can't help seeing irony in the fact that this ability was broken by adding a flag which is supposed to allow running from anywhere).
I lost you. If you put the U-Boot image at an arbitrary location in flash, the CPU will not start it because the CPU begins execution at the reset vector.
As for the half-hour of effort, the half-hour part is an assumption which would need supporting, and even if it is only half an hour, it is half an hours for each person configuring u-boot for arm; a burden that
No. Only for those who have a system with such a reset vector location, and I seriously doubt that any of these changes to the linker script have to be board specific. That means you just need to perform this task once to improve the platform-specific linker script, and it will automatically work for all other users of that architecture as well.
This statement does not contradict the proposal that U-boot, despite being linked for some address in FLASH, should be able to run, from _start to relocation, at any FLASH location at least for architectures, CPUs, SoCs or boards which trivially allow this. I do believe this requirement is both reasonable and useful.
If you know how to implement this in a clean way, then please go forward and do it. Patches are welcome. All I can say is that I don't know how to do that, but then, I'm not an ARM expert. Eventually it might be easier on ARM than on PowerPC, where we don't have this feature yet either.
Anyway: there is a bottom line on which I think we agree now:
init_sequence is a constant array and should thus be qualified 'const';
any data accessed between _start and relocation should be const as well.
I think you mean the right thing, but the wording is wrong again.
You can fully access (read and write) data in the special "global data" or "initial data" structure. You can perform read-accesses to any data in the text and/or data segments. You cannot write to data in the the text and/or data segments. You must not attempt to access any data in the bss segment because this does not even exist, so you're accessing random addresses.
Best regards,
Wolfgang Denk

Le 17/09/2010 13:05, Wolfgang Denk a écrit :
Dear Albert ARIBAUD,
In message4C9307C4.40208@free.fr you wrote:
Things do change indeed, hence my attempt à 1) making sure I detect the change, 2) design things so that they are as resilient to change as possible. One example of such a resilience is making sure the u-boot code designed to run in FLASH can run *anywhere* in FLASH.
As for 1), just follow the postings on this mailing list.
Check. :)
As for 2), you need to implement the following features (none of which are supported yet, AFAICT):
[This is based on the assumption that you want to use the very same binary image fom different addresses]
- The code must be completely position-independent.
This is indeed what I am trying to achieve by suggesting qualifying const init_sequence and any other constant data used by u-boot while executing from FLASH.
- You need a way to detect if you are running on a virgin CPU fresh out of reset or on a pre-initialized system.
- You need to isolate parts in the initialization sequence that must not be repeated.
- You must make sure such steps are not re-run on a pre-initialized system.
This is not required per se to 'start from any location'. It is required to 'start in any state', which is another requirement -- also commandable since it increases resilience to varying conditions. I think the 'start from anywhere' requirement can be fulfilled without fulfilling (yet) the 'start in any state' one.
- You need to implement a way with the different behaviour in terms of resources.
This requirement sounds very general; can you be more precise on it?
As for what I am trying to do: ironically, I am trying to find a way that the entry point of u-boot be at the reset vector location, just as it should.
There it is.
Yes. And you are opposing this, which I do not understand since I'm trying to make this SoC/board perform exactly as you specify while maintaining balance with the hardware's constraints.
I do not understand what you mean. Unless loaded by some other mechanism (like when booting from NAND flash etc.), the entry point to U-Boot *is* of course at the reset vector location - or how would the CPU be able to execute the code?
Yes, u-boot needs to be stored in FLASH so that at execution time the _start symbol is mapped at the physical location of the reset vector.
But no, u-boot does not necessarily need to be linked so that the _start symbol maps at the vector reset location; not, at least, if the startup code is position-independent.
Now, for arm926ejs, it so happens that prior to Heiko's relocation patches, u-boot's startup code *was* position-independent, and is not any more, but that making init_sequence (and other data read during startup) onst makes it p-i again.
If you can live with the wasted 64 kB of empty space "behind" the reset vector, then it is not worse than counting the number of flash sectors needed for the image (which you have to do anyway to determine the TEXT_BASE). And moving a number of static, never-changing objects into that free area is no real rocket science either. Say, half an hour of efforts including basic testing.
Precisely, I do not want to live with wasting 64 out of 512 KB of FLASH.
OK, se put a few objects in that "hole" to fill it.
This is a bad approach, as I explain below.
Regarding counting the flash sectors for mapping u-boot to flash to determine TEXT_BASE, I never had to, thanks to u-boot being (albeit accidentally) able to run from anywhere in FLASH (I can't help seeing irony in the fact that this ability was broken by adding a flag which is supposed to allow running from anywhere).
I lost you. If you put the U-Boot image at an arbitrary location in flash, the CPU will not start it because the CPU begins execution at the reset vector.
You're mistaking "putting the image anywhere in FLASH" and "putting _start anywhere in FLASH".
As for the half-hour of effort, the half-hour part is an assumption which would need supporting, and even if it is only half an hour, it is half an hours for each person configuring u-boot for arm; a burden that
No. Only for those who have a system with such a reset vector location,
That is, all people using orion5x for instance.
and I seriously doubt that any of these changes to the linker script have to be board specific.
I did not say board-specific, I said config-specific.
That means you just need to perform this task once to improve the platform-specific linker script, and it will automatically work for all other users of that architecture as well.
Only for a given u-boot configuration. Change it, and that changes the image content, thus the mapping, and you've got to fix _start again.
This statement does not contradict the proposal that U-boot, despite being linked for some address in FLASH, should be able to run, from _start to relocation, at any FLASH location at least for architectures, CPUs, SoCs or boards which trivially allow this. I do believe this requirement is both reasonable and useful.
If you know how to implement this in a clean way, then please go forward and do it. Patches are welcome. All I can say is that I don't know how to do that, but then, I'm not an ARM expert. Eventually it might be easier on ARM than on PowerPC, where we don't have this feature yet either.
I do know how to implement this indeed -- I actually have a working (and thoroughly tested) implementation, but valid for the master branch, without Heiko's patches; I am working on making it work with Heiko's patches right now. I can send a patch set based on master to the list as an RFC.
Anyway: there is a bottom line on which I think we agree now:
init_sequence is a constant array and should thus be qualified 'const';
any data accessed between _start and relocation should be const as well.
I think you mean the right thing, but the wording is wrong again.
You can fully access (read and write) data in the special "global data" or "initial data" structure.
In that respect I may indeed have expressed myself inadequately. When I said that a driver's _f init function could pass data via 'globals space allocated below the stack, I should have said 'above' -- but I had clearly expressed that I was talking about the memory area where gd lives.
You can perform read-accesses to any data in the text and/or data segments. You cannot write to data in the the text and/or data segments. You must not attempt to access any data in the bss segment because this does not even exist, so you're accessing random addresses.
I think none of this contradicts either of points 1) and 2) above. Or does it?
Best regards,
Wolfgang Denk
Amicalement,

Dear Albert ARIBAUD,
In message 4C9365E7.50505@free.fr you wrote:
- You need a way to detect if you are running on a virgin CPU fresh out of reset or on a pre-initialized system.
- You need to isolate parts in the initialization sequence that must not be repeated.
- You must make sure such steps are not re-run on a pre-initialized system.
This is not required per se to 'start from any location'. It is required to 'start in any state', which is another requirement -- also
"start in any state" is only possible by going through the hardware reset. There are messed up situations where you cannot recover the processor any more by software.
You probably mean "virgin state after reset" versus "some other, but sane state, for example while running U-Boot". You cannot separate these. If you want to start from another location, you must run some other code before that (as the CPU will always start from the boot vector only), so your system state has been changed.
commandable since it increases resilience to varying conditions. I think the 'start from anywhere' requirement can be fulfilled without fulfilling (yet) the 'start in any state' one.
But not without being able to "start in another, non-virgin state".
- You need to implement a way with the different behaviour in terms of resources.
This requirement sounds very general; can you be more precise on it?
After reset you have no RAM, no stack, no BSS, no writable data segment, etc. etc. When starting from some other code, conditions may be different.
Now, for arm926ejs, it so happens that prior to Heiko's relocation patches, u-boot's startup code *was* position-independent, and is not any more, but that making init_sequence (and other data read during startup) onst makes it p-i again.
OK.
I lost you. If you put the U-Boot image at an arbitrary location in flash, the CPU will not start it because the CPU begins execution at the reset vector.
You're mistaking "putting the image anywhere in FLASH" and "putting _start anywhere in FLASH".
_start is integral part of the U-Boot image...
As for the half-hour of effort, the half-hour part is an assumption which would need supporting, and even if it is only half an hour, it is half an hours for each person configuring u-boot for arm; a burden that
No. Only for those who have a system with such a reset vector location,
That is, all people using orion5x for instance.
and I seriously doubt that any of these changes to the linker script have to be board specific.
I did not say board-specific, I said config-specific.
It does not depend on board configuration or such. It depends only on your system's memory map (location of the reset vector), and this is constant - for example - for all orion5x boards.
Only for a given u-boot configuration. Change it, and that changes the image content, thus the mapping, and you've got to fix _start again.
Why should I? Did you not state that the reset vector is at a fixed location? Then we can use constant data (comon to all board configurations) to fill the gap between there and end of physical memory space.
Best regards,
Wolfgang Denk

Le 17/09/2010 16:52, Wolfgang Denk a écrit :
Dear Albert ARIBAUD,
In message4C9365E7.50505@free.fr you wrote:
- You need a way to detect if you are running on a virgin CPU fresh out of reset or on a pre-initialized system.
- You need to isolate parts in the initialization sequence that must not be repeated.
- You must make sure such steps are not re-run on a pre-initialized system.
This is not required per se to 'start from any location'. It is required to 'start in any state', which is another requirement -- also
"start in any state" is only possible by going through the hardware reset.
Depends on the processor I guess; but still, my point is that "start at any location" does not require that you detect whether you are fresh out of reset or not.
There are messed up situations where you cannot recover the processor any more by software.
Possibly. So what?
You probably mean "virgin state after reset" versus "some other, but sane state, for example while running U-Boot". You cannot separate these.
Yes, I mean start in any sane state, and I think this is a different problem that "start from any location".
If you want to start from another location, you must run some other code before that (as the CPU will always start from the boot vector only), so your system state has been changed.
On ARM, the other code could be a single branch instruction, in which case for all practical purposes the only part of the state that would changed is the pc, which is already prone to changing a lot.
commandable since it increases resilience to varying conditions. I think the 'start from anywhere' requirement can be fulfilled without fulfilling (yet) the 'start in any state' one.
But not without being able to "start in another, non-virgin state".
Maybe on some architectures this other state is considerably different to the point that u-boot could not start properly; on arm926ejs (and, I suspect, on other ARMs as well) the 'non-virginity' can be limited to "having done some reads, writes and branches" without preventing u-boot from starting using exactly the same code as it would if executed directly on reset. That's tested, and actually used in production on several arm926ejs based boards.
- You need to implement a way with the different behaviour in terms of resources.
This requirement sounds very general; can you be more precise on it?
After reset you have no RAM, no stack, no BSS, no writable data segment, etc. etc. When starting from some other code, conditions may be different.
On orion5x the DRAM controller can be fully reinitialized, and I suspect it is not the only one which can do this.
Now, for arm926ejs, it so happens that prior to Heiko's relocation patches, u-boot's startup code *was* position-independent, and is not any more, but that making init_sequence (and other data read during startup) onst makes it p-i again.
OK.
I lost you. If you put the U-Boot image at an arbitrary location in flash, the CPU will not start it because the CPU begins execution at the reset vector.
You're mistaking "putting the image anywhere in FLASH" and "putting _start anywhere in FLASH".
_start is integral part of the U-Boot image...
I did not sayt it wasn't -- but this point shall be better understood when I publish my patch above Heiko's code, with consts added where due.
As for the half-hour of effort, the half-hour part is an assumption which would need supporting, and even if it is only half an hour, it is half an hours for each person configuring u-boot for arm; a burden that
No. Only for those who have a system with such a reset vector location,
That is, all people using orion5x for instance.
and I seriously doubt that any of these changes to the linker script have to be board specific.
I did not say board-specific, I said config-specific.
It does not depend on board configuration or such. It depends only on your system's memory map (location of the reset vector), and this is constant - for example - for all orion5x boards.
Reminder: here we're talking about fitting a >64 KB u-boot in flash, with _start at the reset vector (0xffff0000 on orion5x), without wasting the space above the reset vector (64 KB on orion5x) and with minimal waste in the rest of the mapping.
You suggested tweaking the linker file to manually place the _start symbol at the reset location, and then bin-pack the rest of the code -- some of which will have to go above _start, some below. This can only be achieved by defining 'MEMORY' regions in the linker file, and then you have to decide what sections go in the top region with the start.o .text section, and define another region big enough for what's left. And then, if you add or remove a configuration option, you section sizes will either grow or shrink; you risk a 'region full' link failure or a hole growing in the mapping, so you have to do it all over again.
This is why I say that the proposed solution of manually tweaking the linker file is sensitive to configuration changes.
Only for a given u-boot configuration. Change it, and that changes the image content, thus the mapping, and you've got to fix _start again.
Why should I?
Your change may overfill one of the 'MEMORY' regions that would have to be defined to get _start mapped to the reset vector location. Personally, I hate it when I enable some configuration option and it results in a link-time mapping error.
Did you not state that the reset vector is at a fixed location? Then we can use constant data (comon to all board configurations) to fill the gap between there and end of physical memory space.
That will not fill it properly and consistently unless that constant data is 1) really constant across all configuration option choices for all boards and 2) nicely filling the gap up to 64 KB.
Best regards,
Wolfgang Denk
As I said, I have a solution for my problem which puts _start at the reset vector location without changing the linker file at all, and with little, contained and controlled changes to the start.S file. I will post this as a [PATCH][NEXT] ([RFC] also if you will), clearly exposing the issue it addresses and the solution it uses, and we can discuss its merit then.
Amicalement,

Dear Albert ARIBAUD,
In message 4C9399A7.5020006@free.fr you wrote:
Depends on the processor I guess; but still, my point is that "start at any location" does not require that you detect whether you are fresh out of reset or not.
OK. I've repeated that often enough now, I will not iterate over this any longer.
Reminder: here we're talking about fitting a >64 KB u-boot in flash, with _start at the reset vector (0xffff0000 on orion5x), without wasting the space above the reset vector (64 KB on orion5x) and with minimal waste in the rest of the mapping.
We do similar things on several boards to align the environment with special, small flash sectors that happen to lie in the middle of the image.
Your case is the same - you would align the _start such that it is located right in the middle of the image: not on a specific flash sector, but at the reset vector.
You suggested tweaking the linker file to manually place the _start symbol at the reset location, and then bin-pack the rest of the code -- some of which will have to go above _start, some below. This can only be achieved by defining 'MEMORY' regions in the linker file, and then you
This is not needed.
This is why I say that the proposed solution of manually tweaking the linker file is sensitive to configuration changes.
Yes, it is. I do not deny that. But this is not a real problem. If the configuration grows such that you need an additional flash sector, you will have to adjust TEXT_BASE. This does not happen frequently.
Only for a given u-boot configuration. Change it, and that changes the image content, thus the mapping, and you've got to fix _start again.
Why should I?
Your change may overfill one of the 'MEMORY' regions that would have to be defined to get _start mapped to the reset vector location. Personally, I hate it when I enable some configuration option and it results in a link-time mapping error.
The "upper part", for reset vector to end of address space, would never change.
location? Then we can use constant data (comon to all board configurations) to fill the gap between there and end of physical memory space.
That will not fill it properly and consistently unless that constant data is 1) really constant across all configuration option choices for all boards and 2) nicely filling the gap up to 64 KB.
See for example the TQM860L board configuration - it uses an embedded flash sector, with manual tweaking in the linker script.
u-boot.map for this board shows:
... arch/powerpc/lib/cache.o(.text) .text 0x40007c20 0x64 arch/powerpc/lib/cache.o 0x40007c20 flush_cache 0x00008000 . = DEFINED (env_offset)?env_offset:. *fill* 0x40007c84 0x37c 00 common/env_embedded.o(.ppcenv) .ppcenv 0x40008000 0x8000 common/env_embedded.o 0x40008000 environment 0x4000c000 redundand_environment *(.text) .text 0x40010000 0x4 common/env_embedded.o 0x40010000 env_size .text 0x40010004 0x0 lib/libgeneric.a(ctype.o) ...
So we are "wasting" 0x37c = 892 bytes of memory for an unused gap. The last changes where the object placing had to be changed due to code size etc. were commit 32482be6 (Feb 19, 2009), and before that fe57bb19 (Sep 18, 2002). Having to tweak this file every 7 years or so is something I'm considering to be acceptable. YMMV...
As I said, I have a solution for my problem which puts _start at the reset vector location without changing the linker file at all, and with little, contained and controlled changes to the start.S file. I will post this as a [PATCH][NEXT] ([RFC] also if you will), clearly exposing the issue it addresses and the solution it uses, and we can discuss its merit then.
I'm looking forward to seeing your patches.
Best regards,
Wolfgang Denk

Le 17/09/2010 21:04, Wolfgang Denk a écrit :
Dear Albert ARIBAUD,
Reminder: here we're talking about fitting a>64 KB u-boot in flash, with _start at the reset vector (0xffff0000 on orion5x), without wasting the space above the reset vector (64 KB on orion5x) and with minimal waste in the rest of the mapping.
We do similar things on several boards to align the environment with special, small flash sectors that happen to lie in the middle of the image.
Your case is the same - you would align the _start such that it is located right in the middle of the image: not on a specific flash sector, but at the reset vector.
You suggested tweaking the linker file to manually place the _start symbol at the reset location, and then bin-pack the rest of the code -- some of which will have to go above _start, some below. This can only be achieved by defining 'MEMORY' regions in the linker file, and then you
This is not needed.
This is the only way to *ensure* a symbol ends up linked at a given address. Methods based on -- at least the only one that isn't utterly sensitive to any change in the configuration.
This is why I say that the proposed solution of manually tweaking the linker file is sensitive to configuration changes.
Yes, it is. I do not deny that. But this is not a real problem. If the configuration grows such that you need an additional flash sector, you will have to adjust TEXT_BASE. This does not happen frequently.
Only for a given u-boot configuration. Change it, and that changes the image content, thus the mapping, and you've got to fix _start again.
Why should I?
Your change may overfill one of the 'MEMORY' regions that would have to be defined to get _start mapped to the reset vector location. Personally, I hate it when I enable some configuration option and it results in a link-time mapping error.
The "upper part", for reset vector to end of address space, would never change.
This is a bold assumption to make, and hard to prove, I think.
location? Then we can use constant data (comon to all board configurations) to fill the gap between there and end of physical memory space.
That will not fill it properly and consistently unless that constant data is 1) really constant across all configuration option choices for all boards and 2) nicely filling the gap up to 64 KB.
See for example the TQM860L board configuration - it uses an embedded flash sector, with manual tweaking in the linker script.
You mean the one in which the comment about hand-optimizing ends with "XXX FIXME XXX" ? :)
I fail to see that it is an example of setting _start at a specific location within the image: it sets it at the first location of .text always. My problem is being able flash an image bigger than 64 KB while getting _start to end up flashed at 0xffff0000, which means putting _start somewhere in the middle of the .text section (which this ld trick does not help do)... or use the solution I posted (see below).
u-boot.map for this board shows:
... arch/powerpc/lib/cache.o(.text) .text 0x40007c20 0x64 arch/powerpc/lib/cache.o 0x40007c20 flush_cache 0x00008000 . = DEFINED (env_offset)?env_offset:. *fill* 0x40007c84 0x37c 00 common/env_embedded.o(.ppcenv) .ppcenv 0x40008000 0x8000 common/env_embedded.o 0x40008000 environment 0x4000c000 redundand_environment *(.text) .text 0x40010000 0x4 common/env_embedded.o 0x40010000 env_size .text 0x40010004 0x0 lib/libgeneric.a(ctype.o) ...
So we are "wasting" 0x37c = 892 bytes of memory for an unused gap. The last changes where the object placing had to be changed due to code size etc. were commit 32482be6 (Feb 19, 2009), and before that fe57bb19 (Sep 18, 2002). Having to tweak this file every 7 years or so is something I'm considering to be acceptable. YMMV...
This is a simple alignment. I do not need to align code, I need to map *one* symbol, namely _start, at a given location, here 0xffff0000, so that the 64 KB sector which contains start is not wasted and the image resides in as few sectors as possible.
As I said, I have a solution for my problem which puts _start at the reset vector location without changing the linker file at all, and with little, contained and controlled changes to the start.S file. I will post this as a [PATCH][NEXT] ([RFC] also if you will), clearly exposing the issue it addresses and the solution it uses, and we can discuss its merit then.
I'm looking forward to seeing your patches.
I am finishing it for next, but you can already see the version for master I'd posted, and then withdrawn only because I wanted to rewrite it above Heiko's patches. It is at http://www.mail-archive.com/u-boot@lists.denx.de/msg37952.html, and there is a large comment to explain how it works. As indicated, it has been tested for all functional cases.
Note that the new version will slightly differ in the order of the copies, so as to minimize register usage.
Best regards,
Wolfgang Denk
Amicalement,

Dear Albert ARIBAUD,
In message 4C93E978.9010508@free.fr you wrote:
u-boot.map for this board shows:
... arch/powerpc/lib/cache.o(.text) .text 0x40007c20 0x64 arch/powerpc/lib/cache.o 0x40007c20 flush_cache 0x00008000 . = DEFINED (env_offset)?env_offset:. *fill* 0x40007c84 0x37c 00 common/env_embedded.o(.ppcenv) .ppcenv 0x40008000 0x8000 common/env_embedded.o 0x40008000 environment 0x4000c000 redundand_environment *(.text) .text 0x40010000 0x4 common/env_embedded.o 0x40010000 env_size .text 0x40010004 0x0 lib/libgeneric.a(ctype.o) ...
So we are "wasting" 0x37c = 892 bytes of memory for an unused gap. The last changes where the object placing had to be changed due to code size etc. were commit 32482be6 (Feb 19, 2009), and before that fe57bb19 (Sep 18, 2002). Having to tweak this file every 7 years or so is something I'm considering to be acceptable. YMMV...
This is a simple alignment. I do not need to align code, I need to map *one* symbol, namely _start, at a given location, here 0xffff0000, so that the 64 KB sector which contains start is not wasted and the image resides in as few sectors as possible.
And I map *one* symbol, namely environment, at a given location, here 0x40008000.
It seems you are not willing or trying or able to understand. I give up here.
Viele Grüße,
Wolfgang Denk

Le 18/09/2010 00:42, Wolfgang Denk a écrit :
Dear Albert ARIBAUD,
In message4C93E978.9010508@free.fr you wrote:
u-boot.map for this board shows:
... arch/powerpc/lib/cache.o(.text) .text 0x40007c20 0x64 arch/powerpc/lib/cache.o 0x40007c20 flush_cache 0x00008000 . = DEFINED (env_offset)?env_offset:. *fill* 0x40007c84 0x37c 00 common/env_embedded.o(.ppcenv) .ppcenv 0x40008000 0x8000 common/env_embedded.o 0x40008000 environment 0x4000c000 redundand_environment *(.text) .text 0x40010000 0x4 common/env_embedded.o 0x40010000 env_size .text 0x40010004 0x0 lib/libgeneric.a(ctype.o) ...
So we are "wasting" 0x37c = 892 bytes of memory for an unused gap. The last changes where the object placing had to be changed due to code size etc. were commit 32482be6 (Feb 19, 2009), and before that fe57bb19 (Sep 18, 2002). Having to tweak this file every 7 years or so is something I'm considering to be acceptable. YMMV...
This is a simple alignment. I do not need to align code, I need to map *one* symbol, namely _start, at a given location, here 0xffff0000, so that the 64 KB sector which contains start is not wasted and the image resides in as few sectors as possible.
And I map *one* symbol, namely environment, at a given location, here 0x40008000.
It seems you are not willing or trying or able to understand. I give up here.
I *am* willing to understand, and *able* I think too; I believe I never expressed any doubt on your own will or ability to understand, and I would appreciate if you kept your doubts about me to yourself.
I still fail to see a mapping of _start at a given here, at least I fail to see a manual action to get there. Are we both talking about the boards/tqc/tqm8xx/u-boot.lds linker file? If so, then it places _start right at the beginning of the .text section (line 58 of the linker file) -- just like all linker files I saw so far -- and does the alignment trick on the location pointer later, at line 67, which aligns the location of env_embedded, not of _start.
Maybe the intent was to move env_embedded out of the sector where start.o et al. are put; but then, that is not what I am look for. I do not want to isolate _start within a given sector; I want to make sure it gets flashed at a given location, where it cannot end up if it was mapped at the beginning of the iagem, because the image is bigger than the space from the reset vector location to the end of the addressable space.
Viele Grüße,
Wolfgang Denk
Amicalement,
participants (6)
-
Albert ARIBAUD
-
Alessandro Rubini
-
Graeme Russ
-
Heiko Schocher
-
Wolfgang Denk
-
wolfgang@leila.ping.de