Booting GNU/Linux on an ARM board from scratch (using Kali and iMX.6 as an example)

tl;dr: I'm creating a Kali Linux image for an ARM computer in the program debootstrap, linux and u-boot.

Booting GNU/Linux on an ARM board from scratch (using Kali and iMX.6 as an example)

If you purchased a lesser-known single-board computer, you might have encountered the lack of an image for your favorite distribution. The same situation happened with the planned Flipper One. There's simply no Kali Linux for IMX6 (I'm preparing it), so I have to compile it myself.

The boot process is quite simple:

  1. The hardware is initialized.
  2. A bootloader is read and executed from a designated area on the storage device (SD card/eMMC/etc).
  3. The bootloader searches for the operating system kernel and loads it into a specific memory area and executes it.
  4. The kernel loads the rest of the OS.

For my task, this level of detail is sufficient; you can read the specifics in another article. The aforementioned "certain" areas vary from board to board, which creates some difficulties in installation. The boot process for server ARM platforms is being standardized with UEFI, but since this isn't available for everyone yet, it will be necessary to assemble everything separately.

Building the root filesystem

First, you need to prepare the partitions. Das U-Boot supports various filesystems, I chose FAT32 for /boot and ext3 for the root; this is the standard layout for Kali images under ARM. I will use GNU Parted, but you can do the same with the more familiar fdisk. You will also need dosfstools and e2fsprogs to create filesystems: apt install parted dosfstools e2fsprogs.

Partitioning the SD card:

  1. Marking the SD card as using MBR partitioning: parted -s /dev/mmcblk0 mklabel msdos
  2. Creating a partition for /boot of 128 megabytes: parted -s /dev/mmcblk0 mkpart primary fat32 1MiB 128MiB. The first megabyte is reserved for the partitioning itself and the bootloader.
  3. Creating the root filesystem with the remaining storage: parted -s /dev/mmcblk0 mkpart primary ext4 128MiB 100%
  4. If for some reason your partition files were not created or modified, you need to run `partprobe`, then the partition table will be re-read.
  5. Creating the filesystem for the boot partition labeled BOOT: mkfs.vfat -n BOOT -F 32 -v /dev/mmcblk0p1
  6. Creating the root filesystem labeled ROOTFS: mkfs.ext3 -L ROOTFS /dev/mmcblk0p2

Great, now you can fill it. Additionally, you will need debootstrap, a utility for creating root filesystems for Debian-like operating systems: apt install debootstrap.

Building the filesystem:

  1. Mounting the partition in /mnt/ (use a more convenient mount point for yourself): mount /dev/mmcblk0p2 /mnt
  2. Now, let's fill the file system: debootstrap --foreign --include=qemu-user-static --arch armhf kali-rolling /mnt/ http://http.kali.org/kali. The parameter --include specifies additional packages to install; I included the statically built QEMU emulator. It allows running chroot in an ARM environment. You can find the meaning of the other options in man debootstrap. Don't forget that not every ARM board supports the armhf.
  3. Due to architecture differences debootstrap the process is carried out in two stages, the second is executed as follows: chroot /mnt/ /debootstrap/debootstrap --second-stage
  4. Now we need to chroot: chroot /mnt /bin/bash
  5. Filling /etc/hosts and /etc/hostname target FS. Fill it similarly to the contents on your local computer, just make sure to change the hostname.
  6. You can further configure everything else. In particular, I install locales (repository keys), reconfigure locales and time zone (dpkg-reconfigure locales tzdata). Don't forget to set a password with the command passwd.
  7. Set a password for root with the command passwd.
  8. Preparing the image for me concludes with filling in /etc/fstab inside /mnt/.

I will load according to the previously created labels, so the content will be as follows:

LABEL=ROOTFS / auto errors=remount-ro 0 1
LABEL=BOOT /boot auto defaults 0 0

Finally, we can mount the boot partition, which we will need for the kernel: `mount /dev/mmcblk0p1 /mnt/boot/`

Building Linux

To build the kernel (and the bootloader later) on Debian Testing, you need to install the standard set of GCC, GNU Make, and GNU C Library header files for the target architecture (for me armhf), as well as OpenSSL headers, console calculator bc, bison and flex: apt install crossbuild-essential-armhf bison flex libssl-dev bc. Since the bootloader by default looks for the file zImage on the boot partition's file system, it's time to partition the flash drive.

  1. Cloning the kernel takes too long, so I will just download it: wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.9.1.tar.xz. Let's unpack and go to the source directory: tar -xf linux-5.9.1.tar.xz && cd linux-5.9.1
  2. Configure before compiling: make ARCH=arm KBUILD_DEFCONFIG=imx_v6_v7_defconfig defconfig. The config is located in the directory arch/arm/configs/. If it is not there, you can try to find and download a ready-made one and pass the file name in that directory to the parameter KBUILD_DEFCONFIG. If all else fails, just move on to the next step.
  3. Optionally, you can fine-tune the settings: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
  4. And cross-compile the image: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
  5. Now you can copy the file with the kernel: cp arch/arm/boot/zImage /mnt/boot/
  6. And the files with DeviceTree (description of the hardware on the board): cp arch/arm/boot/dts/*.dtb /mnt/boot/
  7. And install the compiled modules as separate files: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- INSTALL_MOD_PATH=/mnt/ modules_install

The kernel is ready. You can unmount everything now: umount /mnt/boot/ /mnt/

Das U-Boot

Since the bootloader is interactive, all you need for testing is the board, the storage device, and optionally a USB-to-UART device. That is, you can postpone the kernel and OS for later.

The vast majority of manufacturers offer to use Das U-Boot for primary booting. Full support is usually provided in their own fork, but they also contribute to the upstream. mainline, therefore fork I ignored it.

We are building the bootloader:

  1. Clone the stable branch of the repository: git clone https://gitlab.denx.de/u-boot/u-boot.git -b v2020.10
  2. Go to the directory: cd u-boot
  3. Prepare the build configuration: make mx6ull_14x14_evk_defconfig. This only works if the configuration exists in Das U-Boot itself; otherwise, you will need to find the manufacturer's config and place it in the root of the repository in a file .config, or build it in another way recommended by the manufacturer.
  4. Build the bootloader image with a cross-compiler armhf: make CROSS_COMPILE=arm-linux-gnueabihf- u-boot.imx

As a result, we get the file u-boot.imx, this is the ready image that can be written to a flash drive. Write to the SD card, skipping the first 1024 bytes. Why did I choose the target u-boot.imx? Почему пропустил именно 1024 байта? Так предлагают сделать в the documentation. For other boards, the process of building the image and writing may differ slightly.

Done, you can boot up. The bootloader should report its own version, some information about the board, and try to find the kernel image on the partition. If it fails, it will attempt to boot over the network. Overall, the output is quite detailed, allowing you to identify errors in case of issues.

In conclusion

Did you know that a dolphin's forehead is not bony? It is literally a third eye, a fatty lens for echolocation!

Booting GNU/Linux on an ARM board from scratch (using Kali and iMX.6 as an example)

Booting GNU/Linux on an ARM board from scratch (using Kali and iMX.6 as an example)

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster