Commit f1d2b313c9eb6808d30c16a9eb5251240452a56c

Authored by Heiko Schocher
Committed by Wolfgang Denk
1 parent 4fff329df2

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

Portions of this work were supported by funding from
the CE Linux Forum.

Signed-off-by: Heiko Schocher <hs@denx.de>

Fix boot from NAND for non-ARM systems
Signed-off-by: Wolfgang Denk <wd@denx.de>

Showing 13 changed files with 910 additions and 8 deletions Side-by-side Diff

... ... @@ -33,6 +33,14 @@
33 33 endif
34 34 endif
35 35  
  36 +ifndef CONFIG_SYS_ARM_WITHOUT_RELOC
  37 +# needed for relocation
  38 +PLATFORM_RELFLAGS += -fPIC
  39 +endif
  40 +
  41 +ifdef CONFIG_SYS_ARM_WITHOUT_RELOC
  42 +PLATFORM_CPPFLAGS += -DCONFIG_SYS_ARM_WITHOUT_RELOC
  43 +endif
36 44 PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
37 45  
38 46 # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
arch/arm/include/asm/config.h
... ... @@ -21,8 +21,9 @@
21 21 #ifndef _ASM_CONFIG_H_
22 22 #define _ASM_CONFIG_H_
23 23  
  24 +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
24 25 /* Relocation to SDRAM works on all ARM boards */
25 26 #define CONFIG_RELOC_FIXUP_WORKS
26   -
  27 +#endif
27 28 #endif
arch/arm/include/asm/global_data.h
... ... @@ -47,6 +47,17 @@
47 47 #ifdef CONFIG_FSL_ESDHC
48 48 unsigned long sdhc_clk;
49 49 #endif
  50 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  51 + unsigned long relocaddr; /* Start address of U-Boot in RAM */
  52 + phys_size_t ram_size; /* RAM size */
  53 + unsigned long mon_len; /* monitor len */
  54 + unsigned long irq_sp; /* irq stack pointer */
  55 + unsigned long start_addr_sp; /* start_addr_stackpointer */
  56 + unsigned long reloc_off;
  57 +#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))
  58 + unsigned long tlb_addr;
  59 +#endif
  60 +#endif
50 61 void **jt; /* jump table */
51 62 char env_buf[32]; /* buffer for getenv() before reloc. */
52 63 } gd_t;
arch/arm/include/asm/u-boot-arm.h
... ... @@ -30,11 +30,20 @@
30 30 #define _U_BOOT_ARM_H_ 1
31 31  
32 32 /* for the following variables, see start.S */
33   -extern ulong _armboot_start; /* code start */
34 33 extern ulong _bss_start; /* code + data end == BSS start */
35 34 extern ulong _bss_end; /* BSS end */
36 35 extern ulong IRQ_STACK_START; /* top of IRQ stack */
37 36 extern ulong FIQ_STACK_START; /* top of FIQ stack */
  37 +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  38 +extern ulong _armboot_start; /* code start */
  39 +#else
  40 +extern ulong _TEXT_BASE; /* code start */
  41 +extern ulong _datarel_start;
  42 +extern ulong _datarelrolocal_start;
  43 +extern ulong _datarellocal_start;
  44 +extern ulong _datarelro_start;
  45 +extern ulong IRQ_STACK_START_IN; /* 8 bytes in IRQ stack */
  46 +#endif
38 47  
39 48 /* cpu/.../cpu.c */
40 49 int cpu_init(void);
... ... @@ -47,6 +56,9 @@
47 56 /* board/.../... */
48 57 int board_init(void);
49 58 int dram_init (void);
  59 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  60 +void dram_init_banksize (void);
  61 +#endif
50 62 void setup_serial_tag (struct tag **params);
51 63 void setup_revision_tag (struct tag **params);
52 64  
arch/arm/lib/board.c
... ... @@ -126,7 +126,12 @@
126 126 {
127 127 char tmp[64]; /* long enough for environment variables */
128 128 int i = getenv_f("baudrate", tmp, sizeof (tmp));
  129 +
  130 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  131 + gd->baudrate = (i > 0)
  132 +#else
129 133 gd->bd->bi_baudrate = gd->baudrate = (i > 0)
  134 +#endif
130 135 ? (int) simple_strtoul (tmp, NULL, 10)
131 136 : CONFIG_BAUDRATE;
132 137  
... ... @@ -137,7 +142,12 @@
137 142 {
138 143 printf ("\n\n%s\n\n", version_string);
139 144 debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
140   - _armboot_start, _bss_start, _bss_end);
  145 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  146 + _TEXT_BASE,
  147 +#else
  148 + _armboot_start,
  149 +#endif
  150 + _bss_start, _bss_end);
141 151 #ifdef CONFIG_MODEM_SUPPORT
142 152 debug ("Modem Support enabled\n");
143 153 #endif
... ... @@ -180,6 +190,7 @@
180 190 return (0);
181 191 }
182 192  
  193 +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
183 194 #ifndef CONFIG_SYS_NO_FLASH
184 195 static void display_flash_config (ulong size)
185 196 {
... ... @@ -187,6 +198,7 @@
187 198 print_size (size, "\n");
188 199 }
189 200 #endif /* CONFIG_SYS_NO_FLASH */
  201 +#endif
190 202  
191 203 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
192 204 static int init_func_i2c (void)
... ... @@ -234,6 +246,7 @@
234 246  
235 247 int print_cpuinfo (void);
236 248  
  249 +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
