[U-Boot-Users] bd_info vs. global_data

In looking at OF_TBCLK-related code, I noticed that U-Boot has what is basically two structures that contain a variety of "global" data, global_data and bd_info. There are a number of fields in bd_info that also exist in global_data and contain the same value. For instance, we have this in board_init_f():
bd->bi_inpfreq = gd->inp_clk; bd->bi_pcifreq = gd->pci_clk; bd->bi_vcofreq = gd->vco_clk; bd->bi_pevfreq = gd->pev_clk; bd->bi_flbfreq = gd->flb_clk;
From my understanding, the bd_info structure is passed to the kernel as a binary blob, whereas the the global_data structure is used internally by U-Boot to store global data. Obviously, we can't get rid of one or the other.
Wouldn't it be better if the bd_info structure were created and initialized only when Linux is about to be booted? Currently, we have some code that uses bd->xxx and other code that uses gd->xxx, with no real consistence. I think the bd_info structure should be local to cmd_bootm.c, and should be allocated and initialized only if we're booting a non-OF version of Linux. This would eliminate using bd-> for anything other than booting non-OF Linux.
Comments?

In message 4553B60D.3030901@freescale.com you wrote:
In looking at OF_TBCLK-related code, I noticed that U-Boot has what is basically two structures that contain a variety of "global" data, global_data and bd_info. There are a number of fields in bd_info that also exist in global_data and contain the same value. For instance, we have this in board_init_f():
Right. Historically, we started with bd_info, and gd was added later when we needed to find a way to pass "global data" around in U-Boot. This was mostly a code size optimization - before, we had to pass all this stuff in long argument lists - if any low level function needed such data, we had to pass it though all callers.
From my understanding, the bd_info structure is passed to the kernel as a binary blob, whereas the the global_data structure is used internally by U-Boot to store global data. Obviously, we can't get rid of one or the other.
Correct.
Wouldn't it be better if the bd_info structure were created and initialized only when Linux is about to be booted? Currently, we have some code that uses
Yes, but IIRC also contains information that is noit available in gd, and I don't want to extend gd if it can be avoided, a this is taken from very scarce resources.
bd->xxx and other code that uses gd->xxx, with no real consistence. I think
Actually, in most cases it makes some sense if you think longer about it. But I agree, it's not nice.
the bd_info structure should be local to cmd_bootm.c, and should be allocated and initialized only if we're booting a non-OF version of Linux. This would eliminate using bd-> for anything other than booting non-OF Linux.
Comments?
Did you try to implement this?
Keep in mind that not all the world is a VAX ... oops, wrong decade, a PowerPC. You won't find OFT implementations on ARM, MIPS, NIOS, BF, CF, ...
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Yes, but IIRC also contains information that is noit available in gd, and I don't want to extend gd if it can be avoided, a this is taken from very scarce resources.
Is the bd located immediately after the gd in memory?
bd->xxx and other code that uses gd->xxx, with no real consistence. I think
Actually, in most cases it makes some sense if you think longer about it. But I agree, it's not nice.
How about a rule that any function can write to bd_info (to initialize its contents), but only the do_bootm_xxx functions can read from it, and only to prepare it for passing to Linux. This would eliminate code like this:
#define OF_TBCLK (bd->bi_busfreq / 4)
and hopefully stuff like this:
if ((s = getenv ("clocks_in_mhz")) != NULL) { /* convert all clock information to MHz */ kbd->bi_intfreq /= 1000000L; kbd->bi_busfreq /= 1000000L; #if defined(CONFIG_MPC8220) kbd->bi_inpfreq /= 1000000L; kbd->bi_pcifreq /= 1000000L; kbd->bi_pevfreq /= 1000000L; kbd->bi_flbfreq /= 1000000L; kbd->bi_vcofreq /= 1000000L; #endif #if defined(CONFIG_CPM2) kbd->bi_cpmfreq /= 1000000L; kbd->bi_brgfreq /= 1000000L; kbd->bi_sccfreq /= 1000000L; kbd->bi_vco /= 1000000L; #endif
In this case, I don't understand the clocks_in_mhz environment variable. Is this something that we really want to be run-time configurable?
the bd_info structure should be local to cmd_bootm.c, and should be allocated and initialized only if we're booting a non-OF version of Linux. This would eliminate using bd-> for anything other than booting non-OF Linux.
Comments?
Did you try to implement this?
No, it's just something that occurred to me today while trying to resolve the OF_TBCLK problem.

In message 4553E0C4.4010207@freescale.com you wrote:
Is the bd located immediately after the gd in memory?
No, not at all. Actually we start with the gd, and space fopr the bd becomes only available after relocation to RAM.
How about a rule that any function can write to bd_info (to initialize its contents), but only the do_bootm_xxx functions can read from it, and only to prepare it for passing to Linux. This would eliminate code like this:
#define OF_TBCLK (bd->bi_busfreq / 4)
I don't see how such a rule would actually prevent such code...
and hopefully stuff like this:
No, this is perfectly reasonable and necessary.
In this case, I don't understand the clocks_in_mhz environment variable. Is
RTFM.
this something that we really want to be run-time configurable?
Yes, of course we de. We certainly *do* want to be able to boot both old and new Linux kernels and to switch between their different interfaces in runtime.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
In message 4553E0C4.4010207@freescale.com you wrote:
Is the bd located immediately after the gd in memory?
No, not at all. Actually we start with the gd, and space fopr the bd becomes only available after relocation to RAM.
So gd initially lives in cache? I don't see in the README where it says where gd_t is initially allocated, but I do see this in the code:
gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
That value is equal to 0xFD000F00. I can't really tell from the code or documentation, but I'm guessing U-Boot has set up a 4KB block of cache-as-RAM at FD000000. Either that or it's some kind of on-chip RAM, but I can't find any reference to that in any of my manuals. I have an 8349.
How about a rule that any function can write to bd_info (to initialize its contents), but only the do_bootm_xxx functions can read from it, and only to prepare it for passing to Linux. This would eliminate code like this:
#define OF_TBCLK (bd->bi_busfreq / 4)
I don't see how such a rule would actually prevent such code...
Well, in this case, the above line would change to "(gd->bus_clk / 4)" to conform with that rule.
In this case, I don't understand the clocks_in_mhz environment variable. Is
RTFM.
Wow, look at that! It's clearly explained in the README! Sorry. :-[
However, it looks like there's some redundancy in this. Couldn't the variable disable_of perform the same function? Or even better, couldn't we just check whether a pointer to an OF tree is passed to the bootm parameter? If the user includes an OF tree on the bootm command line, then boot an OF kernel. Otherwise, convert the frequency values to MHZ and boot a traditional kernel.
Speaking of do_bootm_linux(), why is the PPC version of this function in cmd_bootm.c instead of lib_ppc/ppc_linux.c?

In message 4554AB0E.7000805@freescale.com you wrote:
So gd initially lives in cache? I don't see in the README where it says where gd_t is initially allocated, but I do see this in the code:
This depends on the architecture. It may be cache, or some on-chip memory, or some SRAM, or whatever is available on a board that works as RAM without specific initialization.
However, it looks like there's some redundancy in this. Couldn't the variable disable_of perform the same function? Or even better, couldn't we just check
No, it cannot. Because the change was done a long time ago in the 2.4 kernel tree, somewhere around 2.4.5-pre5. Using a 2.4.4 kernel or a 2.4.5 kernel require different clock encoding (one in MHz, the other in Hz). This does not depend on any OF stuff at all.
whether a pointer to an OF tree is passed to the bootm parameter? If the user includes an OF tree on the bootm command line, then boot an OF kernel. Otherwise, convert the frequency values to MHZ and boot a traditional kernel.
It seems you did not read much of the documentation.
Speaking of do_bootm_linux(), why is the PPC version of this function in cmd_bootm.c instead of lib_ppc/ppc_linux.c?
For historical reasons. We started with PPC only, so it was natural to have this in cmd_bootm.c. Other architectures placed theit code somewhere else, but nobody changed the PPC code.
Best regards,
Wolfgang Denk
participants (2)
-
Timur Tabi
-
Wolfgang Denk