📜 ⬆️ ⬇️

Debian's RISC under QEMU


For embedded systems based on MIPS and ARM architectures, specialized GNU / Linux distribution generators are often used: buildroot, openwrt, and other Yocto.
But sometimes it is interesting to run a universal Debian OS on such a system. Installing Debian on a computer with an x86 / amd64 architecture processor is simple, but with embedded systems, believe me, everything is not so simple ...
In this publication, I will tell you how to install using debootstrap, and then how to use Debian for running a Debian operating system for computers with MIPS and ARM processors using QEMU.


Introduction


GNU / Linux operating systems most often consist of at least two components: the OS kernel (kernel) and the user programs (userspace). The Linux kernel (yes, yes, this is exactly the kernel called Linux!) Directly interacts with the hardware and provides user programs access to computer hardware resources using abstract interfaces.
While the kernel is strongly tied to a specific SoC family or even to a specific board, user applications are much more “loose” components; their executable files are tied only to a specific version of the processor command system (for example, MIPS-I or MIPS32r2), and to the version of the kernel programming interfaces.
This state of affairs turns out to be the following: it becomes possible to run the same applications on completely different SoCs, on completely different boards, the main thing is to ensure that the program interfaces of the kernel are the same.
Such a “lag” of applications can be very useful in practice. For example, the Raspbian and QEMU publication describes the launch of the Raspbian OS for the Raspberry Pi on an ARM Versatile card emulated with QEMU.

Action plan


From the above, it is clear that to run Debian on an emulated MIPS (or ARM) board we need:

We will build the Linux kernel using cross-development tools on our own, and we will entrust the creation of an image of the root file system of Debian to the debootstrap program.
We will use a computer with an x86_64 processor running the Debian Linux testing version as an instrumental computer (a computer on which we will cross-compile and run the QEMU emulator).
Why choose Debian testing?
Because out-of-the-box Debian testing supports a comparatively recent version of QEMU and cross-compilers for both MIPS and ARM.

All actions to build the kernel and form an image of the root file system are performed from the command line, do not require operator intervention, and can easily be placed inside a script.
Commands to be executed as root are preceded by a # character, commands that do not need superuser privileges are preceded by a $ character.
For example:

How to quickly build the required tool computer?
The required tool computer is easy to build with virtualization software (VMWare, VirtualBox or QEMU / KVM).
For this:
  • Download the debian-8.3.0-amd64-netinst.iso network installation disk image ,
  • Create a virtual computer with the following minimum parameters: RAM: 1 GB, HDD: 8 GB; connect the Debian installation boot disk to the virtual computer;
  • start the virtual computer with the download of the Debian installer from the installation disk;
  • Install the Debian virtual computer OS on an almost minimal configuration (for example, to launch QEMU there is no need to install the components of a web server and a graphical user interface):


  • Download the newly installed Debian OS, and log in as root;
  • enable the ability to install Debian packages of the testing version, to do this in the command line
     # echo "deb http://ftp.ru.debian.org/debian/ testing main non-free contrib" \
             >> /etc/apt/sources.list
     # apt-get update 

Note: in a good way, it would be better to do apt-get dist-upgrade after apt-get update , but if you want to use a virtual machine only to start Debian MIPS / ARM, then this is not necessary at all.


')

Debian for MIPS


Debian for MIPS under QEMU will be demonstrated on a MIPS Malta virtual board with a MIPS32R2 architecture processor in big-endian mode.

Linux kernel build for QEMU Malta


First, let's take care of getting the source code for the kernel - download it from kernel.org:
 $ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.3.tar.xz 

Unpack the archive and go to the linux-4.4.3 directory:
 $ tar fx linux-4.4.3.tar.xz
 $ cd linux-4.4.3 

Install the toolchain for MIPS:
 # aptitude install -y gcc-mips-linux-gnu 

In addition to the toolchain for MIPS, additional tools will be needed to build the Linux kernel:
 # aptitude install -y make gcc gawk 

Prepare for assembly under MIPS:
 $ export ARCH = mips
 $ export CROSS_COMPILE = mips-linux-gnu- 

The ARCH variable explains to the kernel build system (Kbuild) that all platform-specific kernel components are taken in the arch/mips directory, and the CROSS_COMPILE variable explicitly tells Kbuild which compiler (or rather toolchain) to use - they can be several on the machine, and Kbuild likes accuracy.
A note about ARCH and CROSS_COMPILE
In principle, you can not do this, and each time you can set the ARCH and CROSS_COMPILE on the make command line, but then the make line will look somewhat cumbersome.

Note about out of tree build
The Linux kernel build order described below is called in tree build , i.e. compiled object files fall into the same directories as the source files. Kbuild allows you to use the out of tree build order, in which the object files fall into a separate directory, which allows you to collect several different kernel variants from the same source code, while the object files of different kernel variants will not conflict. For details, see, for example, here .

Now select the configuration for the core based on the pre-configured configuration for the Malta board.
The preparation of the configuration file for the Malta arch/mips/configs/malta_defconfig that ships in linux-4.4.3 does not work for two reasons:

