Zynq Linux Kernel Load address - linux

I want to build linux for zed board. When I look into zynq-common.h file in u-boot/include/configs directory, I see that kernel_load_address is 0x02080000.
Why kernel load address is 0x02080000?
What is the logic of it?
I am using version 2018.01.
Value that I mentioned is "kernel_load_address=0x2080000" in CONFIG_EXTRA_ENV_SETTINGS

I don't think that's the actual load address. UBoot should load it to 0x8000 by default. It could be modified, but you arn't going to want to do that through the header files.
(You shouldn't need to be looking at those files, especially not modifying them.)
If you want to build the kernel for the zedboard, I reccomend following either of these guides:
https://wiki.analog.com/resources/eval/user-guides/ad-fmcomms2-ebz/software/linux/zynq_2014r2
https://highlevel-synthesis.com/2016/10/31/how-to-compile-xilinx-linux-kernel-for-zynq/
You will also need the toolchains from Xilinx if you don't want to build the kernel on platform which will take 4-6 or more hours (I have had to do it before, not fun).

Value that I mentioned is "kernel_load_address=0x2080000" in CONFIG_EXTRA_ENV_SETTINGS
That particular environment variable is not the mainline version of U-Boot. So apparently you are using a custom version.
The use of that env variable is likely to locate the kernel image with an input command in main memory. Since this is an ARM board the kernel image would be a zImage or uImage (which would contain a zImage).
The zImage is capable of uncompressing itself and relocating the kernel image to its proper load address for actual execution.
That final load address is typically the start of physical memory plus 0x8000. See Building kernel uImage using LOADADDR
Since the kernel will be relocated during decompression, this intermediate memory address used by U-boot for reading in the compressed kernel image is not crucial. The uncompression code attached to the zImage is position independent, so loading the zImage into memory is flexible. As long as the zImage resides in memory higher than the kernel's actual loadaddress, there is no issue (i.e. an extra relocation).

Related

Buildroot doesn't generate compressed Kernel image

I've successfully used buildroot (v. 2019.05) to built u-boot and Kernel and was able to boot it together.
The problem is that, even though I selected Kernel compression mode to gzip, all I get is the uncompressed Image file.
In the output directory (and Linux as well) there is only Image file, while there should be Image.gz.
How to generate Image.gz from / instead of Image?
On arm64, Linux does not support self-extracting compression. It relies on the boot loader to do that.
The Linux build system does have an Image.gz (and Image.bz2 etc.) target, but it does nothing more than calling gzip on Image (compare this with zImage, which adds a self-extractor).
Since it is easy to do the compression outside of the kernel build system, and since there are so many different compressors possible, Buildroot doesn't provide options for them. However, it is possible to select a custom image name (BR2_LINUX_KERNEL_IMAGE_TARGET_CUSTOM) and then set BR2_LINUX_KERNEL_IMAGE_TARGET_NAME to Image.gz. Alternatively, you can do the compression in a post-build script.
Remember to make sure that the bootloader is able to decompress with that algorithm.
According to the Linux package configuration tool:
This selection will just ensure that the correct host tools are built.
The actual compression for the kernel should be selected in the kernel
configuration menu.
Make sure you select the compression option using make linux-menuconfig too.
In buildroot, besides selecting the compression mechanism you can also select the output format for the kernel image (uImage, zImage, vmlinux ...).
You should find on of those in your output/images/ or in the build directory of your kernel.
When using U-boot you probably want to use the uImage or the zImage. See this question. Both of them will be compressed if selected in the kernel configuration (CONFIG_KERNEL_GZIP).
During boot the uncompressed size of the kernel is logged in the beginning. You can compare it to the size on your filesystem.
## Booting kernel from Legacy Image at 10000000 ...
Image Name: Linux-4.14.73-ltsi
Created: 2019-05-14 11:55:16 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 4684016 Bytes = 4.5 MiB
Load Address: 00008000
Entry Point: 00008000
...

How to load device tree overlay on kernel 3.19+

Kernel 3.19 (re-)introduced Device Tree Overlays. I am on Linux kernel 3.19.4, via Fedora (3.19.4-200.fc21.armv7hl).
I have an overlay file overlay.dts as described in the documentation.
overlay.c contains functions to work with overlays, including to functions to load an overlay.
Does the kernel check any paths for overlays to load? If so, where? If not, how can I load my overlay?
From my experience (3.8-3.14), DTB loading is actually the jurisdiction of the boot-loader, rather than the kernel itself. I've used u-boot for this - u-boot can load the compiled device-tree file (man dtc) from an EXT2-based filesystem to a known location in RAM, which is then specified in the kernel command line.
Which boot-loader are you using?

Why is the bulk of the kernel image only ~1.5MB in RAM after loaded?

According to this picture from The Kernel Boot Process:
The bulk of the kernel image is only ~1.5MB. I thought the kernel image should be a fairy large binary image file in order to support the hardware (or is this kernel module?) and various kernel functions, since the source is pretty large. Also, where's the initrd?
First the kernel is compressed. Then in most desktop environment, the kernel is built with a minimal set of statically linked modules. The initrd image is loaded from the hard drive, from the /boot folder (see your grub configuration) and is used to detect your desktop hardware to load the appropriate modules, to be able to mount a root file system. The initrd image contains this sets of modules. Imagine a RAID, LVM or an exotic file system that cannot be recognized by the bootloader. This is why the boot partition is most of time in ext2/3/(4?). Then when the right modules are loaded, the root file system is swapped from initrd image with the one on the hard drive (pivot_root). Then the rest of the hardware modules are loaded from the "none initrd" filesystem, mostly with the help of udev.
Hope this helps!
P.S. Correct me if I'm wrong!

loading u-Boot in memory instead of flashing it

In my ARM based custom board, I flash u-boot to NAND whenever I do changes on that. (putting some debug statements/modification). Is there any way to directly load the uboot image in RAM memory instead of flashing it every time?
For linux kernel image I do load it in memory and use bootm to boot that image. Similarly for u-boot I am trying out. Kindly provide your suggestions.
Someone at Freescale has done this, for their P1022DS evaluation system (and some others as well). They have provided a somewhat useful document about the process in the file ${UBOOTROOT}/doc/README.ramboot-ppc8500 (in U-Boot V2010.12). This document is pretty terse and leaves many questions unanswered, but I found it a reasonable place to start when I needed to debug U-Boot for a new board, before the flash memory for that board was operating correctly.
In fact, having non-functional flash memory is one reason you might want to debug U-Boot in RAM. (There are a few reasons listed in the README, and they all sound pretty reasonable to me, in contrast to some of the other advice available on this subject)
In our situation, it was found that early prototype target board hardware included an error in the address bus connection to the flash memory that prevented us from using that flash memory. While the hardware was being redesigned and re-fabricated, we wanted to continue testing/debugging those parts of our U-Boot configuration that did not depend on flash memory, for example, I2C, Ethernet, FPGA configuration, PCIe, etc. (there are plenty of things that are independent of where the U-Boot image comes from).
Running U-Boot after loading it into RAM via a JTAG interface (using Codewarrior and the USB TAP) allowed us to continue our U-Boot bring-up tasks, even though we had no functional flash memory. Once we received a newer version of the target board with correctly functioning flash memory, we returned to debugging those parts of U-Boot that we hadn't been able to test earlier. After that, U-Boot was fully functional, and we did not have to wait for a board spin to make any progress.
Debugging a bootloader is a bit difficult, but with the right tools it should be relatively painless.
I deal with the PowerPC achitecture and with a BDI-3000 I can load and debug directly to RAM (of course, after initializing the DDR controller).
One option is if you have on-chip SRAM or L2 Cache that can be configured as on-chip SRAM. The BDI can copy to the SRAM area first, u-boot does it's thing (initialize DDR controller for example), then relocates itself to DDR RAM afterwards. Definitely faster that re-writing to slow Flash all the time.
It wasn't possible in 2004, at least.
It should be possible, if the U-Boot image you want to run has startup code that allows running it from arbitrary addresses. Whether or not that is the case for your board I can't tell.
If the startup code begins by copying the code section from the current (PC-relative) address to the final execution address (usually this is preceded by a check that these areas don't overlap), then you can load the .bin file to any address in RAM, and invoke it using go.
The second obstacle I could see would be unconditional RAM setup code at the beginning, which a number of boards have.
This is what can be read on the u-boot documentation FAQ:
Question:
I don't want to erase my flash memory because I'm not sure if my new U-Boot image will work. Is it possible to configure U-Boot such
that I can load it into RAM instead of flash, and start it from my old
boot loader?
Answer:
No. (Unless you're using a Blackfin processor, or Socfpga board, but you probably aren't.)
Question:
But I've been told it is possible??
Answer:
Well, yes. Of course this is possible. This is software, so everything is possible. But it is difficult, unsupported, and fraught
with peril. You are on your own if you choose to do it. And it will
not help you to solve your problem.
source:http://www.denx.de/wiki/view/DULG/CanUBootBeConfiguredSuchThatItCanBeStartedInRAM
The problem here is that what you are trying to do goes against the philosophy of what a bootloader is. Most processors require that code starts from Flash. That code is called a bootloader. That is what U-boot is.
However, if you want to modify U-boot so that it is not a true bootloader, then you can do whatever you want. It's just software. But don't expect any mainline support for the above reasons.
Just take in mind (be care of) the hardware that you are configuring in your modified U-Boot. U
Boot is intended to initialize critical modules, some of them are not able to be re-configured on the fly or they may not performe as if they were initialized/configured at startup.
If your Target board support network booting, you can load uboot image from host machine to RAM through network.
You can use usb boot. TI and Freescale provides their usb boot utilities. I don't know about other vendors.
Yes, It is possible most of the compilation structure at the end U-Boot provides a u-boot.bin file which is a flattened binary, if your target supports USB/TFTP or any other medium which current U-boot can detect on you target environment then we can load the u-boot.bin file to the static memory address area. This address is the entry point of U-Boot Code and U-boot can execute the flattened binaries by go 0x<memory_address>. The static memory address area can be deduced form u-boot.map file, This entry point is basically address to the .text area of compiled program usually can we searched in the .map file with string "Address of section .text set to 0x." Below is the example of doing it from USB.
usb start
load usb 0x<memory_address> u-boot.bin
go 0x<memory_address>
This should run you U-Boot from usb with out disturbing current code.

Arguments to kernel

Is there anything that the kernel need to get from the boot loader.Usually the kernel is capable of bringing up a system from scratch, so why does it require anything from boot-loader?
I have seen boot messages from kernel like this.
"Fetching vars from bootloader... OK"
So what exactly are the variables being passed?
Also how are the variables being passed from the boot-loader? Is it through stack?
The kernel accept so called command-line options, that are text based. This is very useful, because you can do a lot of thing without having to recompile your kernel. As for the argument passing, it is architecture dependent. On ARM it is done through a pointer to a location in memory, or a fixed location in memory.
Here is how it is done on ARM.
Usually a kernel is not capable of booting the machine from scratch. May be from the bios, but then it is not from scratch. It needs some initialisation, this is the job of the bootloader.
There are some parametres that the Linux kernel accepts from the bootloader, of which what I can remember now is the vga parametre. For example:
kernel /vmlinuz-2.6.30 root=/dev/disk/by-uuid/3999cb7d-8e1e-4daf-9cce-3f49a02b00f2 ro vga=0x318
Have a look at 10 boot time parameters you should know about the Linux kernel which explains some of the common parametres.
For the Linux kernel, there are several things the bootloader has to tell the kernel. It includes things like the kernel command line (as several other people already mentioned), where in the memory the initrd has been loaded and its size, if an initrd is being used (the kernel cannot load it by itself; often when using an initrd, the modules needed to acess storage devices are within the initrd, and it can also have to do some quite complex setup before being able to access the storage), and several assorted odds and ends.
See Documentation/x86/boot.txt (link to 2.6.30's version) for more detail for the traditional x86 architecture (both 32-bit and 64-bit), including how these variables are passed to the kernel setup code.
The bootloader doesn't use a stack to pass arguments to the kernel. At least in the case of Linux, there is a rather complex memory structure that the bootloader fills in that the kernel knows how to parse. This is how the bootloader points the kernel to its command line. See Documentaion/x86/boot.txt for more info.
Linux accepts variables from the boot loader to allow certain options to be used. I know that one of the things you can do is make it so that you don't have to log-in (recovery mode) and there are several other options. It mainly just allows fixes to be done if there's an issue with something or for password changing. This is how the Ubuntu Live-CD boots Linux if you select to use another option.
Normally the parameters called command line parameters, which is passed to kernel module from boot loader. Bootloader use many of the BIOS interrupts to detect,
memory
HDD
Processor
Keyboard
Screen
Mouse
ETC...
and all harwares details are going to be detected at boot time, that is in real mode, then pass this parameters to Kernel.

Resources