237 250 init_fnc_t *init_sequence[] = {
238 251 #if defined(CONFIG_ARCH_CPU_INIT)
239 252 arch_cpu_init, /* basic arch cpu dependent setup */
... ... @@ -449,6 +462,459 @@
449 462  
450 463 /* NOTREACHED - no way out of command loop except booting */
451 464 }
  465 +#else
  466 +void __dram_init_banksize(void)
  467 +{
  468 + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
  469 + gd->bd->bi_dram[0].size = gd->ram_size;
  470 +}
  471 +void dram_init_banksize(void)
  472 + __attribute__((weak, alias("__dram_init_banksize")));
  473 +
  474 +init_fnc_t *init_sequence[] = {
  475 +#if defined(CONFIG_ARCH_CPU_INIT)
  476 + arch_cpu_init, /* basic arch cpu dependent setup */
  477 +#endif
  478 +#if defined(CONFIG_BOARD_EARLY_INIT_F)
  479 + board_early_init_f,
  480 +#endif
  481 + timer_init, /* initialize timer */
  482 +#ifdef CONFIG_FSL_ESDHC
  483 + get_clocks,
  484 +#endif
  485 + env_init, /* initialize environment */
  486 + init_baudrate, /* initialze baudrate settings */
  487 + serial_init, /* serial communications setup */
  488 + console_init_f, /* stage 1 init of console */
  489 + display_banner, /* say that we are here */
  490 +#if defined(CONFIG_DISPLAY_CPUINFO)
  491 + print_cpuinfo, /* display cpu info (and speed) */
  492 +#endif
  493 +#if defined(CONFIG_DISPLAY_BOARDINFO)
  494 + checkboard, /* display board info */
  495 +#endif
  496 +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
  497 + init_func_i2c,
  498 +#endif
  499 + dram_init, /* configure available RAM banks */
  500 +#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
  501 + arm_pci_init,
  502 +#endif
  503 + NULL,
  504 +};
  505 +
  506 +void board_init_f (ulong bootflag)
  507 +{
  508 + bd_t *bd;
  509 + init_fnc_t **init_fnc_ptr;
  510 + gd_t *id;
  511 + ulong addr, addr_sp;
  512 +
  513 + /* Pointer is writable since we allocated a register for it */
  514 + gd = (gd_t *) (CONFIG_SYS_INIT_SP_ADDR);
  515 + /* compiler optimization barrier needed for GCC >= 3.4 */
  516 + __asm__ __volatile__("": : :"memory");
  517 +
  518 + memset ((void*)gd, 0, sizeof (gd_t));
  519 +
  520 + gd->mon_len = _bss_end - _TEXT_BASE;
  521 +
  522 + for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
  523 + if ((*init_fnc_ptr)() != 0) {
  524 + hang ();
  525 + }
  526 + }
  527 +
  528 + debug ("monitor len: %08lX\n", gd->mon_len);
  529 + /*
  530 + * Ram is setup, size stored in gd !!
  531 + */
  532 + debug ("ramsize: %08lX\n", gd->ram_size);
  533 +#if defined(CONFIG_SYS_MEM_TOP_HIDE)
  534 + /*
  535 + * Subtract specified amount of memory to hide so that it won't
  536 + * get "touched" at all by U-Boot. By fixing up gd->ram_size
  537 + * the Linux kernel should now get passed the now "corrected"
  538 + * memory size and won't touch it either. This should work
  539 + * for arch/ppc and arch/powerpc. Only Linux board ports in
  540 + * arch/powerpc with bootwrapper support, that recalculate the
  541 + * memory size from the SDRAM controller setup will have to
  542 + * get fixed.
  543 + */
  544 + gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
  545 +#endif
  546 +
  547 + addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
  548 +
  549 +#ifdef CONFIG_LOGBUFFER
  550 +#ifndef CONFIG_ALT_LB_ADDR
  551 + /* reserve kernel log buffer */
  552 + addr -= (LOGBUFF_RESERVE);
  553 + debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
  554 +#endif
  555 +#endif
  556 +
  557 +#ifdef CONFIG_PRAM
  558 + /*
  559 + * reserve protected RAM
  560 + */
  561 + i = getenv_r ("pram", (char *)tmp, sizeof (tmp));
  562 + reg = (i > 0) ? simple_strtoul ((const char *)tmp, NULL, 10) : CONFIG_PRAM;
  563 + addr -= (reg << 10); /* size is in kB */
  564 + debug ("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
  565 +#endif /* CONFIG_PRAM */
  566 +
  567 +#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))
  568 + /* reserve TLB table */
  569 + addr -= (4096 * 4);
  570 +
  571 + /* round down to next 64 kB limit */
  572 + addr &= ~(0x10000 - 1);
  573 +
  574 + gd->tlb_addr = addr;
  575 + debug ("TLB table at: %08lx\n", addr);
  576 +#endif
  577 +
  578 + /* round down to next 4 kB limit */
  579 + addr &= ~(4096 - 1);
  580 + debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
  581 +
  582 +#ifdef CONFIG_VFD
  583 +# ifndef PAGE_SIZE
  584 +# define PAGE_SIZE 4096
  585 +# endif
  586 + /*
  587 + * reserve memory for VFD display (always full pages)
  588 + */
  589 + addr -= vfd_setmem (addr);
  590 + gd->fb_base = addr;
  591 +#endif /* CONFIG_VFD */
  592 +
  593 +#ifdef CONFIG_LCD
  594 + /* reserve memory for LCD display (always full pages) */
  595 + addr = lcd_setmem (addr);
  596 + gd->fb_base = addr;
  597 +#endif /* CONFIG_LCD */
  598 +
  599 + /*
  600 + * reserve memory for U-Boot code, data & bss
  601 + * round down to next 4 kB limit
  602 + */
  603 + addr -= gd->mon_len;
  604 + addr &= ~(4096 - 1);
  605 +
  606 + debug ("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);
  607 +
  608 +#ifndef CONFIG_PRELOADER
  609 + /*
  610 + * reserve memory for malloc() arena
  611 + */
  612 + addr_sp = addr - TOTAL_MALLOC_LEN;
  613 + debug ("Reserving %dk for malloc() at: %08lx\n",
  614 + TOTAL_MALLOC_LEN >> 10, addr_sp);
  615 + /*
  616 + * (permanently) allocate a Board Info struct
  617 + * and a permanent copy of the "global" data
  618 + */
  619 + addr_sp -= sizeof (bd_t);
  620 + bd = (bd_t *) addr_sp;
  621 + gd->bd = bd;
  622 + debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
  623 + sizeof (bd_t), addr_sp);
  624 + addr_sp -= sizeof (gd_t);
  625 + id = (gd_t *) addr_sp;
  626 + debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
  627 + sizeof (gd_t), addr_sp);
  628 +
  629 + /* setup stackpointer for exeptions */
  630 + gd->irq_sp = addr_sp;
  631 +#ifdef CONFIG_USE_IRQ
  632 + addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
  633 + debug ("Reserving %zu Bytes for IRQ stack at: %08lx\n",
  634 + CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
  635 +#endif
  636 + /* leave 3 words for abort-stack */
  637 + addr_sp -= 3;
  638 +
  639 + /* 8-byte alignment for ABI compliance */
  640 + addr_sp &= ~0x07;
  641 +#else
  642 + addr_sp += 128; /* leave 32 words for abort-stack */
  643 + gd->irq_sp = addr_sp;
  644 +#endif
  645 +
  646 + debug ("New Stack Pointer is: %08lx\n", addr_sp);
  647 +
  648 +#ifdef CONFIG_POST
  649 + post_bootmode_init();
  650 + post_run (NULL, POST_ROM | post_bootmode_get(0));
  651 +#endif
  652 +
  653 + gd->bd->bi_baudrate = gd->baudrate;
  654 + /* Ram ist board specific, so move it to board code ... */
  655 + dram_init_banksize();
  656 + display_dram_config(); /* and display it */
  657 +
  658 + gd->relocaddr = addr;
  659 + gd->start_addr_sp = addr_sp;
  660 + gd->reloc_off = addr - _TEXT_BASE;
  661 + debug ("relocation Offset is: %08lx\n", gd->reloc_off);
  662 + memcpy (id, (void *)gd, sizeof (gd_t));
  663 +
  664 + relocate_code (addr_sp, id, addr);
  665 +
  666 + /* NOTREACHED - relocate_code() does not return */
  667 +}
  668 +
  669 +#if !defined(CONFIG_SYS_NO_FLASH)
  670 +static char *failed = "*** failed ***\n";
  671 +#endif
  672 +
  673 +/************************************************************************
  674 + *
  675 + * This is the next part if the initialization sequence: we are now
  676 + * running from RAM and have a "normal" C environment, i. e. global
  677 + * data can be written, BSS has been cleared, the stack size in not
  678 + * that critical any more, etc.
  679 + *
  680 + ************************************************************************
  681 + */
  682 +void board_init_r (gd_t *id, ulong dest_addr)
  683 +{
  684 + char *s;
  685 + bd_t *bd;
  686 + ulong malloc_start;
  687 +#if !defined(CONFIG_SYS_NO_FLASH)
  688 + ulong flash_size;
  689 +#endif
  690 +#if !defined(CONFIG_RELOC_FIXUP_WORKS)
  691 + extern void malloc_bin_reloc (void);
  692 +#if defined(CONFIG_CMD_BMP)
  693 + extern void bmp_reloc(void);
  694 +#endif
  695 +#if defined(CONFIG_CMD_I2C)
  696 + extern void i2c_reloc(void);
  697 +#endif
  698 +#endif
  699 +
  700 + gd = id;
  701 + bd = gd->bd;
  702 +
  703 + gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
  704 +
  705 + monitor_flash_len = _bss_start - _TEXT_BASE;
  706 + debug ("monitor flash len: %08lX\n", monitor_flash_len);
  707 + board_init(); /* Setup chipselects */
  708 +
  709 +#ifdef CONFIG_SERIAL_MULTI
  710 + serial_initialize();
  711 +#endif
  712 +
  713 + debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
  714 +
  715 +#if !defined(CONFIG_RELOC_FIXUP_WORKS)
  716 + /*
  717 + * We have to relocate the command table manually
  718 + */
  719 + fixup_cmdtable(&__u_boot_cmd_start,
  720 + (ulong)(&__u_boot_cmd_end - &__u_boot_cmd_start));
  721 +#if defined(CONFIG_CMD_BMP)
  722 + bmp_reloc();
  723 +#endif
  724 +#if defined(CONFIG_CMD_I2C)
  725 + i2c_reloc();
  726 +#endif
  727 +#endif /* !defined(CONFIG_RELOC_FIXUP_WORKS) */
  728 +
  729 +#ifdef CONFIG_LOGBUFFER
  730 + logbuff_init_ptrs ();
  731 +#endif
  732 +#ifdef CONFIG_POST
  733 + post_output_backlog ();
  734 +#ifndef CONFIG_RELOC_FIXUP_WORKS
  735 + post_reloc ();
  736 +#endif
  737 +#endif
  738 +
  739 + /* The Malloc area is immediately below the monitor copy in DRAM */
  740 + malloc_start = dest_addr - TOTAL_MALLOC_LEN;
  741 + mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
  742 +#if !defined(CONFIG_RELOC_FIXUP_WORKS)
  743 + malloc_bin_reloc ();
  744 +#endif
  745 +
  746 +#if !defined(CONFIG_SYS_NO_FLASH)
  747 + puts ("FLASH: ");
  748 +
  749 + if ((flash_size = flash_init ()) > 0) {
  750 +# ifdef CONFIG_SYS_FLASH_CHECKSUM
  751 + print_size (flash_size, "");
  752 + /*
  753 + * Compute and print flash CRC if flashchecksum is set to 'y'
  754 + *
  755 + * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
  756 + */
  757 + s = getenv ("flashchecksum");
  758 + if (s && (*s == 'y')) {
  759 + printf (" CRC: %08X",
  760 + crc32 (0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size)
  761 + );
  762 + }
  763 + putc ('\n');
  764 +# else /* !CONFIG_SYS_FLASH_CHECKSUM */
  765 + print_size (flash_size, "\n");
  766 +# endif /* CONFIG_SYS_FLASH_CHECKSUM */
  767 + } else {
  768 + puts (failed);
  769 + hang ();
  770 + }
  771 +#endif
  772 +
  773 +#if defined(CONFIG_CMD_NAND)
  774 + puts ("NAND: ");
  775 + nand_init(); /* go init the NAND */
  776 +#endif
  777 +
  778 +#if defined(CONFIG_CMD_ONENAND)
  779 + onenand_init();
  780 +#endif
  781 +
  782 +#ifdef CONFIG_HAS_DATAFLASH
  783 + AT91F_DataflashInit();
  784 + dataflash_print_info();
  785 +#endif
  786 +
  787 + /* initialize environment */
  788 + env_relocate ();
  789 +
  790 +#ifdef CONFIG_VFD
  791 + /* must do this after the framebuffer is allocated */
  792 + drv_vfd_init();
  793 +#endif /* CONFIG_VFD */
  794 +
  795 + /* IP Address */
  796 + gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
  797 +
  798 + stdio_init (); /* get the devices list going. */
  799 +
  800 + jumptable_init ();
  801 +
  802 +#if defined(CONFIG_API)
  803 + /* Initialize API */
  804 + api_init ();
  805 +#endif
  806 +
  807 + console_init_r (); /* fully init console as a device */
  808 +
  809 +#if defined(CONFIG_ARCH_MISC_INIT)
  810 + /* miscellaneous arch dependent initialisations */
  811 + arch_misc_init ();
  812 +#endif
  813 +#if defined(CONFIG_MISC_INIT_R)
  814 + /* miscellaneous platform dependent initialisations */
  815 + misc_init_r ();
  816 +#endif
  817 +
  818 + /* set up exceptions */
  819 + interrupt_init ();
  820 + /* enable exceptions */
  821 + enable_interrupts ();
  822 +
  823 + /* Perform network card initialisation if necessary */
  824 +#ifdef CONFIG_DRIVER_TI_EMAC
  825 + /* XXX: this needs to be moved to board init */
  826 +extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
  827 + if (getenv ("ethaddr")) {
  828 + uchar enetaddr[6];
  829 + eth_getenv_enetaddr("ethaddr", enetaddr);
  830 + davinci_eth_set_mac_addr(enetaddr);
  831 + }
  832 +#endif
  833 +
  834 +#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
  835 + /* XXX: this needs to be moved to board init */
  836 + if (getenv ("ethaddr")) {
  837 + uchar enetaddr[6];
  838 + eth_getenv_enetaddr("ethaddr", enetaddr);
  839 + smc_set_mac_addr(enetaddr);
  840 + }
  841 +#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
  842 +
  843 + /* Initialize from environment */
  844 + if ((s = getenv ("loadaddr")) != NULL) {
  845 + load_addr = simple_strtoul (s, NULL, 16);
  846 + }
  847 +#if defined(CONFIG_CMD_NET)
  848 + if ((s = getenv ("bootfile")) != NULL) {
  849 + copy_filename (BootFile, s, sizeof (BootFile));
  850 + }
  851 +#endif
  852 +
  853 +#ifdef BOARD_LATE_INIT
  854 + board_late_init ();
  855 +#endif
  856 +
  857 +#ifdef CONFIG_GENERIC_MMC
  858 + puts ("MMC: ");
  859 + mmc_initialize (gd->bd);
  860 +#endif
  861 +
  862 +#ifdef CONFIG_BITBANGMII
  863 + bb_miiphy_init();
  864 +#endif
  865 +#if defined(CONFIG_CMD_NET)
  866 +#if defined(CONFIG_NET_MULTI)
  867 + puts ("Net: ");
  868 +#endif
  869 + eth_initialize(gd->bd);
  870 +#if defined(CONFIG_RESET_PHY_R)
  871 + debug ("Reset Ethernet PHY\n");
  872 + reset_phy();
  873 +#endif
  874 +#endif
  875 +
  876 +#ifdef CONFIG_POST
  877 + post_run (NULL, POST_RAM | post_bootmode_get(0));
  878 +#endif
  879 +
  880 +#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
  881 + /*
  882 + * Export available size of memory for Linux,
  883 + * taking into account the protected RAM at top of memory
  884 + */
  885 + {
  886 + ulong pram;
  887 + uchar memsz[32];
  888 +#ifdef CONFIG_PRAM
  889 + char *s;
  890 +
  891 + if ((s = getenv ("pram")) != NULL) {
  892 + pram = simple_strtoul (s, NULL, 10);
  893 + } else {
  894 + pram = CONFIG_PRAM;
  895 + }
  896 +#else
  897 + pram=0;
  898 +#endif
  899 +#ifdef CONFIG_LOGBUFFER
  900 +#ifndef CONFIG_ALT_LB_ADDR
  901 + /* Also take the logbuffer into account (pram is in kB) */
  902 + pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024;
  903 +#endif
  904 +#endif
  905 + sprintf ((char *)memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
  906 + setenv ("mem", (char *)memsz);
  907 + }
  908 +#endif
  909 +
  910 + /* main_loop() can return to retry autoboot, if so just run it again. */
  911 + for (;;) {
  912 + main_loop ();
  913 + }
  914 +
  915 + /* NOTREACHED - no way out of command loop except booting */
  916 +}
  917 +#endif /* defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
452 918  
453 919 void hang (void)
454 920 {
arch/arm/lib/cache-cp15.c
... ... @@ -44,17 +44,44 @@
44 44 asm volatile("" : : : "memory");
45 45 }
46 46  
47   -/* to activate the MMU we need to set up virtual memory: use 1M areas in bss */
  47 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  48 +static inline void dram_bank_mmu_setup(int bank)
  49 +{
  50 + u32 *page_table = (u32 *)gd->tlb_addr;
  51 + bd_t *bd = gd->bd;
  52 + int i;
  53 +
  54 + debug("%s: bank: %d\n", __func__, bank);
  55 + for (i = bd->bi_dram[bank].start >> 20;
  56 + i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >> 20;
  57 + i++) {
  58 + page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP;
  59 + }
  60 +}
  61 +#endif
  62 +
  63 +/* to activate the MMU we need to set up virtual memory: use 1M areas */
48 64 static inline void mmu_setup(void)
49 65 {
  66 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  67 + u32 *page_table = (u32 *)gd->tlb_addr;
  68 +#else
50 69 static u32 __attribute__((aligned(16384))) page_table[4096];
51 70 bd_t *bd = gd->bd;
52   - int i, j;
  71 + int j;
  72 +#endif
  73 + int i;
53 74 u32 reg;
54 75  
55 76 /* Set up an identity-mapping for all 4GB, rw for everyone */
56 77 for (i = 0; i < 4096; i++)
57 78 page_table[i] = i << 20 | (3 << 10) | 0x12;
  79 +
  80 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  81 + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
  82 + dram_bank_mmu_setup(i);
  83 + }
  84 +#else
58 85 /* Then, enable cacheable and bufferable for RAM only */
59 86 for (j = 0; j < CONFIG_NR_DRAM_BANKS; j++) {
60 87 for (i = bd->bi_dram[j].start >> 20;
... ... @@ -63,6 +90,7 @@
63 90 page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP;
64 91 }
65 92 }
  93 +#endif
66 94  
67 95 /* Copy the page table address to cp15 */
68 96 asm volatile("mcr p15, 0, %0, c2, c0, 0"
... ... @@ -74,7 +102,6 @@
74 102 reg = get_cr(); /* get control reg. */
75 103 cp_delay();
76 104 set_cr(reg | CR_M);
77   -
78 105 }
79 106  
80 107 /* cache_bit must be either CR_I or CR_C */
... ... @@ -96,6 +123,10 @@
96 123 uint32_t reg;
97 124  
98 125 if (cache_bit == CR_C) {
  126 + /* if cache isn;t enabled no need to disable */
  127 + reg = get_cr();
  128 + if ((reg & CR_C) != CR_C)
  129 + return;
99 130 /* if disabling data cache, disable mmu too */
100 131 cache_bit |= CR_M;
101 132 flush_cache(0, ~0);
arch/arm/lib/interrupts.c
... ... @@ -38,15 +38,20 @@
38 38 #include <common.h>
39 39 #include <asm/proc-armv/ptrace.h>
40 40  
41   -#ifdef CONFIG_USE_IRQ
42 41 DECLARE_GLOBAL_DATA_PTR;
43 42  
  43 +#ifdef CONFIG_USE_IRQ
44 44 int interrupt_init (void)
45 45 {
46 46 /*
47 47 * setup up stacks if necessary
48 48 */
  49 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  50 + IRQ_STACK_START = gd->irq_sp - 4;
  51 + IRQ_STACK_START_IN = gd->irq_sp + 8;
  52 +#else
49 53 IRQ_STACK_START = _armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4;
  54 +#endif
50 55 FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
51 56  
52 57 return arch_interrupt_init();
... ... @@ -81,6 +86,18 @@
81 86 return (old & 0x80) == 0;
82 87 }
83 88 #else
  89 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  90 +int interrupt_init (void)
  91 +{
  92 + /*
  93 + * setup up stacks if necessary
  94 + */
  95 + IRQ_STACK_START_IN = gd->irq_sp + 8;
  96 +
  97 + return 0;
  98 +}
  99 +#endif
  100 +
84 101 void enable_interrupts (void)
85 102 {
86 103 return;
... ... @@ -343,7 +343,16 @@
343 343 printf ("ip_addr = %pI4\n", &bd->bi_ip_addr);
344 344 #endif
345 345 printf ("baudrate = %d bps\n", bd->bi_baudrate);
346   -
  346 +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  347 +#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))
  348 + print_num ("TLB addr", gd->tlb_addr);
  349 +#endif
  350 + print_num ("relocaddr", gd->relocaddr);
  351 + print_num ("reloc off", gd->reloc_off);
  352 + print_num ("irq_sp", gd->irq_sp); /* irq stack pointer */
  353 + print_num ("sp start ", gd->start_addr_sp);
  354 + print_num ("FB base ", gd->fb_base);
  355 +#endif
347 356 return 0;
348 357 }
349 358  
... ... @@ -137,6 +137,12 @@
137 137 U_BOOT_CMD_MKENT(display, 5, 0, do_bmp_display, "", ""),
138 138 };
139 139  
  140 +#ifndef CONFIG_RELOC_FIXUP_WORKS
  141 +void bmp_reloc(void) {
  142 + fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub));
  143 +}
  144 +#endif
  145 +