Based on the malta_defconfig we will create the necessary malta_defconfig configuration file malta-big_defconfig , which will not have these disadvantages:
 $ sed "s / CONFIG_CPU_LITTLE_ENDIAN = y / CONFIG_CPU_BIG_ENDIAN = y /" \
         <arch / mips / configs / malta_defconfig \
         > arch / mips / configs / malta-big_defconfig
 $ echo "CONFIG_FHANDLE = y" >> arch / mips / configs / malta-big_defconfig
 $ echo "CONFIG_CGROUPS = y" >> arch / mips / configs / malta-big_defconfig 

Now, from the workpiece, we will generate the kernel configuration file .config :
 $ make malta-big_defconfig 

And run the build process:
 $ make 

Note: If your tool computer has more than one processor core, you should use them. In order to parallelize the make operation, the -j option is used, the argument of which is the number of tasks (commands) that make will try to run at the same time. So on a 4-processor instrumental computer, it makes sense to run make like this: $ make -j 4

As a result, we get the vmlinux kernel vmlinux . Check its performance under QEMU!
Install QEMU:
 # aptitude install -y qemu-system 

Run the newly compiled kernel under QEMU, after leaving the linux-4.4.3 directory:
 $ cd ..
 $ qemu-system-mips -nodefaults -nographic -kernel linux-4.4.3 / vmlinux -serial stdio
 Linux version 4.4.3 (user @ debian) (gcc version 5.3.1 20160205 (Debian 5.3.1-8))
 earlycon console serial ix port 0x3f8 (options '38400n8')
 bootconsole [uart0] enabled
 Config serial console: console = ttyS0,38400n8r
 CPU0 revision is: 00019300 (MIPS 24Kc)
 FPU revision is: 00739300
 MIPS: machine is mti, malta

 ...
 Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block (0,0) 

As you can see, the kernel successfully passed the initialization and tried to mount the root file system, which, however, did not work.
Create the necessary root filesystem!

Creating a root file system for MIPS


Creating the Debian root filesystem will therefore begin with the installation of debootstrap and the components necessary for it to work:
 # aptitude install -y binfmt-support qemu qemu-user-static debootstrap 

Now run the first stage of debootstrap:
 # debootstrap --foreign --arch = mips jessie debian-jessie-mips / \
         http://ftp.ru.debian.org/debian/ 

At the first stage, debootstrap will download the jessie version (stable) Debian packages required for the minimal root filesystem from ftp.ru.debian.org/debian (the official Russian Debian mirror) for the 32-bit MIPS big-endian architecture (options --foreign and --arch=mips ), and unpack them into the debian-jessie-mips/ directory.
According to the results of the first stage of debootstrap, a file system will be formed in the debian-jessie-mips/ directory, very similar to the real one, you can even try to use it for downloading. However, the root filesystem components (Debian packages) are not yet configured at this stage.
To perform the setup, you must run the second stage of debootstrap. At this stage, you need to run programs for MIPS, so you have to use a special version of QEMU, the so-called usermode qemu, which ensures the launch of separate programs for Linux MIPS under Linux amd64.
We will put a statically assembled system emulator with a MIPS architecture processor inside the root file system and run debootstrap inside the root file system using chroot:
 # cp / usr / bin / qemu-mips-static debian-jessie-mips / usr / bin /
 # DEBIAN_FRONTEND = noninteractive DEBCONF_NONINTERACTIVE_SEEN = true \
         LC_ALL = C LANGUAGE = C LANG = C \
         PATH = / usr / local / bin: / usr / bin: / bin: / usr / local / sbin: / usr / sbin: / sbin \
         chroot debian-jessie-mips / / debootstrap / debootstrap - second-stage 

When the second stage of debootstrap is finished, the components of the Debian root filesystem are configured, and it remains to put the final touches (for example, fix some files in /etc , say, configure the host and network, add users, etc.).
But for this demo, we will limit ourselves to installing the trivial password 123 for the root user:
 # echo 'root: 123' |  chroot debian-jessie-mips / chpasswd 

Now the root file system can be considered configured - it's time to cover up the tracks. For safekeeping, archive the root file system:
 # rm debian-jessie-mips / usr / bin / qemu-mips-static
 # tar czf debian-jessie-mips.tar.gz -C debian-jessie-mips. 

To run under the emulator, the root file system will have to be placed on a virtual drive (in the case of Malta it is a virtual IDE disk).
Let us estimate the size of the disk we will have to create:
 # du -sh debian-jessie-mips /
 284M debian-jessie-mips / 

Once the root file system is less than 300 MB, it is quite possible to allocate a virtual disk of 512 MB for its storage. Create a virtual disk file, create an ext2 file system on it, and copy our root file system to it:
 $ dd if = / dev / zero bs = 1M count = 512 of = debian-jessie-mips.ext2
 $ / sbin / mke2fs -F debian-jessie-mips.ext2

 # mkdir ext2
 # mount debian-jessie-mips.ext2 ext2 /
 # tar xf debian-jessie-mips.tar.gz -C ext2 /
 # umount ext2 /
 # rmdir ext2 / 

