Previously, ubldr would use the virtual addresses in the elf headers by
masking off the high bits and assuming the result was a physical address
where the kernel should be loaded. That would sometimes discard
significant bits of the physical address, but the effects of that were
undone by archsw copy code that would find a large block of memory and
apply an offset to the source/dest copy addresses. The result was that
things were loaded at a different physical address than requested by the
higher code layers, but that worked because other adjustments were applied
later (such as when jumping to the entry point). Very confusing, and
somewhat fragile.
Now the archsw copy routines are just simple copies, and instead
archsw.arch_loadaddr is implemented to choose a load address. The new
routine uses some of the code from the old offset-translation routine to
find the largest block of ram, but it excludes ubldr itself from that
range, and also excludes If ubldr splits the largest block of ram in
two, the kernel is loaded into the bottom of whichever resulting block is
larger.
As part of eliminating ubldr itself from the ram ranges, export the heap
start/end addresses in a pair of new global variables.
This change means that the virtual addresses in the arm kernel elf headers
now have no meaning at all, except for the entry point address. There is
an implicit assumption that the entry point is in the first text page, and
that the address in the the header can be turned into an offset by masking
it with PAGE_MASK. In the future we can link all arm kernels at a virtual
address of 0xC0000000 with no need to use any low-order part of the
address to influence where in ram the kernel gets loaded.
u-boot env into the loader(8) env (which also gets them into the kernel
env). You can import selected variables or the whole environment. Each
u-boot var=value becomes uboot.var=value in the loader env. You can also
use 'ubenv show' to display uboot vars without importing them.
particular, allow loaders to define the name of the RC script the
interpreter needs to use. Use this new-found control to have the
PXE loader (when compiled with TFTP support and not NFS support)
read from ${bootfile}.4th, where ${bootfile} is the name of the
file fetched by the PXE firmware.
The normal startup process involves reading the following files:
1. /boot/boot.4th
2. /boot/loader.rc or alternatively /boot/boot.conf
When these come from a FreeBSD-defined file system, this is all
good. But when we boot over the network, subdirectories and fixed
file names are often painful to administrators and there's really
no way for them to change the behaviour of the loader.
Obtained from: Juniper Networks, Inc.
- Display slice and partition as <auto> instead of 0 or -1 when they're
not set to specific values (the paritition=-1 was confusing folks).
- When loaderdev isn't set in the u-boot environment, say so rather
than displaying unknown device ''.
- Print the loader(8) ident/version info earlier, so that all device-
related info appears together afterwards.
The one change here that isn't purely cosmetic is to call setheap()
earlier. The comment says "Initialise heap as early as possible", now
that's more accurate. It shouldn't make any functional difference, but
may be safer if future changes lead to trying to allocate memory earlier.
setting the u-boot environment variable loaderdev=. It used to accept only
'disk' or 'net'. Now it allows specification of unit, slice, and partition
as well. In addition to the generic 'disk' it also accepts specific
storage device types such as 'mmc' or 'sata'.
If there isn't a loaderdev env var, the historical behavior is maintained.
It will use the first storage device it finds, or a network device if
no working storage device exists.
99% of the work on this was done by Patrick Kelsey, but I made some
changes, so if anything goes wrong, blame me.
Submitted by: Patrick Kelsey <kelsey@ieee.org>
by having uboot_autoload() do the fdt setup (which may load a file) rather
than waiting until we're actually in the process of launching the kernel.
As part of making this happen...
- Define LOADER_FDT_SUPPORT on the uboot/lib compile command line when
MK_FDT is set.
- Make fdt_setup_fdtb() public.
- Declare public fdt_whatever() functions in a header instead of using
scattered extern decls in .c files.
If a "loaderdev=<device>" env variable is set and the named device
exists, it is used. If the device doesn't exist, fall back to the
historic "probe" loop that prefers disk devices over network devices.
If the env var is not set, preserve the historic behavior of using the
first working disk device provided by u-boot, or a network device if no
functional disk device is found and a network device exists.
The old probe loop is reworked so that it checks all bootable devices
provided by u-boot rather than taking an early-out on the first device
found. This results in the cosmetic change of listing all potential boot
devices for the user, but the behavior of which device it chooses is the
same as it has always been.
- Add "fdt addr" subcommand that lets you specify preloaded blob address
- Do not pre-initialize blob for "fdt addr"
- Do not try to load dtb every time fdt subcommand is issued,
do it only once
- Change the way DTB is passed to kernel. With introduction of "fdt addr"
actual blob address can be not virtual but physical or reside in
area higher then 64Mb. ubldr should create copy of it in kernel area
and pass pointer to this newly allocated buffer which is guaranteed to work
in kernel after switching on MMU.
- Convert memreserv FDT info to "memreserv" property of root node
FDT uses /memreserve/ data to notify OS about reserved memory areas.
Technically it's not real property, it's just data blob, sequence
of <start, size> pairs where both start and size are 64-bit integers.
It doesn't fit nicely with OF API we use in kernel, so in order to unify
thing ubldr converts this data to "memreserve" property using the same
format for addresses and sizes as /memory node.
The code previously assumed that copyin/copyout did no
address translation and that the device tree blob could
be manipulated in-place (with only a few adjustments for
the ELF loader offset). This isn't possible on all platforms,
so the revised code uses copyout() to copy the device tree
blob into a heap-allocated buffer and then updates the
device tree with copyout(). This isn't ideal, since it
bloats the loader memory usage, but seems the only feasible
approach (short of rewriting all of the fdt manipulation
routines).
Enable using the statically embedded blob from the kernel, if present. The KLD
loaded DTB takes precedence, but they are both recognized and handled in the
same way.
Submitted by: Lukasz Wojcik
Obtained from: Semihalf
MFC after: 1 week
o This is disabled by default for now, and can be enabled using WITH_FDT at
build time.
o Tested with ARM and PowerPC.
Reviewed by: imp
Sponsored by: The FreeBSD Foundation
- add new diag commands: devinfo, sysinfo for U-Boot-style details about the system
configuration
- better memory info summary
- style corrections
Obtained from: Semihalf