180 likes | 192 Views
Learn how to cross compile a Linux kernel for Raspberry Pi, set up a root filesystem manually, and boot Linux via U-Boot. Step-by-step guide with software and hardware requirements provided.
E N D
Computer System Laboratory Lab3 - OS Kernel + Root Filesystem / 18
Experimental Goal • Cross compile Linux kernel for Raspberry Pi. • Set up a root filesystem for Raspberry Pi. • Boot Linux via U-Boot. / 18
Environment • Host Machine • OS: Windows • Target Machine • Raspberry Pi (2 or 3) • Build Machine • A computer with a SD card slot • OS: Ubuntu 15.10 (or above) 64-bit / 18
Software Required • Host Machine • PL2303 Driver • PuTTY • Build Machine • Linux source code for Raspberry Pi • GCC cross compiler targeting ARM • Debootstrap • You may find all software on the CSL Course Software. / 18
Hardware Checklist • Raspberry Pi • Power supply • Micro SD card and card reader • USB-TTL cable • Network cable / 18
Overview • In previous RPi Lab, we created two partitions (labelled boot and root, respectively) on a SD card, put firmware and U-Boot in the boot partition, and dropped into U-Boot after turning on RPi. • In this Lab, we first cross compile a Linux kernel for RPi. Then, we set up a Linux root filesystem on the root partition manually and put those compiled files into the two partitions. Finally, we use the same setup as previous RPi Lab to launch U-Boot, and configure it to boot Linux. / 18
Cross Compile Linux Kernel • Download and extract the Linux source code managed by Raspberry Pi foundation. • Build it. This may take some time. • % export ARCH=arm • % export CROSS_COMPILE=arm-linux-gnueabihf- • % cd linux-rpi-bootloader-1.20160315-1 • % make clean • % make bcm2709_defconfig • % make # -j<the number of CPU> / 18
Kernel Image and Device Tree Blob • After a successful build, you get the compressed Linux kernel image zImagein arch/arm/boot. We will later configure U-Boot to load this image. • Some hardware information (e.g. the number and type of CPUs) are non-discoverable (i.e. There is no way to run-time detect it). To overcome this problem, this kind of information is manually recorded in a source file called “device tree source” for each platform, and is compiled into a binary format called “device tree blob” after the build. The one we need is bcm2709-rpi-2-b.dtb in arch/arm/boot/dts. We will later configure U-Boot to pass the .dtb to the Linux kernel. / 18
Kernel Modules, Firmware, and Headers • The kernel needs additional kernel modules and firmware to work well. Also, you need Linux headers when you develop kernel module in the system. Prepare these files and we will later put them into the root filesystem. • % mkdir mod • % make modules_install INSTALL_MOD_PATH=./mod • % mkdirfw • % make firmware_install INSTALL_FW_PATH=./fw • % mkdirhdr • % make headers_install INSTALL_HDR_PATH=./hdr / 18
Prepare a Root Filesystem Image • Get required packages. • % sudo apt-get install debootstrap • % sudoapt-get install binfmt-support qemu-user-static • Create a root filesystemimage and mount it. • % dd if=/dev/zero of=rootfs.imgbs=1M count=3072 • % mkfs.ext4 -F -L root rootfs.img • % mkdirrootfs • % sudo mount -o loop rootfs.imgrootfs / 18
Create Files in the Root Filesystem • Create files in the root filesystem via Debootstrap. This may take some time. • % sudodebootstrap --arch=armhf --foreign xenialrootfs • Temporarily use the root filesystem as our root directory. • % sudo mount -t proc proc rootfs/proc • % sudomodprobebinfmt_misc • % sudocp /usr/bin/qemu-arm-static rootfs/usr/bin • % sudochrootrootfs • The username becomes “I have no name!” since the root filesystem is not completely set up, and system configuration files such as /etc/passwddo not exist yet. Start the second stage setup. This may take some time. • % /debootstrap/debootstrap --second-stage / 18
System Configuration • After install the base system, do some system configuration in thechrootenvironment. • Add user “rpi” (password is up to you). Add “rpi” to group “sudo”. • % useradd –m –s /bin/bash rpi • % passwdrpi • % usermod –aGsudorpi • Correct the hostname. • % vi /etc/hostname # replace the original content with “ubuntu”. • % vi /etc/hosts # modify the line “127.0.0.1 localhost” into “127.0.0.1 localhost ubuntu”. • Configure the network. • % vi /etc/network/interfaces # replace the original content with the following lines. • auto lo • iface lo inet loopback • auto eth0 • iface eth0 inetdhcp / 18
Write the Root Filesystem to the SD card • After finishing the above system configuration, exit from chroot and unmount the root filesystem image. • % exit • % sudoumountrootfs/proc • % sudoumountrootfs • Insert the SD card. Find the device name of the 2nd partition (/dev/sdc2 in my case). • % lsblk • Write the root filesystem image to the 2nd partition. This may take some time. • % sudoumount /dev/sdc2 • % sudoddbs=4M if=rootfs.img of=/dev/sdc2 / 18
Copy the Compiled Files to the SD card • Mount the two partition of the SD card and find their path. (In my case, they are /media/<username>/boot and /media/<username>/root, which are mounted by the GUI file manager.) • Copy the kernel image and the device tree blob to the 1st partition. • % sudocparch/arm/boot/zImage/media/<username>/boot • % sudorm/media/<username>/boot/bcm2709-rpi-2-b.dtb • % sudocp arch/arm/boot/dts/bcm2709-rpi-2-b.dtb /media/<username>/boot • Copy the kernel modules, firmware, and headers to the 2nd partition. • % sudocp -r mod/lib/modules /media/<username>/root/lib/modules • % sudocp -r fw/media/<username>/root/lib/firmware • % sudocp -r hdr/include/* /media/<username>/root/usr/include • Safely eject the SD card. Now you are ready to boot your Linux! / 18
Set U-Boot Environment Variables • Insert the SD card to RPi. Plug the USB-TTL cable between RPi and the host machine. Plug the network cable between RPi and LAN. Launch Putty in the host machine with the correct serial options. Plug the RPi power supply to turn on RPi and hit any key in two second to drop into U-Boot command line. (All the same as Lab 2 except the network cable.) • Tell U-Boot how to boot the Linux kernel. • u-boot$ setenvbootcmd_kernel "fatload mmc 0:1 ${kernel_addr_r} zImage" • u-boot$ setenvbootcmd_fdt "fatload mmc 0:1 ${fdt_addr_r} bcm2709-rpi-2-b.dtb" • u-boot$ setenvbootcmd "${bootcmd_kernel}; ${bootcmd_fdt}; bootz ${kernel_addr_r} - ${fdt_addr_r};" • Tell U-Boot what boot arguments should be pass to the Linux kernel. • u-boot$ setenvbootargs "earlyprintk console=tty0 console=ttyAMA0 root=/dev/mmcblk0p2 rootfstype=ext4 rwrootwaitnoinitrd" • If the commands you copy-and-paste do not match those executed by U-Boot, you will have to type them yourself rather than copy-and-paste them. / 18
Boot Successfully • Check the environment variables you set, and save them to uboot.env. • u-boot$ printenv • u-boot$ saveenv • Reset U-Boot and this time just let it perform autoboot. If you see Linux waiting for you to log in, congratulations! • u-boot$reset / 18
Lab Requirement • Install gcc and write a “Hello, world!” program. • $ sudo apt-get update • $ sudo apt-get install gcc • $ vi hello.c • $ gcc –o hello hello.c • $ ./hello / 18
Reference • Kernel building - Raspberry Pi Documentation • Device Tree - eLinux.org • Building own Debian image for Raspberry Pi • RPiU-Boot - eLinux.org / 18