[U-Boot] [PATCH 0/4] Make u-boot true PIC for ppc

This series adds link_off(), a function to calculate the difference between load address and link address.
Using this function it is possible to make u-boot 100% PIC by wrapping global data accesses LINK_OFF() calls. Plenty of examples in the code to show how to use it.
All start.S needs to be updated too and I have done so with mpc83xx.
-DCONFIG_LINK_OFF in your platform config.mk to make use of this function.
Needs the -ffixed-r14 patches I just sent or you can fix the conflicts manually.
Would really appreciate some testing by 83xx owners. Scott?
Jocke
Joakim Tjernlund (4): ppc: Add const void *link_off(const void *addr) Use LINK_OFF to access global data Use LINK_OFF in enviroment too ppc: Make mpc83xx start.S relative.
common/cmd_nvedit.c | 2 + common/console.c | 12 ++++++-- common/env_common.c | 2 +- common/env_flash.c | 65 ++++++++++++++++++++++++---------------- cpu/mpc83xx/cpu.c | 10 +++--- cpu/mpc83xx/cpu_init.c | 38 ++++++++++++----------- cpu/mpc83xx/speed.c | 28 +++++++----------- cpu/mpc83xx/start.S | 35 +++++++++++++++++---- drivers/serial/serial.c | 21 +++++++------ include/common.h | 7 ++++ include/linux/ctype.h | 6 ++-- lib_generic/crc32.c | 7 ++++- lib_generic/ctype.c | 2 +- lib_generic/display_options.c | 5 ++- lib_generic/vsprintf.c | 9 ++++-- lib_ppc/board.c | 5 ++- lib_ppc/reloc.S | 21 +++++++++++++ tools/updater/ctype.c | 2 +- 18 files changed, 177 insertions(+), 100 deletions(-)

Calculates the offset between global data link address and where the data is actually loaded. Add this offset to 'addr' arg and return the result. Useful for true PIC and when relocating code to RAM. --- include/common.h | 7 +++++++ lib_ppc/reloc.S | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/include/common.h b/include/common.h index 7df9afa..b37cb1d 100644 --- a/include/common.h +++ b/include/common.h @@ -108,6 +108,13 @@ typedef volatile unsigned char vu_char; #include <asm/blackfin.h> #endif
+#ifdef CONFIG_LINK_OFF +const void * link_off(const void * addr); +#else +#define link_off(addr) ((const void *) (addr)) +#endif +#define LINK_OFF(x) ((__typeof__(&(x)[0]))link_off(x)) + #include <part.h> #include <flash.h> #include <image.h> diff --git a/lib_ppc/reloc.S b/lib_ppc/reloc.S index 50f9a83..3ec26cc 100644 --- a/lib_ppc/reloc.S +++ b/lib_ppc/reloc.S @@ -47,3 +47,24 @@ trap_reloc: blr .size trap_reloc, .-trap_reloc #endif + +#ifdef CONFIG_LINK_OFF + /* Calculate the offset between global data link address + * and where the data is actually loaded. Add this offset + * to 'addr' arg and return the result. + * Useful for true PIC and when relocating code to RAM */ + .globl link_off + .type link_off, @function +link_off: /* const void * link_off(const void * addr) */ + /* In asm as we cannot use the stack */ + mflr r5 + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr r4 + mtlr r5 + addi r4,r4,12 /* find first .got2 entry */ + lwz r5,0(r4) /* get link address */ + subf r4,r5,r4 /* r4 = r4 - r5 */ + add r3,r3,r4 /* r3 = r4 + r3 */ + blr + .size link_off, .-link_off +#endif

