In My previous Tutorial ARM Versatile Express Emulation On Qemu From Scratch :Part 1 i have explained how to setup Embedded Linux Setup using Qemu, Cross-compiling Linux source code for ARM target , Cross_compiling Compiling Busybox-based Rootfile system.
In this tutorial will explore more on compiling BusyBox dynamically and Need for Mounting the root filesystem via NFS which i have already explained here NFS.
Host ubuntu :- 14.04
Linux kernel version: linux :-4.9.0
busybox version: busybox :-1.25.0
Cross compiler tool chain:arm :-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux gnu.tar.bz2
qemu version :- qemu-2.7.0
1.Download and Installation of QEMU:
2.ARM Cross_Compiler Tool chain installation:
For above 1 and 2 refer the procedure from Previous tutorial .
3.Download Linux kernel source code : Refer for compilation instruction from this Post.
4.Compiling Busybox for ARM on QEMU : compilation instruction are similar as the previous one .
cd busybox $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- defconfig $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- menuconfig
In previous tutorial i enabled Build BusyBox as a static binary.
Busybox Settings —> Build Options —>
[*] Build BusyBox as a static binary (no shared libs).
As i told in my previous tutorial here i will explain why Static or Shared?
Under the BusyBox Settings/Build Options menu is the option “Build BusyBox as a static binary.” This is false by default, resulting in the BusyBox file being linked with shared libraries. Thus the final BusyBox binary is much smaller because a large chunk of the code resides in another file: the C standard library used when compiling the software that must also be present on the final root file system. When you’re using a shared library, the operating system performs the final link at runtime by loading both the executable and shared library and fixing the references in the program to run code in the shared library.
When statically linked, all the code the program uses resides in the file. The code is loaded into memory and executed. This is a much faster operation than loading a file with shared libraries, in exchange for a larger memory footprint, because a fresh copy of the code is loaded for each instance of BusyBox executed. If the BusyBox executable contains just a few executables, the rule of thumb is about a 200KB program size. Static linking then makes sense because of the increased performance and savings from not needing the shared libraries.
Onward we will stick to Dynamic and shared library which will simplify while adding and executing user level application on target without much worry about shared and dynamic libraries. Don’t Enable this below option.
[ ] Build BusyBox as a static binary (no shared libs).
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- install
Next, you need to create folder for mounting Virtual file systems like proc, sys and init scripts.
$ mkdir -p _install/proc/ $ mkdir -p _install/sys/ $ mkdir -p _install/tmp/ $ mkdir -p _install/root/ $ mkdir -p _install/var/ $ mkdir -p _install/mnt/ $ mkdir -p _install/dev/ $ mkdir -p _install/Home/ $ mkdir -p _install/lib/ $ mkdir -p _install/etc/init.d/
Download below files from github and copy to rootfs.
$ git clone https://github.com/mahadevvinay/Embedded_Linux_Files.git 1. copy fstab to _install/etc/ 2. copy inittab to _install/etc/ 3. copy rcS to _install/etc/init.d/
Once above file created and added change the permission of rcS file.
$ chmod a+x _install/etc/init.d/rcS $ chmod 777 _install/etc/init.d/rcS
When BusyBox was built with shared libraries, you need to copy them into the root file system and place them into the /lib directory. These files can be copied from the sysroot directory of the toolchain. BusyBox links against the m and c libraries.
Copy all the library files
$ cp -a arm-2014.05/arm-none-linux-gnueabi/libc/lib/* _install/lib/.
Create ext3 image file and Copy all the files in our _install folder to image: Skip this Step
Instead of creating ext3 image we will stick to NFS . The nfs is explained here Network File System protocol .
Create a directory NFS_rootfs under /.
$ mkdir /NFS_rootfs $ chown 1000:1000 /NFS_rootfs $ cp -a busybox-1.25.0/_install/* /NFS_rootfs
Edit the file /etc/exports adding the following line in host machine:
$ sudo vi /etc/exports /NFS_rootfs 127.0.0.1(rw,sync,no_subtree_check,no_root_squash,insecure)
Verify the nfs mounts properly by below commands
$ sudo exportfs -av $ mkdir ~/nfs $ mount localhost:/NFS_rootfs ~/nfs # check rootfs mounted under /nfs and the unmount it $ umount ~/nfs
QEMU offers a network model that allows to access the host as thought it was connected with an Ethernet network. The details of the default connection can be found in the documentation; briefly, a virtual LAN is created where the guest virtual system is given address 10.0.2.15 while the host workstation can be accessed using address 10.0.2.2.
Yes finally we are at last stage of booting Linux with nfs as rootfs.
qemu-system-arm -M vexpress-a9 -dtb linux/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel linux/arch/arm/boot/zImage -append "root=/dev/nfs nfsroot=10.0.2.2:/NFS_rootfs rw ip=10.0.2.15::10.0.2.1:255.255.255.0 init=/linuxrc console=ttyAMA0" -serial stdio
Let me know if you have any questions or comments.
1)Pro Embedded Linux
2)Embedded Linux Primer