Some details on ARM Linux boot

2.3k views Asked by At

I'm trying to understand the details of linux booting on arm architecture. I did lot of search on the internet and understood so far some details although I feel each time I read an article it brings lot of other new terms and this makes things more complex. I do have 2 boards running linux, an olimex 9261 and a beaglebone black. My expertise in embedded systems especially arm is pretty good, but didn't play too much with linux though (except some user space programs and char drivers in kernel).

Here are my questions:

One one board I have the following uboot output (linux 2.6.30):

 bootargs=mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2
 bootcmd= cp.b 0xC0042000 0x22000000 0x00199954; bootm 0x22000000

The board has 64MB RAM (mapped at 0x20000000), 512MB nand flash(didn't find mapping so far) and 2MB data flash (mapped at 0xc0000000).

What I don't understand here:

  • why there is a mem=64 in the bootargs? Isn't this supposed to be given as ATAG or DTB ?
  • why is there a console given as argument when we pass the control to kernel? Is the kernel using the tty already configured by uboot?
  • initrd vs rootfs. This is still not clear to me. I know initrd can be included in kernel as a block device or a separate image for which uboot has to pass address details to kernel (true?). Can we have a kernel without an initrd included + another file system, like this jffs2, from which the kernel will run rest of drivers? Actually I'm not able to understand full details of the file system used by kernel at boot. In this setup I have, there are 4 files: uImage, bootstrap, env.bin and jffs2 file system. So there is no initrd. How is this working? And how is the process of rooting the file system pointed in the above bootargs? In my understanding, the kernel should access first the jffs2 file system, then grab the image found in /dev/mtdblock1 and mount it. Perhaps my understanding is wrong. Actually this interaction between kernel and file system is what I seem not to understand. In the above bootcmd, the kernel is copied from nand to sdram then bootm jumps to it. But how does the kernel find the jffs at booting time? I see this output line during boot: VFS: Mounted root (jffs2 filesystem) on device 31:1.

In the board user guide I found this:

WARNING: Due to AT91SAM9261 chip errata booting from NAND flash is not supported.

...

512MB NAND Flash (seen in Linux as silicon drive).

  • After compiling the kernel, I observed the System.map doesn't have all symbols. I checked the vmlinux and it's the same. Does anyone know why? Maybe the compiler was not configured properly?

Many thanks, Daniel.

2

There are 2 answers

4
artless noise On

Most of your questions can be answered by reading the Documentation that comes with your Linux source. Some key files are,

  • kernel-parameters.txt
  • arm/booting.txt

Please take a look through them as they will have information current to your version of Linux.


One one board I have the following uboot output (linux 2.6.30):

The 2.6.30 kernel pre-dates device trees for the ARM.

why there is a mem=64 in the bootargs? Isn't this supposed to be given as ATAG or DTB ?

There are two mechanisms. The ATAGS is more flexible as it can specify several non-contiguous banks of memory. The idea is that boot code can probe the memory and provide it via ATAGS. That is the theory. It is often tough to do, so allowing a user to specify mem=64 is a lot easier to implement. If there are two board types, one with 64MB and one with 128MB, it is up to the user to provide a command line to use the extra memory.

why is there a console given as argument when we pass the control to kernel? Is the kernel using the tty already configured by uboot?

Some devices have multiple serial ports. Some kernels may wish to use the 'u-boot' port for something else. HDSPA modem, printer, etc. The Linux kernel and the u-boot consoles may be different. That is a feature. I often use /dev/null as the console. Hardware is often stingy to give an extra serial port. Maybe you are lucky and your hardware people don't think software is free.

initrd vs rootfs.

You may boot directly to a file system (rootfs), but all of the code and mechanisms for finding the code must be inside the Linux image. Even if they are (JFFS2/NAND), you may end up with a corrupt rootfs as NAND wears. The first 128MB of NAND is usually a higher quality. You may put a Linux with initrd here that is capable of repair of the main file system. For other boot devices, it may not be straight forward to boot the device and complex decisions can be made in an initrd image. Often the initrd take far less time to mount and you may perform some actions more quickly. Finally, you may load different modules and then lock module loading in the initrd.

You may use the rootfs directly. It is simpler to implement. The initrd is much more flexible and powerful. You may wish to transition from JFFS2 to Ubi/UbiFS. If you don't have an initrd, then this is pretty much impossible (at least much more difficult to implement).

In this setup I have, there are 4 files: uImage, bootstrap, env.bin and jffs2 file system. So there is no initrd.

The uImage may have an initrd attached to it. It is mounted as a ramdisk and after it unmounts (and switch_root to the new/final rootfs) the memory is free to use. However, your command line has no initrd info, so you probably don't have one.

In my understanding, the kernel should access first the jffs2 file system, then grab the image found in /dev/mtdblock1 and mount it. Perhaps my understanding is wrong. Actually this interaction between kernel and file system is what I seem not to understand. In the above bootcmd, the kernel is copied from nand to sdram then bootm jumps to it. But how does the kernel find the jffs at booting time? I see this output line during boot: VFS: Mounted root (jffs2 filesystem) on device 31:1.

You have information to find the device; root=/dev/mtdblock1 and you told it the file system type; rootfstype=jffs2. The missing piece is the init=/sbin/init. You can read about it in the kernel-parameters.txt for your Linux. After the JFFS2 is mounted, the init code looks for a process to run. It is the parent process of everything and it will start to execute many different processes. Typically it is init, but you can specify init=/bin/sh and you will just have a shell to start with. This can be a good way to develop an initrd image as you can test scripts with only one process running.

After compiling the kernel, I observed the System.map doesn't have all symbols. I checked the vmlinux and it's the same. Does anyone know why? Maybe the compiler was not configured properly?

The System.map is really only external functions and data. It does not include every function. In fact some functions may not exist due to in-lining.

WARNING: Due to AT91SAM9261 chip errata booting from NAND flash is not supported.

I guess it is u-boot's job to handle this.

1
domen On
  • mem=64 - I assume this might be needed before device tree can be loaded. Maybe not.
  • tty - but how could the kernel know which tty was configured by bootloader? There has to be some configuration, either passed to, compiled in, or just a default setting.
  • initrd (or initramfs) vs. nothing - initrd is just a very small userspace that can ie. prompt for decryption password, wait for USB device with rootfs to be plugged in, or something else. Things could work without, just be sure to then compile in all the necessary modules to boot from rootfs. If I recall correctly, a few years ago initramfs was introduced as initrd replacement. It is a CPIO archive packed inside the kernel and it might be what you're seeing when there's "no initrd"