Accessing global data before relocation needs special handling if link address != load address. Use LINK_OFF to calculate the difference. --- common/cmd_nvedit.c | 2 ++ common/console.c | 12 +++++++++--- common/env_common.c | 2 +- cpu/mpc83xx/cpu.c | 10 +++++----- cpu/mpc83xx/cpu_init.c | 38 ++++++++++++++++++++------------------ cpu/mpc83xx/speed.c | 28 +++++++++++----------------- drivers/serial/serial.c | 21 +++++++++++---------- include/linux/ctype.h | 6 +++--- lib_generic/crc32.c | 7 ++++++- lib_generic/ctype.c | 2 +- lib_generic/display_options.c | 5 +++-- lib_generic/vsprintf.c | 9 ++++++--- lib_ppc/board.c | 5 +++-- tools/updater/ctype.c | 2 +- 14 files changed, 82 insertions(+), 67 deletions(-)
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 9f8d531..182c6fe 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -512,6 +512,7 @@ char *getenv (char *name) { int i, nxt;
+ name = LINK_OFF(name); WATCHDOG_RESET();
for (i=0; env_get_char(i) != '\0'; i=nxt+1) { @@ -534,6 +535,7 @@ int getenv_r (char *name, char *buf, unsigned len) { int i, nxt;
+ name = LINK_OFF(name); for (i=0; env_get_char(i) != '\0'; i=nxt+1) { int val, n;
diff --git a/common/console.c b/common/console.c index dc0d13b..afda83a 100644 --- a/common/console.c +++ b/common/console.c @@ -346,7 +346,7 @@ void putc(const char c) } }
-void puts(const char *s) +static void printf_puts(const char *s) { #ifdef CONFIG_SILENT_CONSOLE if (gd->flags & GD_FLG_SILENT) @@ -367,12 +367,18 @@ void puts(const char *s) } }
+void puts(const char *s) +{ + printf_puts(LINK_OFF(s)); +} + void printf(const char *fmt, ...) { va_list args; uint i; char printbuffer[CONFIG_SYS_PBSIZE];
+ fmt = LINK_OFF(fmt); va_start(args, fmt);
/* For this to work, printbuffer must be larger than @@ -382,7 +388,7 @@ void printf(const char *fmt, ...) va_end(args);
/* Print the string */ - puts(printbuffer); + printf_puts(printbuffer); }
void vprintf(const char *fmt, va_list args) @@ -396,7 +402,7 @@ void vprintf(const char *fmt, va_list args) i = vsprintf(printbuffer, fmt, args);
/* Print the string */ - puts(printbuffer); + printf_puts(printbuffer); }
/* test if ctrl-c was pressed */ diff --git a/common/env_common.c b/common/env_common.c index 439a4a9..107e711 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -153,7 +153,7 @@ static uchar env_get_char_init (int index) { c = env_get_char_spec(index); } else { - c = default_environment[index]; + c = LINK_OFF(default_environment)[index]; }
return (c); diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index e38a372..12a2a84 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -51,8 +51,8 @@ int checkcpu(void) char buf[32]; int i;
- const struct cpu_type { - char name[15]; + static const struct cpu_type { + char *name; u32 partid; } cpu_type_list [] = { CPU_TYPE_ENTRY(8311), @@ -72,6 +72,7 @@ int checkcpu(void) CPU_TYPE_ENTRY(8378), CPU_TYPE_ENTRY(8379), }; + const struct cpu_type *cpu_ptr = LINK_OFF(cpu_type_list);
immr = (immap_t *)CONFIG_SYS_IMMR;
@@ -99,11 +100,10 @@ int checkcpu(void) }
spridr = immr->sysconf.spridr; - for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) - if (cpu_type_list[i].partid == PARTID_NO_E(spridr)) { + if (cpu_ptr[i].partid == PARTID_NO_E(spridr)) { puts("MPC"); - puts(cpu_type_list[i].name); + puts(cpu_ptr[i].name); if (IS_E_PROCESSOR(spridr)) puts("E"); if (REVID_MAJOR(spridr) >= 2) diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index 031e8d5..e1f9018 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -42,13 +42,14 @@ static void config_qe_ioports(void) u8 port, pin; int dir, open_drain, assign; int i; - - for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) { - port = qe_iop_conf_tab[i].port; - pin = qe_iop_conf_tab[i].pin; - dir = qe_iop_conf_tab[i].dir; - open_drain = qe_iop_conf_tab[i].open_drain; - assign = qe_iop_conf_tab[i].assign; + qe_iop_conf_t *qe_ptr = LINK_OFF(qe_iop_conf_tab); + + for (i = 0; qe_ptr[i].assign != QE_IOP_TAB_END; i++) { + port = qe_ptr[i].port; + pin = qe_ptr[i].pin; + dir = qe_ptr[i].dir; + open_drain = qe_ptr[i].open_drain; + assign = qe_ptr[i].assign; qe_config_iopin(port, pin, dir, open_drain, assign); } } @@ -378,7 +379,7 @@ int cpu_init_r (void) #if defined(CONFIG_DISPLAY_AER_FULL) static int print_83xx_arb_event(int force) { - static char* event[] = { + static const char* event[] = { "Address Time Out", "Data Time Out", "Address Only Transfer Type", @@ -388,7 +389,7 @@ static int print_83xx_arb_event(int force) "reserved", "reserved" }; - static char* master[] = { + static const char* master[] = { "e300 Core Data Transaction", "reserved", "e300 Core Instruction Fetch", @@ -422,7 +423,7 @@ static int print_83xx_arb_event(int force) "PCI Express 2", "TDM-DMAC" }; - static char *transfer[] = { + static const char *transfer[] = { "Address-only, Clean Block", "Address-only, lwarx reservation set", "Single-beat or Burst write", @@ -473,11 +474,11 @@ static int print_83xx_arb_event(int force)
puts("Arbiter Event Status:\n"); printf(" Event Address: 0x%08lX\n", gd->arbiter_event_address); - printf(" Event Type: 0x%1x = %s\n", etype, event[etype]); - printf(" Master ID: 0x%02x = %s\n", mstr_id, master[mstr_id]); + printf(" Event Type: 0x%1x = %s\n", etype, LINK_OFF(event)[etype]); + printf(" Master ID: 0x%02x = %s\n", mstr_id, LINK_OFF(master)[mstr_id]); printf(" Transfer Size: 0x%1x = %d bytes\n", (tbst<<3) | tsize, tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize); - printf(" Transfer Type: 0x%02x = %s\n", ttype, transfer[ttype]); + printf(" Transfer Type: 0x%02x = %s\n", ttype, LINK_OFF(transfer)[ttype]);
return gd->arbiter_event_address; } @@ -501,7 +502,7 @@ static int print_83xx_arb_event(int force) */ int prt_83xx_rsr(void) { - static struct { + static const struct reset_type { ulong mask; char *desc; } bits[] = { @@ -515,7 +516,7 @@ int prt_83xx_rsr(void) RSR_SRS, "External/Internal Soft"}, { RSR_HRS, "External/Internal Hard"} }; - static int n = sizeof bits / sizeof bits[0]; + const struct reset_type *bp = LINK_OFF(bits); ulong rsr = gd->reset_status; int i; char *sep; @@ -523,9 +524,10 @@ int prt_83xx_rsr(void) puts("Reset Status:");
sep = " "; - for (i = 0; i < n; i++) - if (rsr & bits[i].mask) { - printf("%s%s", sep, bits[i].desc); + for (i = 0; i < ARRAY_SIZE(bits); i++) + if (rsr & bp[i].mask) { + puts(sep); + puts(bp[i].desc); sep = ", "; } puts("\n"); diff --git a/cpu/mpc83xx/speed.c b/cpu/mpc83xx/speed.c index bde7e92..001387a 100644 --- a/cpu/mpc83xx/speed.c +++ b/cpu/mpc83xx/speed.c @@ -98,7 +98,8 @@ int get_clocks(void) u32 corecnf_tab_index; u8 corepll; u32 lcrr; - + corecnf_t *cnf_tab; + int csb_r; u32 csb_clk; #if defined(CONFIG_MPC834x) || defined(CONFIG_MPC831x) || defined(CONFIG_MPC837x) u32 tsec1_clk; @@ -413,28 +414,21 @@ int get_clocks(void) /* corecnf_tab_index is too high, possibly worng value */ return -11; } - switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) { - case _byp: - case _x1: - case _1x: + cnf_tab = LINK_OFF(corecnf_tab); + csb_r = cnf_tab[corecnf_tab_index].core_csb_ratio; + /* Cannot use a switch stmt here, it uses linked address */ + if (csb_r == _byp || csb_r == _x1 || csb_r == _1x) core_clk = csb_clk; - break; - case _1_5x: + else if (csb_r == _1_5x) core_clk = (3 * csb_clk) / 2; - break; - case _2x: + else if (csb_r == _2x) core_clk = 2 * csb_clk; - break; - case _2_5x: + else if (csb_r == _2_5x) core_clk = (5 * csb_clk) / 2; - break; - case _3x: + else if (csb_r == _3x) core_clk = 3 * csb_clk; - break; - default: - /* unkown core to csb ratio */ + else /* unkown core to csb ratio */ return -13; - }
#if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832x) qepmf = (im->reset.rcwl & HRCWL_CEPMF) >> HRCWL_CEPMF_SHIFT; diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index dd5f332..4ccfb56 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -85,9 +85,9 @@ static NS16550_t serial_ports[4] = { #endif };
-#define PORT serial_ports[port-1] +#define PORT (LINK_OFF(serial_ports)[port-1]) #if defined(CONFIG_CONS_INDEX) -#define CONSOLE (serial_ports[CONFIG_CONS_INDEX-1]) +#define CONSOLE (LINK_OFF(serial_ports)[CONFIG_CONS_INDEX-1]) #endif
#if defined(CONFIG_SERIAL_MULTI) @@ -159,26 +159,27 @@ static int calc_divisor (NS16550_t port) int serial_init (void) { int clock_divisor; + NS16550_t * sp = LINK_OFF(serial_ports);
#ifdef CONFIG_NS87308 initialise_ns87308(); #endif
#ifdef CONFIG_SYS_NS16550_COM1 - clock_divisor = calc_divisor(serial_ports[0]); - NS16550_init(serial_ports[0], clock_divisor); + clock_divisor = calc_divisor(sp[0]); + NS16550_init(sp[0], clock_divisor); #endif #ifdef CONFIG_SYS_NS16550_COM2 - clock_divisor = calc_divisor(serial_ports[1]); - NS16550_init(serial_ports[1], clock_divisor); + clock_divisor = calc_divisor(sp[1]); + NS16550_init(sp[1], clock_divisor); #endif #ifdef CONFIG_SYS_NS16550_COM3 - clock_divisor = calc_divisor(serial_ports[2]); - NS16550_init(serial_ports[2], clock_divisor); + clock_divisor = calc_divisor(sp[2]); + NS16550_init(sp[2], clock_divisor); #endif #ifdef CONFIG_SYS_NS16550_COM4 - clock_divisor = calc_divisor(serial_ports[3]); - NS16550_init(serial_ports[3], clock_divisor); + clock_divisor = calc_divisor(sp[3]); + NS16550_init(sp[3], clock_divisor); #endif
return (0); diff --git a/include/linux/ctype.h b/include/linux/ctype.h index afa3639..5873c55 100644 --- a/include/linux/ctype.h +++ b/include/linux/ctype.h @@ -1,6 +1,6 @@ #ifndef _LINUX_CTYPE_H #define _LINUX_CTYPE_H - +#include <common.h> /* * NOTE! This ctype does not handle EOF like the standard C * library is required to. @@ -15,9 +15,9 @@ #define _X 0x40 /* hex digit */ #define _SP 0x80 /* hard space (0x20) */
-extern unsigned char _ctype[]; +extern const unsigned char _ctype[];
-#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) +#define __ismask(x) (LINK_OFF(_ctype)[(int)(unsigned char)(x)])
#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) diff --git a/lib_generic/crc32.c b/lib_generic/crc32.c index b27048c..2e11548 100644 --- a/lib_generic/crc32.c +++ b/lib_generic/crc32.c @@ -148,7 +148,7 @@ const uint32_t * ZEXPORT get_crc_table() #endif
/* ========================================================================= */ -#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO1(buf) crc = crc_tab[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); #define DO2(buf) DO1(buf); DO1(buf); #define DO4(buf) DO2(buf); DO2(buf); #define DO8(buf) DO4(buf); DO4(buf); @@ -156,6 +156,11 @@ const uint32_t * ZEXPORT get_crc_table() /* ========================================================================= */ uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *buf, uInt len) { +#ifdef LINK_OFF + const uint32_t *crc_tab = LINK_OFF(crc_table); +#else + const uint32_t *crc_tab = crc_table; +#endif #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); diff --git a/lib_generic/ctype.c b/lib_generic/ctype.c index 6ed0468..dffe563 100644 --- a/lib_generic/ctype.c +++ b/lib_generic/ctype.c @@ -29,7 +29,7 @@
#include <linux/ctype.h>
-unsigned char _ctype[] = { +const unsigned char _ctype[] = { _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ diff --git a/lib_generic/display_options.c b/lib_generic/display_options.c index 2dc2567..6b9fba2 100644 --- a/lib_generic/display_options.c +++ b/lib_generic/display_options.c @@ -31,9 +31,9 @@ int display_options (void) extern char version_string[];
#if defined(BUILD_TAG) - printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG); + printf ("\n\n%s, Build: %s\n\n", LINK_OFF(version_string), LINK_OFF(BUILD_TAG)); #else - printf ("\n\n%s\n\n", version_string); + printf ("\n\n%s\n\n", LINK_OFF(version_string)); #endif return 0; } @@ -49,6 +49,7 @@ void print_size (phys_size_t size, const char *s) phys_size_t d = 1 << 30; /* 1 GB */ char c = 'G';
+ s = LINK_OFF(s); if (size < d) { /* try MB */ c = 'M'; d = 1 << 20; diff --git a/lib_generic/vsprintf.c b/lib_generic/vsprintf.c index 3d95728..b779f56 100644 --- a/lib_generic/vsprintf.c +++ b/lib_generic/vsprintf.c @@ -37,8 +37,8 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
const char hex_asc[] = "0123456789abcdef"; -#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] -#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] +#define hex_asc_lo(x) LINK_OFF(hex_asc)[((x) & 0x0f)] +#define hex_asc_hi(x) LINK_OFF(hex_asc)[((x) & 0xf0) >> 4]
static inline char *pack_hex_byte(char *buf, u8 byte) { @@ -303,7 +303,7 @@ static char *number(char *buf, unsigned NUM_TYPE num, int base, int size, int pr int shift = 3; if (base == 16) shift = 4; do { - tmp[i++] = (digits[((unsigned char)num) & mask] | locase); + tmp[i++] = (LINK_OFF(digits)[((unsigned char)num) & mask] | locase); num >>= shift; } while (num); } else { /* base 10 */ @@ -675,6 +675,7 @@ int sprintf(char * buf, const char *fmt, ...) va_list args; int i;
+ fmt = LINK_OFF(fmt); va_start(args, fmt); i=vsprintf(buf,fmt,args); va_end(args); @@ -684,6 +685,8 @@ int sprintf(char * buf, const char *fmt, ...) void panic(const char *fmt, ...) { va_list args; + + fmt = LINK_OFF(fmt); va_start(args, fmt); vprintf(fmt, args); putc('\n'); diff --git a/lib_ppc/board.c b/lib_ppc/board.c index 765f97a..f9a7d30 100644 --- a/lib_ppc/board.c +++ b/lib_ppc/board.c @@ -384,8 +384,9 @@ void board_init_f (ulong bootflag) memset ((void *) gd, 0, sizeof (gd_t)); #endif
- for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { - if ((*init_fnc_ptr) () != 0) { + for (init_fnc_ptr = LINK_OFF(init_sequence); *init_fnc_ptr; + ++init_fnc_ptr) { + if (((init_fnc_t *)link_off(*init_fnc_ptr)) () != 0) { hang (); } } diff --git a/tools/updater/ctype.c b/tools/updater/ctype.c index 6ed0468..dffe563 100644 --- a/tools/updater/ctype.c +++ b/tools/updater/ctype.c @@ -29,7 +29,7 @@
#include <linux/ctype.h>
-unsigned char _ctype[] = { +const unsigned char _ctype[] = { _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */

This is the most complex change. Keep this one as a separate commit for now. --- common/env_flash.c | 65 +++++++++++++++++++++++++++++++-------------------- 1 files changed, 39 insertions(+), 26 deletions(-)
diff --git a/common/env_flash.c b/common/env_flash.c index b860c48..64882d2 100644 --- a/common/env_flash.c +++ b/common/env_flash.c @@ -52,27 +52,28 @@ DECLARE_GLOBAL_DATA_PTR;
char * env_name_spec = "Flash";
+static int flash_env_swapped; + #ifdef ENV_IS_EMBEDDED
extern uchar environment[]; env_t *env_ptr = (env_t *)(&environment[0]);
#ifdef CMD_SAVEENV -/* static env_t *flash_addr = (env_t *)(&environment[0]);-broken on ARM-wd-*/ -static env_t *flash_addr = (env_t *)CONFIG_ENV_ADDR; +#define flash_addr f_flash_addr() #endif
#else /* ! ENV_IS_EMBEDDED */
env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; #ifdef CMD_SAVEENV -static env_t *flash_addr = (env_t *)CONFIG_ENV_ADDR; +#define flash_addr f_flash_addr() #endif
#endif /* ENV_IS_EMBEDDED */
#ifdef CONFIG_ENV_ADDR_REDUND -static env_t *flash_addr_new = (env_t *)CONFIG_ENV_ADDR_REDUND; +#define flash_addr_new f_flash_addr_new()
/* CONFIG_ENV_ADDR is supposed to be on sector boundary */ static ulong end_addr = CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1; @@ -80,10 +81,35 @@ static ulong end_addr_new = CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1;
#define ACTIVE_FLAG 1 #define OBSOLETE_FLAG 0 + +static void flash_env_swap(void) +{ + ulong ltmp = end_addr; + + flash_env_swapped = !flash_env_swapped; + + end_addr = end_addr_new; + end_addr_new = ltmp; +} + +static env_t * f_flash_addr_new(void) +{ + if (!*(LINK_OFF(&flash_env_swapped))) + return (env_t *)CONFIG_ENV_ADDR_REDUND; + else + return (env_t *)CONFIG_ENV_ADDR; +} #endif /* CONFIG_ENV_ADDR_REDUND */
extern uchar default_environment[];
+static env_t * f_flash_addr(void) +{ + if (!(*LINK_OFF(&flash_env_swapped))) + return (env_t *)CONFIG_ENV_ADDR; + else + return (env_t *)CONFIG_ENV_ADDR_REDUND; +}
uchar env_get_char_spec (int index) { @@ -99,7 +125,7 @@ int env_init(void) uchar flag1 = flash_addr->flags; uchar flag2 = flash_addr_new->flags;
- ulong addr_default = (ulong)&default_environment[0]; + ulong addr_default = (ulong)LINK_OFF(default_environment); ulong addr1 = (ulong)&(flash_addr->data); ulong addr2 = (ulong)&(flash_addr_new->data);
@@ -218,14 +244,7 @@ int saveenv(void) } #endif { - env_t * etmp = flash_addr; - ulong ltmp = end_addr; - - flash_addr = flash_addr_new; - flash_addr_new = etmp; - - end_addr = end_addr_new; - end_addr_new = ltmp; + flash_env_swap(); }
rc = 0; @@ -245,13 +264,15 @@ Done:
int env_init(void) { - if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { - gd->env_addr = (ulong)&(env_ptr->data); + env_t *ep = *LINK_OFF(&env_ptr); + + if (crc32(0, ep->data, ENV_SIZE) == ep->crc) { + gd->env_addr = (ulong)&(ep->data); gd->env_valid = 1; return(0); }
- gd->env_addr = (ulong)&default_environment[0]; + gd->env_addr = (ulong)LINK_OFF(default_environment); gd->env_valid = 0; return (0); } @@ -334,16 +355,8 @@ void env_relocate_spec (void) { #if !defined(ENV_IS_EMBEDDED) || defined(CONFIG_ENV_ADDR_REDUND) #ifdef CONFIG_ENV_ADDR_REDUND - if (gd->env_addr != (ulong)&(flash_addr->data)) { - env_t * etmp = flash_addr; - ulong ltmp = end_addr; - - flash_addr = flash_addr_new; - flash_addr_new = etmp; - - end_addr = end_addr_new; - end_addr_new = ltmp; - } + if (gd->env_addr != (ulong)&(flash_addr->data)) + flash_env_swap();
if (flash_addr_new->flags != OBSOLETE_FLAG && crc32(0, flash_addr_new->data, ENV_SIZE) ==

To use a different link address than load address, start.S must not make any absolute accesses. This makes it so. Use link_off(), if defined, to calculate the difference in load and link address. --- cpu/mpc83xx/start.S | 35 ++++++++++++++++++++++++++++------- 1 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index 68bb620..bc17a60 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -240,9 +240,23 @@ boot_warm: /* time t 5 */ /* there and deflate the flash size back to minimal size */ /*------------------------------------------------------------*/ bl map_flash_by_law1 - lis r4, (CONFIG_SYS_MONITOR_BASE)@h - ori r4, r4, (CONFIG_SYS_MONITOR_BASE)@l - addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET + + /* Calculate address in flash and jump there */ + bl 1f +1: mflr r5 /* get current address */ + addi r5, r5, in_flash - 1b + /* Check if already inside flash address space. */ + /* if so, do not add CONFIG_SYS_FLASH_BASE */ + lis r4, (CONFIG_SYS_FLASH_BASE)@h + ori r4, r4, (CONFIG_SYS_FLASH_BASE)@l + cmplw cr0, r5, r4 + ble cr0, 2f /* r5 < r4 ? */ + lis r6, (CONFIG_SYS_FLASH_BASE+CONFIG_SYS_FLASH_SIZE)@h + ori r6, r6, (CONFIG_SYS_FLASH_BASE+CONFIG_SYS_FLASH_SIZE)@l + cmplw cr0, r5, r6 + bgt cr0, 3f /* r5 > r6 ? */ +2: add r5,r5,r4 +3: mtlr r5 blr in_flash: @@ -831,11 +845,18 @@ relocate_code: mr r10, r5 /* Save copy of Destination Address */
GET_GOT - mr r3, r5 /* Destination Address */ - lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */ - ori r4, r4, CONFIG_SYS_MONITOR_BASE@l + li r3, 0 +#ifdef CONFIG_LINK_OFF + bl link_off /* const void * link_off(const void *) */ +#endif + lwz r4, GOT(_start) /* Source Address */ + add r4, r4, r3 + addi r4, r4, -EXC_OFF_SYS_RESET lwz r5, GOT(__bss_start) - sub r5, r5, r4 + add r5, r5, r3 + mr r3, r10 /* Destination Address */ + + sub r5, r5, r4 /* r4 - r5 */ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
/*

Any interest in these patches I sent some time ago?
Jocke
Joakim Tjernlund Joakim.Tjernlund@transmode.se wrote on 02/11/2009 19:01:16:
From: Joakim Tjernlund Joakim.Tjernlund@transmode.se To: u-boot@lists.denx.de Cc: Joakim Tjernlund Joakim.Tjernlund@transmode.se Date: 02/11/2009 19:01 Subject: [PATCH 0/4] Make u-boot true PIC for ppc
This series adds link_off(), a function to calculate the difference between load address and link address.
Using this function it is possible to make u-boot 100% PIC by wrapping global data accesses LINK_OFF() calls. Plenty of examples in the code to show how to use it.
All start.S needs to be updated too and I have done so with mpc83xx.
-DCONFIG_LINK_OFF in your platform config.mk to make use of this function.
Needs the -ffixed-r14 patches I just sent or you can fix the conflicts manually.
Would really appreciate some testing by 83xx owners. Scott?
Jocke
Joakim Tjernlund (4): ppc: Add const void *link_off(const void *addr) Use LINK_OFF to access global data Use LINK_OFF in enviroment too ppc: Make mpc83xx start.S relative.
common/cmd_nvedit.c | 2 + common/console.c | 12 ++++++-- common/env_common.c | 2 +- common/env_flash.c | 65 ++++++++++++++++++++++++---------------- cpu/mpc83xx/cpu.c | 10 +++--- cpu/mpc83xx/cpu_init.c | 38 ++++++++++++----------- cpu/mpc83xx/speed.c | 28 +++++++----------- cpu/mpc83xx/start.S | 35 +++++++++++++++++---- drivers/serial/serial.c | 21 +++++++------ include/common.h | 7 ++++ include/linux/ctype.h | 6 ++-- lib_generic/crc32.c | 7 ++++- lib_generic/ctype.c | 2 +- lib_generic/display_options.c | 5 ++- lib_generic/vsprintf.c | 9 ++++-- lib_ppc/board.c | 5 ++- lib_ppc/reloc.S | 21 +++++++++++++ tools/updater/ctype.c | 2 +- 18 files changed, 177 insertions(+), 100 deletions(-)

Dear Joakim Tjernlund,
In message OF8B4816FE.B31EEE7E-ONC125768C.004F687D-C125768C.004F9011@transmode.se you wrote:
Any interest in these patches I sent some time ago?
Lots of ionterest actually. But so little time :-(
Sorry..
Best regards,
Wolfgang Denk

Wolfgang Denk wd@denx.de wrote on 14/12/2009 21:11:17:
Dear Joakim Tjernlund,
In message <OF8B4816FE.B31EEE7E-ONC125768C.004F687D-C125768C. 004F9011@transmode.se> you wrote:
Any interest in these patches I sent some time ago?
Lots of ionterest actually. But so little time :-(
OK, good to know. I will wait then.
Jocke
participants (3)
-
Joakim Tjernlund
-
Joakim Tjernlund
-
Wolfgang Denk