U-Boot:
Booting a Linux System Is a Three-Act Play:
Boot loader mainly sets up the groundwork for the board to be able to load the kernel. Just like an opening, the boot loader paves the way for the kernel, going as far to load it from a remote server into memory so it can be executed. After it’s in memory, the boot loader hands execution to the kernel and exits. The kernel then has its own bootstrapping process (which duplicates what the boot loader did in some cases) that readies the hardware, loads drivers, and starts its processes to manage the system. When it’s in a running state, the kernel hands off control to an init program. The kernel and init then share the stage until you shut down the system.
This blog Aims to put everything together i.e U-boot (a bootloader) , kernel and NFS Rootfilesystem to emulate a complete boot procedure on Qemu.
Environment Introduction:
Host ubuntu :- 12.04
Linux kernel version: linux-4.8
busybox version: 1.24.0
Cross compiler tool chain: arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux gnu.tar.bz2
qemu version: qemu-2.5
u-boot: U-Boot 2016.11-00108-gca39bd8
Websites:
QEMU: https://github.com/qemu/qemu
Linux: https://github.com/torvalds/linux
U-boot: http://www.denx.de/wiki/U-Boot/SourceCode
Toolchain: http://sourcery.mentor.com/public/gnu_toolchain/arm-none-linux-gnueabi/
Download and Installation of QEMU: previous blog
ARM Cross_Compiler Tool chain installation: previous blog
Download U-boot source code :
git clone git://git.denx.de/u-boot.git
Prepare for compilation:
Load default config for target board i.e vexpress_ca9x4_defconfig using 1st command and Compile U-boot using 2nd command shown in below .
1.cd u-boot 2.make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- vexpress_ca9x4_defconfig 3.make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
Verify qemu and U-boot cross-compiled properly and can run successfully(test it).
Run below command and Hit any key to stop autoboot.
~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot -nographic
Download Linux kernel source code : Taking latest stable code
$ git clone https://github.com/torvalds/linux $ cd linux $ git checkout -b stable v4.8
Prepare for compilation:
Load default config for target board i.e vexpress_defconfig. defconfig is explained here.
$ cd linux $ make ARCH=arm CROSS_COMPILE=path to your/Binary_images/ARM_Cross_Tools/arm-2014.05/bin/arm-none-linux-gnueabi- vexpress_defconfig e.g CROSS_COMPILE=/Home/vinay/Workspace/Binary_images/ARM_Cross_Tools/arm-2014.05/bin/arm-none-linux-gnueabi-
Run below command to configure some settings :
$ make ARCH=arm CROSS_COMPILE=path to your/Binary_images/ARM_Cross_Tools/arm-2014.05/bin/arm-none-linux-gnueabi- menuconfig
Enable some settings as shown(*use space bar to enable).
Go to :
Boot options —>
[*] Use appended device tree blob to zImage (EXPERIMENTAL)
CONFIG_ARM_APPENDED_DTB:
With this option, the boot code will look for a device tree binary (DTB) appended to zImage
(e.g. cat zImage .dtb > zImage_w_dtb).
[*] Supplement the appended DTB with traditional ATAG information (NEW)
(console=ttyAMA0) Default kernel command string.
CONFIG_ARM_ATAG_DTB_COMPAT:
Some old bootloaders can’t be updated to a DTB capable one, yet they provide ATAGs with memory configuration, the ramdisk address,the kernel cmdline string, etc. Such information is dynamically provided by the bootloader and can’t always be stored in a static DTB. To allow a device tree enabled kernel to be used with such bootloaders, this option allows zImage to extract the information from the ATAG list and store it at run time into the appended DTB.
Kernel hacking —>
[*] Kernel low-level debugging functions (read help!)
CONFIG_DEBUG_LL:
Say Y here to include definitions of printascii, printch, printhex in the kernel. This is helpful if you are debugging code that executes before the console is initialized
Kernel low-level debugging port(Autodetect UART0 onVersatile Express Cortex-A core tiles) —>
(X) Use PL011 UART0 at 0x10009000 (V2P-CA9 core tile)
CONFIG_DEBUG_VEXPRESS_UART0_CA9:
This option selects UART0 at 0x10009000. Except for custom models,this applies only to the V2P-CA9 tile.
[*] Early printk
CONFIG_EARLY_PRINTK:
Say Y here if you want to have an early console using the kernel low-level debugging functions. Add earlyprintk to your kernel parameters to enable this console.
Compile the kernel using below command :
$ make ARCH=arm CROSS_COMPILE=path to your/Binary_images/ARM_Cross_Tools/arm-2014.05/bin/arm-none-linux-gnueabi- all
Once compilation of kernel is completed next step is to Install TFTP Server in Host ubuntu machine. For installation refer this .
Once tftp server is up and starts running, copy the kernel zImage and dtb image to /tftpboot.
$ cp arch/arm/boot/zImage /tftpboot/. $ cp arch/arm/boot/dts/vexpress-v2p-ca9.dtb /tftpboot/.</pre> <pre>$cd /tftpboot</pre> <pre>$ cp zImage kernel $ cat vexpress-v2p-ca9.dtb >> kernel
Start U-BOOT:
Run below command and Hit any key to stop autoboot.
$ sudo ~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -m 512M -serial stdio -net nic -net tap,ifname=tap0 -kernel path to u-boot/u-boot
Once boot loader is up, U-Boot in this you can load a kernel into memory and then run that image. The image loaded into memory can be stored on a server running TFTP.
You configure IP information in U-Boot by setting environment variables to configure the board’s and TFTP server’s address. To set the board’s IP address and the address of the TFTP server use the following commands:
For serverip check you host Ubuntu using ifconfig command
setenv ipaddr <set target ip> e.g:192.168.12.3 setenv serverip <Set host ubuntu ip> e.g 192.168.12.1 setenv netmask 255.255.255.0
The bootargs environment variable controls what kernel command-line parameters are sent during bootup. Setting bootargs works like setting the board’s IP address:
setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0,38400n8'
The device is now configured so that it can communicate over the Ethernet adapter. To download a file from a TFTP server, use the tftpboot command:
tftp 0x62008000 kernel
This loads the kernel into memory at the specified address and starts the booting process.
bootz 0x62008000
The above images shows kernel bootup dmesg in terminal. Due to absence of root file system( rootfs) , Kernel panic – not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
Let’s then create the Minimal Rootfilesystem.
Compiling Busybox for ARM on QEMU : Refer
Follow all the steps from previous blog, Except (don’t follow) this steps.
Create ext3 image file and Copy all the files in our _install folder to image:Skip this step
Copy Busybox filesystem to NFS : Why NFS as RootFileSystem ?
Copy the _install directory that is generated with Busybox build into the NFS share folder:
Populate the root filesystem:
$ cp -a busybox/_install/ /rootfs_ES/. $ sudo chmod 777 / rootfs - R $ sudo chown nobody:nogroup /rootfs_ES/ -R
1. sudo ~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -m 512M -serial stdio -net nic -net tap,ifname=tap0 -kernel u-boot OR 2. sudo ~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -m 512M -nographic -net nic -net tap,ifname=tap0 -kernel u-boot
command 1 will give qemu graphical view where as command 2 with No graphic view.
Set environment variables as instructed above:
setenv ipaddr 192.168.122.3 setenv serverip 192.168.122.1 setenv netmask 255.255.255.0 # Set bootargs option 1 or 2, option 1 redirects dmesg to terminal , option 2 redirects both Host terminal and qemu terminal as shown below image. 1. setenv bootargs 'root=/dev/nfs rw nfsroot=192.168.122.1:/rootfs_ES init=/linuxrc console=ttyAMA0 ip=192.168.122.3' OR 2. setenv bootargs 'root=/dev/nfs rw nfsroot=192.168.122.1:/rootfs_ES init=/linuxrc console=ttyAMA0 console=tty0 ip=192.168.122.3' tftp 0x62008000 kernel bootz 0x62008000
Let me know if you have any questions or comments.
References:
1. Pro Embedded Linux
2. https://balau82.wordpress.com/
Pingback: ARM Versatile Express Emulation On Qemu: From Scratch | LearningFromU
Pingback: ARM Versatile Express Emulation On Qemu From Scratch :Part 2 | LearningFromU
Very useful.
Thanks your post.
LikeLiked by 1 person
Thank you …
LikeLike
Great guide but couldn’t make networking work for the TFTP
Do you use any custom script for the bridging? do you set anything on the tap0 device that is created?
Help would be appreciated!
LikeLiked by 1 person
Thank you george , What issue you facing for TFTP ??
LikeLike
it is probably a problem of firewall on your ubuntu. stop it and then tftp will work
LikeLike
bonjour
Nice share.
In my opinion the most stable iptv servers are those from Fishbone IPTV cloud
I would like to see more posts like this
Thanks
LikeLike