The use of ARM processors is widespread in mobile phones, with around 80 per cent of today’s mobiles having at least one ARM processor. The ARM environment can also be created in Linux machines through a virtual machine using chroot, QEMU and Linaro. Let’s see how…
If you want to get your hands on ARM architecture or are interested in debugging ARM code, then you probably would be wondering how you could create an ARM environment (or use the ARM toolset) inside an Intel x86 or x64 architecture. This article will explain how this can be achieved by using QEMU, chroot and Linaro.
Almost 80 per cent of all mobile devices we use today have at least one ARM processor as part of the hardware. The ARM processor is a CPU built on the RISC-based architecture developed by Acorn Computers in the 1980s, and is now developed by Advanced RISC Machines (thus ARM).
The use of the ARM processor is very widespread and is not limited to mobile devices. It is also being heavily used as a processor for smart TVs, set-top boxes, IoT devices and most other embedded devices. If you develop applications for an ARM architecture-supporting OS or are learning ARM architecture fundamentals, the chances are that you will want to create a virtual environment of the ARM processor on your Linux system which is probably running on an Intel x86/x64 processor. Learning or being familiar with ARM is a great investment in your future; so without wasting more time, let’s get started.
Creating a chroot environment for ARM
In general, chroot is only capable of creating virtual environments of the same architecture distributions. For example, you can only create a Debian x86 system inside the x86 host system. So, to successfully create an ARM system, we need to use QEMU, which is capable of providing successful emulation for a number of ARM platforms.
Note: I am using Ubuntu 17.10(x64) as my host system. But all the steps remain the same for any other distro or architecture.
Installing the required packages
As mentioned earlier, we need to use QEMU for creating a cross-platform chroot environment. You can install QEMU and some other required packages using the following command:
$ apt-get install binfmt-support qemu qemu-user-static
binfmt-support is a kernel module that will help us execute the binary packages of the ARM architecture. If you want to be able to cross-compile packages using your host computer to build code that will run on the simulator, you’ll need to install the GCC packages, as follows:
$ sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
Downloading the base ARM system
First, you need to install debootstrap for downloading the Debian ARM system, as follows:
$ apt-get install debootstrap
Now download the minimal Debian ARM system. You will need root permission to download the system using debootstrap.
$ qemu-debootstrap --arch armel stretch armDebian http://deb.debian.org/debian/
Here, armDebian is the directory inside which you need to install the system and stretch is the Debian flavour you have to use. It may take a little time to download and configure the system with the above command but once complete, you can start chrooting inside it.
Starting chroot
Before chrooting inside armDebian you need to mount a few things inside that environment to make it work properly. It’s better to put those commands on a script so that every time you want to chroot, you can just run the script.
#!/bin/bash mount --bind /dev/ /home/0day/armDebian/dev mount --bind /dev/pts /home/0day/armDebian/dev/pts mount --bind /dev/shm /home/0day/armDebian/dev/shm mount -t sysfs sysfs /home/0day/armDebian/sys mount -t proc proc /home/0day/armDebian/proc cp -L /etc/resolv.conf /home/0day/armDebian/etc/resolv.conf chroot /home/0day/armDebian
Once you have created this script, just change its permissions and run it using the following commands:
$ chmod +x runArm.sh $ sudo ./runArm.sh
Here, runArm.sh is the name of the script. Now you are inside a minimal ARM based system. The first thing that you should do inside the system is to update and install the few required packages like gdb, Python, etc.
ARM systems don’t require BIOS for their functionality since the bootloader is directly installed on hardware. They have U-boot installed as their bootloader. If you want to play around with U-boot or want a full ARM environment, then you cannot do that in chroot. For that, you need to install it inside a full virtual environment like QEMU to get the booting process. We will look into how to do that using the Linaro toolchain next.
Setting up an ARM VM using Linaro
We can use the Linaro tool to set up an ARM VM and save ourselves from chroot and cross-compilation work. For this method, too, you need to install QEMU and the other required packages, as follows:
$sudo apt-get install qemu qemu-system qemu-system-arm
Add Linaro’s repository, containing its tools and a more recent version of QEMU. After that, install the Linaro image-tools, as follows:
$ sudo add apt-repository ppa:linaro-maintainers/tools $ sudo apt-get install linaro-image-tools
For cross-compile support, again use the following command:
$ sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
Downloading and configuring the packages
Now, let’s download the Linaro release and hardware pack to run the VM:
$ wget https://releases.linaro.org/platform/linaro-n/nano/alpha-3/linaro-natty-nano-tar-20110302-0.tar.gz $ wget https://releases.linaro.org/platform/linaro-n/hwpacks/alpha-3/hwpack_linaro-vexpress_20110302-0_armel_supported.tar.gz Create the image using previously instlled linaro-image-tools $ linaro-media-create --rootfs ext2 --image_file vexpress.img --dev vexpress \ --binary linaro-natty-nano-tar-20110302-0.tar.gz \ --hwpack hwpack_linaro-vexpress_20110302-0_armel_supported.tar.gz
Booting up the VM
Now extract the kernel and initrd using the following command (you can also do that manually):
$ (IMG=vexpress.img ; if [ -e “$IMG” ] ; then sudo mount -o loop,offset=”$(file “$IMG” | awk ‘BEGIN { RS=”;”; } /partition 2/ { print $7*512; }’)” -t auto “$IMG” /mnt/mnt; else echo “$IMG not found”; fi )
Copy boot for booting the VM:
$ sudo cp -vr /mnt/mnt/boot . $ sudo chown -R youruser:youruser boot $ sudo umount /mnt/mnt
You will end up with a number of images in .boot:
abi-3.3.0-1800-linaro-lt-vexpress-a9 config-3.3.0-1800-linaro-lt-vexpress-a9 initrd.img-3.3.0-1800-linaro-lt-vexpress-a9 System.map-3.3.0-1800-linaro-lt-vexpress-a9 vmlinuz-3.3.0-1800-linaro-lt-vexpress-a9
Copy the original VExpress images, vmlinuz.* and initrd.*, somewhere where you plan to keep your VM.
Now run the image using QEMU:
$ qemu-system-arm -kernel vmlinuz-3.3.0-1800-linaro-lt-vexpress-a9 -M vexpress-a9 -cpu cortex-a9 -serial stdio -m 1024 -initrd initrd.img-3.3.0-1800-linaro-lt-vexpress-a9 -append ‘root=/dev/mmcblk0p2 rw mem=1024M raid=noautodetect console=tty1 rootwait vmalloc=256MB devtmpfs.mount=0’ -redir tcp:5022::22 -sd vexpress.img
This will open the window where your ARM based VM is booting, like any other normal operating system.
- -redir tcp:2200::22 redirects TCP traffic on the host port 2200 to the guest machine’s (QEMU) Port 22. This will allow us to SSH into the machine later by connecting to localhost on Port 2200.
- -m 512 specifies that we want 512MB of RAM. You can adjust this, but make sure you also change it in the ‘-append’ string.
- -drive file=vexpress.img,if=sd,cache=writeback attaches the images as an SD card. According to people at Linaro, this method provides faster I/O compared to the traditional -sd option.
After starting the machine, you should end up with a Linux shell in the QEMU window after some startup time.
Installing the required packages inside the VM
You now need to configure the VM for your general use. First install some common packages, as follows:
$apt-get update $ apt-get install binutils gcc gdb build-essential vim openssh-server
You can also connect to this VM using ssh in future. For that, start the ssh service and set the root password using the passwd command.
Our complete virtual environment is now ready. You can use it in the same way you use any other Linux distro for development or general purposes.