[U-Boot] [PATCH 2/4] Use LINK_OFF to access global data
Joakim Tjernlund
joakim.tjernlund at transmode.se
Sun Jan 3 11:33:02 CET 2010
Wolfgang Denk <wd at denx.de> wrote on 02/01/2010 19:13:29:
>
> Dear Joakim Tjernlund,
>
> In message <1262185712-11890-3-git-send-email-Joakim.Tjernlund at transmode.se> you wrote:
> > 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(-)
> ...
> > -void puts(const char *s)
> > +static void printf_puts(const char *s)
>
> The name "printf_puts" makes my (remaining) hair stand on end. Either
> we have printf(), or we have puts(), but please let's never use
> "printf_puts" - I fear there might be a "printf_getchar" coming, too.
OK, I can fix the name easily.
>
> > +void puts(const char *s)
> > +{
> > + printf_puts(LINK_OFF(s));
> > +}
>
> Will such changes be needed to all functions that work on (constant?)
> strings? Or why here?
Only those that work on constant strings before relocation to RAM. One alternative
is to change all call sites to puts(LINK_OFF(s)).
I this particular case I need an intermediate function as puts() are
used by printf() too and printf() don't want the LINK_OFF transformation.
>
> > --- 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;
>
> I guess we have similar constructs in many other places as well. Do
> all of these need to be changed? Really?
I guess I could have changed the code below:
- puts(cpu_type_list[i].name);
+ puts(cpu_ptr[i].name);
to something else instead but the change I did do felt best as
we hardly need name to be 15 chars wide and we don't need to initialise
it at runtime.
but yes, all such constructs in cpu_init like code needs to be looked upon
iff one wants to use this feature.
>
> > - 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 */
>
> Yet another of these really, really invasive changes. Is this
> really unavoidable?
Yes, global data and strings accessed before relocation to RAM needs
to be wrapped with LINK_OFF to calculate the real address.
>
> Why can we use "if" but not "switch/case" ?
For some reason, the code generated by gcc wasn't true PIC. The jump table
that the switch stmt generated accessed the GOT. This may very well be a gcc bug.
>
> > --- 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
>
> I wonder how you selected the places where such changes were needed,
> and where not. There is certainly lots of similar looking code that
> you don't touch. Why not? Because it's not needed (then why do we
> need these changes here?), or because it just did not result in errors
> in your tests so far (then what's the estimate for the full amount of
> changes?) ???
I selected the changes I needed to for my 83xx board and then some. I don't
think serial.c needs any more changes.
Remember you only have to consider code that uses global data and
is executed before relocation to RAM and that limits the scope quite a lot.
The places to look at you find by following board.c's init_sequence.
I think my changes are fairly complete for PowerPC,83xx. There are missing
bits to do, mainly in other archs I think, but boards that doesn't need/want
this functionality don't have to change anything.
Jocke
More information about the U-Boot
mailing list