Now we will start Debian Linux under QEMU:
 $ qemu-system-mips -nodefaults -nographic -kernel linux-4.4.3 / vmlinux \
         -serial stdio -hda debian-jessie-mips.ext2 -append "root = / dev / sda" 

After the login: prompt appears login: you can log in as root (the password is 123) and check the processor type:


Debian for ARM


Debian for ARM under QEMU will be demonstrated on the ARM Versatile PB virtual board.
The steps to build a Linux kernel and create a root filesystem are almost completely similar to those for MIPS, so I’ll only give a sequence of commands to achieve a result with minimal comments.
We will assume that we are starting to work on a “clean” instrumental computer.

Build Linux kernel for ARM Versatile PB


 $ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.3.tar.xz
 $ tar fx linux-4.4.3.tar.xz
 $ cd linux-4.4.3

 # aptitude install -y gcc-arm-linux-gnueabi
 # aptitude install -y make gcc gawk

 $ export ARCH = arm
 $ export CROSS_COMPILE = arm-linux-gnueabi- 

With the preparation of the kernel configuration for Versatile, you will have to tinker, since the built-in ROM Versatile PB emulated by QEMU is quite small (64 MB). Fortunately, the emulated Versatile PB has a PCI controller to which you can connect a virtual SCSI controller. However, support for this hardware will have to be enabled in the kernel:
 $ cp arch / arm / configs / versatile_defconfig arch / arm / configs / versatile-debian_defconfig
 $ echo "CONFIG_FHANDLE = y" >> arch / arm / configs / versatile-debian_defconfig
 $ echo "CONFIG_CGROUPS = y" >> arch / arm / configs / versatile-debian_defconfig
 $ echo "CONFIG_DEVTMPFS = y" >> arch / arm / configs / versatile-debian_defconfig
 $ echo "CONFIG_TMPFS = y" >> arch / arm / configs / versatile-debian_defconfig
 $ echo "CONFIG_PCI = y" >> arch / arm / configs / versatile-debian_defconfig
 $ echo "CONFIG_SCSI = y" >> arch / arm / configs / versatile-debian_defconfig
 $ echo "CONFIG_BLK_DEV_SD = y" >> arch / arm / configs / versatile-debian_defconfig
 $ echo "CONFIG_SCSI_SYM53C8XX_2 = y" >> arch / arm / configs / versatile-debian_defconfig

 $ make versatile-debian_defconfig
 $ make

 # aptitude install -y qemu-system 

Unlike the MIPS Malta board, vmlinux download vmlinux for Versatile PB is not implemented, zImage images are zImage :
 $ cd ..
 $ qemu-system-arm -nodefaults -nographic -M versatilepb \
         -kernel linux-4.4.3 / arch / arm / boot / zImage \
         -append "console = ttyAMA0" -serial stdio
 ...
 Uncompressing Linux ... done, booting the kernel.
 Booting Linux on physical CPU 0x0
 Linux version 4.4.3 (antony @ debian) (gcc version 5.3.1 20160205 (Debian 5.3.1-8))
 CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr = 00093177
 CPU: VIVT data cache, VIVT instruction cache
 Machine: ARM-Versatile PB
 ...
 Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block (0,0) 


Creating a root file system for ARM


 # aptitude install -y binfmt-support qemu qemu-user-static debootstrap
 # debootstrap --foreign --arch = armel jessie debian-jessie-armel \
         http://ftp.ru.debian.org/debian/
 # cp / usr / bin / qemu-arm-static debian-jessie-armel / usr / bin /
 # DEBIAN_FRONTEND = noninteractive DEBCONF_NONINTERACTIVE_SEEN = true \
         LC_ALL = C LANGUAGE = C LANG = C \
         PATH = / usr / local / bin: / usr / bin: / bin: / usr / local / sbin: / usr / sbin: / sbin \
         chroot debian-jessie-armel / / debootstrap / debootstrap --second-stage
 # echo 'root: 123' |  chroot debian-jessie-armel / chpasswd
 # rm debian-jessie-armel / usr / bin / qemu-arm-static
 # tar czf debian-jessie-armel.tar.gz -C debian-jessie-armel.

 # du -sh debian-jessie-armel /
 270M debian-jessie-armel /

 $ dd if = / dev / zero bs = 1M count = 512 of = debian-jessie-armel.ext2
 $ / sbin / mke2fs -F debian-jessie-armel.ext2

 # mkdir ext2
 # mount debian-jessie-armel.ext2 ext2 /
 # tar xf debian-jessie-armel.tar.gz -C ext2 /
 # umount ext2 /
 # rmdir ext2 /

 $ qemu-system-arm -nodefaults -nographic -M versatilepb \
         -kernel linux-4.4.3 / arch / arm / boot / zImage \
         -append "console = ttyAMA0 root = / dev / sda" \
         -serial stdio -hda debian-jessie-armel.ext2 

The results of checking the type of processor (remember, the password is 123):


Conclusion


As you can see, installing and running Debian for MIPS and ARM is not that difficult.
Running Debian on a real motherboard with a MIPS or ARM processor is usually more troublesome and is worthy of a separate publication.

Links


Source: https://habr.com/ru/post/278159/


All Articles