140 146 /*
141 147 * Subroutine: do_bmp
142 148 *
... ... @@ -1284,6 +1284,12 @@
1284 1284 U_BOOT_CMD_MKENT(speed, 1, 1, do_i2c_bus_speed, "", ""),
1285 1285 };
1286 1286  
  1287 +#ifndef CONFIG_RELOC_FIXUP_WORKS
  1288 +void i2c_reloc(void) {
  1289 + fixup_cmdtable(cmd_i2c_sub, ARRAY_SIZE(cmd_i2c_sub));
  1290 +}
  1291 +#endif
  1292 +
1287 1293 static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
1288 1294 {
1289 1295 cmd_tbl_t *c;
doc/README.arm-relocation
  1 +To make relocation on arm working, the following changes are done:
  2 +
  3 +Add new compilerflag:
  4 +
  5 +-fPIC
  6 +
  7 + -> compiler generates position independent code
  8 +
  9 +changes in board code:
  10 +
  11 +- dram_init:
  12 + - bd pointer is now at this point not accessible, so only
  13 + detect the real dramsize, and store it in gd->ram_size.
  14 + best detected with get_ram_size();
  15 + ToDo: move there also the dram initialization on boards where
  16 + it is possible.
  17 + - setup the bd_t dram bank info in the new function
  18 + dram_init_banksize().
  19 +
  20 +- board.c code is adapted from ppc code
  21 +
  22 +- undef CONFIG_RELOC_FIXUP_WORKS
  23 +
  24 + -> cmdtabl, and subcommand table must be handled from "hand"
  25 + collected in section "__datarellocal_start".
  26 +
  27 + - How To fixup the sections:
  28 +
  29 + __datarel_start, __datarelrolocal_start, __datarellocal_start and
  30 + __datarelro_start
  31 +
  32 + automatically? Then it should be possible to define again
  33 + CONFIG_RELOC_FIXUP_WORKS
  34 +
  35 +- irq stack setup is now not longer on a fix position, instead it is
  36 + calculated in board_init_f, and stored in gd->irq_sp
  37 +
  38 +-------------------------------------------------------------------------------------
  39 +
  40 +To compile a board without relocation, define CONFIG_SYS_ARM_WITHOUT_RELOC
  41 +This possibility will removed!! So please fix your board to compile without
  42 +CONFIG_SYS_ARM_WITHOUT_RELOC defined!!!
  43 +
  44 +-------------------------------------------------------------------------------------
  45 +
  46 +ToDo:
  47 +
  48 +- fill in bd_t infos (check)
  49 +- adapt all boards
  50 +
  51 +- maybe adapt TEXT_BASE (this must be checked from board maintainers)
  52 + This *must* be done for boards, which boot from NOR flash
  53 +
  54 + on other boards if TEXT_BASE = relocation baseaddr, this saves
  55 + one copying from u-boot code.
  56 +
  57 +- new function dram_init_banksize() is actual board specific. Maybe
  58 + we make a weak default function in arch/arm/lib/board.c ?
  59 +
  60 +-------------------------------------------------------------------------------------
  61 +
  62 +Relocation with NAND_SPL (example for the tx25):
  63 +
  64 +- cpu copies the first page from NAND to 0xbb000000 (IMX_NFC_BASE)
  65 + and start with code execution on this address.
  66 +
  67 +- The First page contains u-boot code from u-boot:nand_spl/nand_boot_fsl_nfc.c
  68 + which inits the dram, cpu registers, reloacte itself to TEXT_BASE and loads
  69 + the "real" u-boot to CONFIG_SYS_NAND_U_BOOT_DST and starts execution
  70 + @CONFIG_SYS_NAND_U_BOOT_START
  71 +
  72 +- This u-boot does no ram int, nor cpu register setup. Just looks
  73 + where it have to relocate and relocate itself to this address.
  74 + If relocate address = TEXT_BASE(not the same, as the TEXT_BASE
  75 + from the nand_spl code), no need to copy, just go on with bss clear
  76 + and jump to board_init_r.
  77 +
  78 +-------------------------------------------------------------------------------------
  79 +
  80 +Relocation:
  81 +How to translate flash addresses in GOT to ram addresses.
  82 +This is automagically done from code, but this example
  83 +shows, how this magic code works ;-)
  84 +(example on the qong board)
  85 +
  86 +Find a variable:
  87 +
  88 +a) search it in System.map
  89 +(for example flash_info)
  90 +
  91 +a005b4c0 B BootpID
  92 +a005b4c4 B BootpTry
  93 +a005b4c8 b slave
  94 +a005b4cc B flash_info
  95 +^^^^^^^^
  96 +a005c908 b saved_sector.4002
  97 +a005c910 b cfi_mtd_info
  98 +a005c9c0 b cfi_mtd_names
  99 +a005c9d0 B mtd_table
  100 +
  101 +---------------------------------------
  102 +
  103 +b) create hexdump from u-boot code:
  104 +
  105 +hexdump -C u-boot > gnlmpfhex
  106 +
  107 +---------------------------------------
  108 +
  109 +c) search the variables address in the hexdump
  110 +
  111 +
  112 +*
  113 +0005fc80 00 00 00 00 00 00 00 00 2c 06 01 a0 18 cd 05 a0 |........,.......|
  114 +0005fc90 9c d4 05 a0 bc b4 05 a0 1c 7f 05 a0 f0 05 01 a0 |................|
  115 +0005fca0 08 5a 04 a0 1c ab 05 a0 ec a4 05 a0 98 c3 01 a0 |.Z..............|
  116 +0005fcb0 a0 d6 05 a0 04 71 05 a0 c0 f9 00 a0 3c cd 05 a0 |.....q......<...|
  117 +0005fcc0 cc b4 05 a0 f0 fa 00 a0 f0 d6 05 a0 10 86 05 a0 |................|
  118 + ^^^^^^^^^^^
  119 +0005fcd0 a4 16 06 a0 dc 64 05 a0 18 86 05 a0 52 48 05 a0 |.....d......RH..|
  120 +0005fce0 c0 86 05 a0 24 6e 02 a0 b4 6c 05 a0 b0 94 01 a0 |....$n...l......|
  121 +0005fcf0 1c 86 05 a0 50 85 05 a0 d4 0c 06 a0 bc 0b 06 a0 |....P...........|
  122 +
  123 +
  124 +-> 0005fcc0
  125 +
  126 +----------------------------------------
  127 +
  128 +d) know we calculate this address in RAM
  129 +
  130 +
  131 + 8ff08000 (new address of code in RAM *1)
  132 +
  133 ++ 0005fcc0
  134 +
  135 +- 00008000 (offset of text *2)
  136 +
  137 +----------
  138 +
  139 + 8ff5fcc0 -> Addr GOT in RAM
  140 +
  141 +*1:
  142 +activate debug and look for the line:
  143 +Now running in RAM - U-Boot at: 8ff08000
  144 + ^^^^^^^^
  145 + new address of u-boot code in RAM
  146 +
  147 +*2:
  148 +Section Headers:
  149 + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
  150 + [ 0] NULL 00000000 000000 000000 00 0 0 0
  151 + [ 1] .text PROGBITS a0000000 008000 04599c 00 AX 0 0 32
  152 + ^^^^^^
  153 + Offset of text
  154 +
  155 +----------------------------------------
  156 +
  157 +e) now we look in 8ff5fcc0 (RAM)
  158 +
  159 +
  160 +QongEVB>md 0x8ff5fcc0
  161 +8ff5fcc0 : a005b4cc a000faf0 a005d6f0 a0058610 ................
  162 + ^^^^^^^^
  163 + Bingo, here we have the old flash address (when relocation
  164 + is working, here is the fixed ram address. see @ f, how
  165 + it gets calculated)
  166 +
  167 +
  168 +----------------------------------------
  169 +
  170 +f) now translate it in the new RAM address
  171 +
  172 + a005b4cc
  173 +
  174 +- a0000000 TextBase
  175 +
  176 ++ 8ff08000 new address of u-boot in ram
  177 +----------
  178 + 8ff634cc
  179 +
  180 +QongEVB>mm 0x8ff5fcc0 0x8ff634cc 1
  181 +QongEVB>md 0x8ff5fcc0
  182 +8ff5fcc0 : 8ff634cc a000faf0 a005d6f0 a0058610 .4..............
  183 +8ff5fcd0 : a00616a4 a00564dc a0058618 a0054852 .....d......RH..
  184 +
  185 +As this must be done for all address in the GOT, the u-boot
  186 +code did this automagically ... :-)
  187 +
  188 +----------------------------------------------
  189 +
  190 +g) check if the new address is really in the bss section:
  191 +
  192 +bss start:
  193 +8ff6054c (8ff08000 + 0005854C monitorlen)
  194 +
  195 +bss end:
  196 +8ff698ac (8ff08000 + 618AC)
  197 +
  198 +8ff634cc is in bss :-)
  199 +
  200 +----------------------------------------------
  201 +
  202 +h) u-boot prints:
  203 +
  204 +important addresses:
  205 +
  206 +U-Boot code: A0000000 -> A005854C BSS: -> A00618AC TextBase 0xa0000000
  207 +Now running in RAM - U-Boot at: 8ff08000 relocBase 0x8ff08000
  208 +
  209 +
  210 +---------
  211 +
  212 +U-Boot 2010.06-rc2-00002-gf8fbb25-dirty (Jun 18 2010 - 17:07:19)
  213 +
  214 +U-Boot code: A0000000 -> A005854C BSS: -> A00618AC
  215 +CPU: Freescale i.MX31 at 398 MHz
  216 +Board: DAVE/DENX Qong
  217 +mon: FFFFFFFF gd->monLen: 000618AC
  218 +Top of RAM usable for U-Boot at: 90000000
  219 +LCD panel info: 640 x 480, 16 bit/pix
  220 +Reserving 600k for LCD Framebuffer at: 8ff6a000
  221 +Reserving 390k for U-Boot at: 8ff08000
  222 +Reserving 1280k for malloc() at: 8fdc8000
  223 +Reserving 28 Bytes for Board Info at: 8fdc7fe4
  224 +Reserving 48 Bytes for Global Data at: 8fdc7fb4
  225 +New Stack Pointer is: 8fdc7fb0
  226 +RAM Configuration:
  227 +Bank #0: 80000000 256 MiB
  228 +mon: 0005854C gd->monLen: 000618AC
  229 +Now running in RAM - U-Boot at: 8ff08000
  230 +
  231 +-------------------------------------------------------------------------------------
  232 +
  233 +Debugging u-boot in RAM:
  234 +(example on the qong board)
  235 +
  236 +a) add in config.mk:
  237 +
  238 +PLATFORM_CPPFLAGS += -DDEBUG
  239 +
  240 +-----------------
  241 +
  242 +b) start debugger
  243 +
  244 +arm-linux-gdb u-boot
  245 +
  246 +[hs@pollux u-boot]$ arm-linux-gdb u-boot
  247 +GNU gdb Red Hat Linux (6.7-2rh)
  248 +Copyright (C) 2007 Free Software Foundation, Inc.
  249 +License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  250 +This is free software: you are free to change and redistribute it.
  251 +There is NO WARRANTY, to the extent permitted by law. Type "show copying"
  252 +and "show warranty" for details.
  253 +This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
  254 +The target architecture is set automatically (currently arm)
  255 +..
  256 +(gdb)
  257 +
  258 +-----------------
  259 +
  260 +c) connect to target
  261 +
  262 +target remote bdi10:2001
  263 +
  264 +(gdb) target remote bdi10:2001
  265 +Remote debugging using bdi10:2001
  266 +0x8ff17f10 in ?? ()
  267 +(gdb)
  268 +
  269 +-----------------
  270 +
  271 +d) discard symbol-file
  272 +
  273 +(gdb) symbol-file
  274 +Discard symbol table from `/home/hs/celf/u-boot/u-boot'? (y or n) y
  275 +No symbol file now.
  276 +(gdb)
  277 +
  278 +-----------------
  279 +
  280 +e) load new symbol table:
  281 +
  282 +(gdb) add-symbol-file u-boot 0x8ff08000
  283 +add symbol table from file "u-boot" at
  284 + .text_addr = 0x8ff08000
  285 +(y or n) y
  286 +Reading symbols from /home/hs/celf/u-boot/u-boot...done.
  287 +(gdb) c
  288 +Continuing.
  289 +^C
  290 +Program received signal SIGSTOP, Stopped (signal).
  291 +0x8ff17f18 in serial_getc () at serial_mxc.c:192
  292 +192 while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY);
  293 +(gdb)
  294 +
  295 +add-symbol-file u-boot 0x8ff08000
  296 + ^^^^^^^^^^
  297 + get this address from u-boot debug printfs
  298 +
  299 +U-Boot 2010.06-rc2-00009-gf77b8b8-dirty (Jun 22 2010 - 09:43:46)
  300 +
  301 +U-Boot code: A0000000 -> A0058BAC BSS: -> A0061F10
  302 +CPU: Freescale i.MX31 at 398 MHz
  303 +Board: DAVE/DENX Qong
  304 +mon: FFFFFFFF gd->monLen: 00061F10
  305 +Top of RAM usable for U-Boot at: 90000000
  306 +LCD panel info: 640 x 480, 16 bit/pix
  307 +Reserving 600k for LCD Framebuffer at: 8ff6a000
  308 +Reserving 391k for U-Boot at: 8ff08000
  309 + ^^^^^^^^
  310 +Reserving 1280k for malloc() at: 8fdc8000
  311 +Reserving 24 Bytes for Board Info at: 8fdc7fe8
  312 +Reserving 52 Bytes for Global Data at: 8fdc7fb4
  313 +New Stack Pointer is: 8fdc7fb0
  314 +RAM Configuration:
  315 +Bank #0: 80000000 256 MiB
  316 +relocation Offset is: eff08000
  317 +mon: 00058BAC gd->monLen: 00061F10
  318 +Now running in RAM - U-Boot at: 8ff08000
  319 + ^^^^^^^^
  320 +
  321 +Now you can use gdb as usual :-)
nand_spl/nand_boot.c
... ... @@ -221,6 +221,13 @@
221 221 return 0;
222 222 }
223 223  
  224 +#if defined(CONFIG_ARM) && !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  225 +void board_init_f (ulong bootflag)
  226 +{
  227 + relocate_code (TEXT_BASE - TOTAL_MALLOC_LEN, NULL, TEXT_BASE);
  228 +}
  229 +#endif
  230 +
224 231 /*
225 232 * The main entry for NAND booting. It's necessary that SDRAM is already
226 233 * configured and available since this code loads the main U-Boot image
nand_spl/nand_boot_fsl_nfc.c
... ... @@ -263,6 +263,13 @@
263 263 return 0;
264 264 }
265 265  
  266 +#if defined(CONFIG_ARM) && !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
  267 +void board_init_f (ulong bootflag)
  268 +{
  269 + relocate_code (TEXT_BASE - TOTAL_MALLOC_LEN, NULL, TEXT_BASE);
  270 +}
  271 +#endif
  272 +
266 273 /*
267 274 * The main entry for NAND booting. It's necessary that SDRAM is already
268 275 * configured and available since this code loads the main U-Boot image