Sign inSign up

digiampietro/buildroot-armv7

By digiampietro

•Updated about 7 years ago

A Docker image to run an old version of Buildroot (buildroot-2014-02) based on Debian Wheezy

Image
0

1.1K

digiampietro/buildroot-armv7 repository overview

⁠Description

This is a work in progress, it is fully usable and runs correctly, but documentation is still incomplete.

Buildroot-armv7 is a Docker image (in wich Buildroot is not included), a set of scripts, configuration files and Buildroot external tree to easily setup an emulation environment where to run, debug and reverse engineer the Netgear DVA 5592 router executables. This environment uses Docker, Buildroot and Qemu to build a root file system and emulate a board with an ARMv7 Cortex A9 processor, a quite old Linux kernel, version 3.4.11-rt19 with appropriate patches, uClibc 0.9.33.2, and old versions of other libraries.

⁠Table of Contents

⁠Quick Start

On a Linux box, the only OS supported:

  • install Docker, this guide⁠, or similar guides, can be useful
  • add your username to the docker group with a command similar to the following (can be different in some Linux distributions):
    $ sudo adduser *yourusername* docker
    
  • install Qemu⁠, using something similar to the following commands:
    $ sudo apt-get install qemu qemu-block-extra qemu-kvm qemu-slof qemu-system \
      qemu-system-arm qemu-system-common qemu-system-mips qemu-system-misc \
      qemu-system-ppc qemu-system-s390x qemu-system-sparc qemu-system-x86 \
      qemu-user qemu-user-binfmt qemu-utils
    
  • install Binwalk⁠, using something similar to the following commands:
    $ sudo apt-get install binwalk
    
  • install Jefferson⁠, following instructions on the GitHub repository
  • download this project with command similar to the followings:
    valerio@ubuntu-hp:~$ mkdir br      # configuration script will create folders here
    valerio@ubuntu-hp:~$ cd br
    valerio@ubuntu-hp:~/br$ git clone https://github.com/digiampietro/buildroot-armv7.git buildroot-armv7
    
  • type the following commands, the br-armv7-config.sh script will download Buildroot, Linux kernel, router firmware and will configure the environment
    valerio@ubuntu-hp:~/br$ cd buildroot-armv7   
    valerio@ubuntu-hp:~/br/buildroot-armv7$ ./br-armv7-config.sh
    
  • download the docker image from the Docker repository
    valerio@ubuntu-hp:~/br/buildroot-armv7$ docker pull digiampietro/buildroot-armv7
    
  • run the docker image, it is based on the old Debian Wheezy to run the old buildroot-2014-02; the current username and home directory are mapped inside the docker host. Inside the docker host the command prompt has changed, the hostname now is BRHOST:
    valerio@ubuntu-hp:~/br/buildroot-armv7$ cd docker/
    valerio@ubuntu-hp:~/br/buildroot-armv7/docker$ ./dockrun.sh
    valerio@BRHOST:~$ cd ~/br/buildroot-armv7
    
  • run the Buildroot make using the brmake shell script that sets the BR2_EXTERNAL environment variable to use a customized buildroot external tree:
    valerio@BRHOST:~/br/buildroot-armv7$ ./brmake dvaemu-emu_arm_vexpress_defconfig
    valerio@BRHOST:~/br/buildroot-armv7$ ./brmake # takes a loooong time
    
  • at the end of the buildroot process a root file system image has been built, ready to be used by Qemu, running outside the docker machine:
    valerio@BRHOST:~/br/buildroot-armv7$ exit
    root@BRHOST:/src/misc# exit
    valerio@ubuntu-hp:~/br/buildroot-armv7/docker$ cd ../qemu-run/
    valerio@ubuntu-hp:~/br/buildroot-armv7/qemu-run$ ./qr
    ...
    reeing init memory: 160K
    smsc911x 4e000000.ethernet: eth0: SMSC911x/921x identified at 0xc08c0000, IRQ: 47
    Welcome to Buildroot
    buildroot login: root
    root@buildroot:~# uname -a
    Linux buildroot 3.4.11-rt19 #1 SMP PREEMPT Fri Sep 28 18:46:38 UTC 2018 armv7l GNU/Linux
    root@buildroot:~#
    
  • an ARM virtual machine is now available to run debug and reverse engineer the most interesting router executables. The router root file system has been included in the ARM image in the folder /dva-root, the firmware files and file system images are included in the folder /dva-firm:
    root@buildroot:~# ls /dva-root/
    bin         dev.tar.gz  mnt         sbin        usr
    data        etc         proc        sys         var
    dev         lib         root        tmp         www
    root@buildroot:~# ls /dva-firm/
    DVA-5592_A1_WI_20180405.sig  root-fs.bin
    boot-fs.bin                  set-nandsim.sh
    
  • to exit from the Qemu virtual machine you can type # halt and then press Ctrl-A followed by the key X

⁠Building the emulation environment

The purpose of the emulation environment is to run, as much as possible, router executables in a Qemu virtual machine. This means not only that the machine must have an ARM v7 Cortex-A9 processor, but that the kernel and the libraries should be the same version, or compatible versions, used in the router.

⁠Emulation environment requirements

The emulated environment should have:

  • an ARM v7 Cortex A9 Processor
  • an emulated 256Mb Nand flash memory, emulated with the nandsim kernel flash emulator
  • a Linux Kernel version 3.4.11-rt19
  • a root file system using uClibc, version 0.9.33.2, as standard C library
  • a Gnu libgcrypt crypto library version 1.5 (with library file: libgcrypt.so.11)
  • other libraries with compatible versions with the router's binaries These requirements basically means to use what was available in 2014, because the software used to build the router firmware seems coming from that year.

⁠Choosing the tool to build the Root File System

The root file system can be built with a cross compilation toolchain able to generate binaries for the ARM architecture on an Intel based Linux PC; but building the kernel, the libraries and the needed packages can be very challenging and time consuming because of the various version dependency that each package can have with other packages and standard libraries (the so called dependency hell). For this reason it is better to select a build tool able to manage this dependency hell, the most popular building tools for embedded devices are:

  • The Yocto Project⁠ is very powerful, not only builds a root file system, but is able to create a custom Linux distribution for the embedded device. It's main drawback is that it has a steep learning curve
  • Buildroot⁠ has a more limited scope: it builds the root file system and the kernel, it is quite easy and fast to learn and has a very good user manual, not too big, neither too small
  • Openwrt/LEDE Build System⁠ is tailored mainly to build a replacement router firmware, his documentation is much more scattered in the web site and so requires more time to learn.

Buildroot has been the tool chosen for this reverse engineering project. It has been easy to learn ed effective in building the required root file system.

⁠Issues to overcome

Initial idea was using the latest Buildroot version available (buildroot-2018-05) on the last Ubuntu version (18.04.1 LTS, Bionic Beaver), but this buildroot version doesn't have the option to use uClibc, it has uClibc-ng that is not fully compatible with the router's binaries compiled with uClibc; the Gnu libgcrypt crypto library is a newer version, not fully compatible wth the router's binaries. It is practically impossible to downgrade these two libraries and others because of the dependency hell.

Another idea was to use an older Buildroot version (buildroot-2014-02) that has the same router's uClibc version, compatible version of Gnu libgcrypt crypto library and similar versions of other libraries. The problem is that this buildroot version, on Ubuntu 18.04, gives multiple compilation errors, almost impossible to fix; changing gcc version doesn't help to solve all the issues.

The solution has been to use a Docker image, based on Debian Wheezy released in 2013, to run buildroot-2014-02; this docker image is able to run this version of buildroot without any issues.

During the setup of this environment many other issues have arisen, described below in the description of various configurations.

⁠The Docker image

The main purpose of the Docker image is to have a Linux environment able to run buildroot-214.02 without issues, for this reason the image is based on Debian Wheezy (released in 2013) with additional packages needed to run buildroot-2014.02, including packages and QT libraries to do a make xconfig with a GUI. The Docekerfile⁠ is quite simple and doesn't include Buildroot.

Buildroot is installed in the user's home directory because both the user and his home directory are mapped inside the Docker image using the following shell script, docker/dockrun.sh⁠, to run the Docker image:

#!/bin/sh

export GDISPLAY=unix/$DISPLAY      # forward X11 display to the host machine
export GUSERNAME=`id -u -n`        # current user's username
export GUID=`id -u`                # current user's user id
export GGROUP=`id -g -n`           # current user's primary group name
export GGID=`id -g`                # current user's primary group id
export GHOME=$HOME                 # current user's home directory
export GSHELL=$SHELL               # current user's shell
export GRUNXTERM=0                 # flag start lxterminal, useful in windows
export GPWD=`pwd`                  # current working directory

docker run      -h BRHOST                         \
                --rm                              \
                -v /tmp/.X11-unix:/tmp/.X11-unix  \
                -v $HOME:$HOME                    \
                -e DISPLAY=$GDISPLAY              \
                -e GUSERNAME=$GUSERNAME           \
                -e GUID=$GUID                     \
                -e GGROUP=$GGROUP                 \
                -e GGID=$GGID                     \
                -e GHOME=$GHOME                   \
                -e GSHELL=$SHELL                  \
                -e GRUNXTERM=$GRUNXTERM           \
                -e GPWD=$GPWD                     \
                -it digiampietro/buildroot-armv7

In this script:

  • the user's home directory ($HOME) is mapped, with option -v, inside the running image at exactly the same path
  • the -v /tmp/.X11-unix:/tmp/.X11-unix option has the purpose do display, on the host, X11 applications running inside the Docker image
  • the --rm options terminate the Docker image process after exiting from the interactive shell; This is needed to prevent having a lot of unused stopped images
  • some environment variables (options -v) are passed from the host to the docker image with the purpose to create, on the fly, inside the image, the same user existing on the host with exact same attributes (username, uid, primary group, shell, home dir). This job is accomplished by the following entrypoint script docekr/startup.sh:
#!/bin/sh
#
# add current user and user's primary group
#
groupadd -g $GGID $GGROUP
useradd  -u $GUID -s $GSHELL -c $GUSERNAME -g $GGID -M -d $GHOME $GUSERNAME
usermod  -a -G sudo $GUSERNAME
echo $GUSERNAME:docker | chpasswd
if [ "$GRUNXTERM" = "1" ]
then
  # become the current user and start a shell
  su -l -c lxterminal $GUSERNAME
  # another root shel
  lxterminal
else
  # become the current user and start a shell
  su -l $GUSERNAME
  # another root shell
  /bin/bash
fi

This Docker usage pattern allows to transparently share the user's home directory between the host and the Docker image and can be used every time there is a need to use a Docker image to transparently run software that cannot be run on the host and that will use and/or modify files in user's home directory.

In this case the Buildroot folder is not installed inside the Docker image, but will be installed in user's home directory and, in this way, the Buildroot folder will remain persistent across Docker image invocations.

⁠Buildroot configuration

The Buildroot configuration is stored in an external tree in the folder ext-tree, Buildroot itself can be launched with the shell script brmake that, basically, change directory in the Buildroot directory and execute a make BR2_EXTERNAL=<path to ext-tree>.

The ext-tree folder has the following content:

ext-tree/
├── board
│   └── dvaemu
│       ├── kernel-defconfig
│       ├── overlay
│       │   └── etc
│       │       └── profile.d
│       │           └── set-prompt.sh
│       └── post-build.sh
├── Config.in
├── configs
│   ├── dvaemu-emu_arm_vexpress_defconfig
│   └── uClibc-0.9.33.config
├── external.desc
├── external.mk
├── package
│   └── klish
│       ├── 0001-klish-help-param-optional.patch
│       ├── Config.in
│       └── klish.mk
└── patches
    └── linux
        ├── 0002-module.h-remove-p2v8-from-module-id-string.patch
        ├── 0004-jffs2_make_lzma_available.patch
        ├── 0005-jffs2_eofdetect.patch
        └── 0006-jffs2_make_lzma_high_priority.patch
  • ext-tree/board/dvaemu contains files for the fictitious board called dvaemu (for DVA 5592 router emulation)

  • ext-tree/board/dvaemu/kernel-defconfig contains the kernel configuration, saved in a defconfig file; main differences, compared with the default kernel configuration, have been introduced to be more similar to the router's kernel and to run it in QEMU:

    • General setup
      • Choose SLAB allocator: SLAB, this is needed to run some binaries/Libraries
    • System type: Versatile Express platform type with Device Tree support
    • Preemption Model: Preemptible Kernel (low latency Desktop)
    • Device Drivers
      • NAND Device Support and Support for NAND Flash Simulator, this is very important to simulate the JFFS2 file system on the flash memory
      • OneNAND Device Support
      • Enable UBI
    • File Systems
      • Miscellaneous filesystems: JFFS2 support, Advanced Compression, JFFS2 LZMA compression supported
    • Library routines
      • CRC-CCITT functions
      • CRC16 functions
      • CRC calculations for the T10 Data Integrity Field
      • CRC ITU-T V.41 functions
  • ext-tree/board/dvaemu/overlay in this path's subfolder there is the set-prompt.sh script used to setup the prompt inside the QEMU emulated machine

  • ext-tree/board/dvaemu/post-build.sh this is the Buildroot post-build script, used mainly to copy router's root file system and firmware to the root image of the emulated machine

  • ext-tree/Config.in, external.desc, external.mk are files needed by Buildroot to use the external tree

  • ext-tree/configs/dvaemu-emu_arm_vexpress_defconfig contains the buildroot configuration, it is based on the qemu_arm_vexpress_defconfig, included in buildroot, to emulate a Versatile Express ARM board with an ARMv7 Cortex-A9 processor. The most important modified options are:

    • Target Option: EABIhf, because the router's CPU seems to support hardware floating point processing
    • Build Options, the selected options are needed to make easier the reverse engineering job:
      • Build packages with debugging symbols
      • gcc debug level 2
      • strip binaries: no
      • gcc optimization level 0
      • global patch directories, to point to the external tree patch directory
    • Toolchain, the selected options are needed to enable and facilitate debugging and to compile the 3.4.11-rt9 Kernel
      • Kernle Headers: 3.4.x
      • Enable large file support
      • Enable WCHAR support
      • Thread library debugging
      • Enable C++ support
      • Build cross GDB for the host
    • Linux Kernel, the selected options are needed to select the 3.4.11-rt9 kernel and to run it under QEMU:
      • Custom tarball location
      • Kernel configuration: using a custom config file
      • Device tree support
      • Install kernel image to /boot Target
    • Compressor and Decompressor, useful for the purpose of emulating the router environment
      • bzip2
      • xz-utils
    • Debugging profiling and benchmark, the selected options are useful for reverse engineering
      • gdb (gdbserver and full debugger)
      • ltrace
      • strace
    • Development tools
      • binutils, flex, libtools, make, pkgconf
      • mtd, jffs2 and ubi/ubifs tools; these are very important because are related to flash eeprom Emulation
    • Libraries, the selected options are needed to emulate binaries requiring the selected libraries
      • libgcrypt, expat, roxml, libxml2, Mini-XML
    • Network Applications are included to exchange files between the emulated machine and the external world
      • rsync, rsh-redone, socat, ncftp, iputils
    • Shell and utilities
      • file, sudo
    • Host utilities
      • host mtd, jffs2 and ubi/ubifs tools
    • User provided options
      • klish, to try to emulate the router's shell
  • ext-tree/configs/uClibc-0.9.33.config this is the uClibc configuration, the main differences, compared with the default, have been introduced to be compatible with the router's binaries and to include debugging symbols in the library files. The inclusion of debugging symbols has been problematic: uClibc don't obey to the general option included in the Buildroot configuration, has his own flag for this purpose; the problem is that enabling his own flag the compilation gives impossible to fix errors, for this reason a workaround, described below, has been used:

    • Target Architecture Features and Options
      • Build for EABI
      • Use BX in function return
      • Enable full C99 math library support
    • General Library Settings
      • Enable library loader preload file, not selected
      • Link LD Config statically, not selected
      • Thread support, native POSIX Threading
      • Build pthreads debugging support
      • Malloc returns live pointer for malloc(0)
      • Provide libutil library and functions
    • String and Stdio support
      • Wide character support
      • Support hexadecimal float notation
      • Support glibc's register_printf_function()
      • Some other glibc compatible settings
    • Development/debugging options
      • in Compiler Warnings add the string "-ggdb", this is the work around to compile the uClibc with debugging symbols
  • ext-tree/package, in this directory is included the klish package, but, unfortunately, it is not compatible with the router's klish configuration files, probably the klish application in the router has been modified in incompatible ways

  • ext-tree/patches/linux: linux patches to have the kernel more similar to the router's kernel, the patches are:

    • 0002-module.h-remove-p2v8-from-module-id-string.patch to make the kernel identifying string identical to the router's kernel modules, but, unfortunately, in this way it is possible to load router's module in the emulated machine, but the kernel crashes
    • 0004-jffs2_make_lzma_available.patch this patch implements the LZMA compression for the JFFS2 file system, it has been borrowed and adapted from the OpenWRT project
    • 0005-jffs2_eofdetect.patch this patch implements the end of partition detection for JFFS2 filesystems, this patch is included in the router's kernel and automatically detect the end of a JFFS2 partition, thanks to a magic number
    • 0006-jffs2_make_lzma_high_priority.patch this patch makes LZMA compression the preferred compression method for the JFFS2 partition, similar to what the router's kernel does.

⁠Running Buildroot

The Buildroot User's Manual⁠ is a very good guide on how to configure and run Buildroot; in this environment Buildroot make commands should be executed using the brmake script inside the buildroot-armv7 folder, the most useful commands are:

  • ./brmake xconfig (or ./brmake menu-config) to configure Buildroot options;

  • ./brmake linux-xconfig (or ./brmake linux-menuconfig) to configure the Linux Kernel

  • ./brmake uclibc-menuconfig (the xconfig version is not available for uClibc) to configure the uClibc library

  • ./brmake savedefconfig to save the Buildroot configuration in the external tree, on the file ext-tree/configs/dvaemu-emu_arm_vexpress_defconfig

  • ./brmake linux-update-defconfig to save the Linux Kernel configuration in the external tree, on the file ext-tree/board/dvaemu/kernel-defconfig

  • ./brmake uclibc-update-defconfig to save the uClibc configuration in the external tree, on the file ext-tree/configs/uClibc-0.9.33.config

  • ./brmake clean to delete all build products (including build directories, host, staging and target trees, the images and the toolchain)

  • ./brmake distclean to delete everything, including configuration files; needed to build for a new target, should not be needed with this environment;

  • ./brmake linux-dirclean removes the whole kernel build directory, to be used when kernel configuration changes are made;

  • ./brmake -s printvars to dump all the variables known to make;

    • ./brmake to build the kernel and the root file system.

    ⁠Running QEMU

    To run QEMU there is the qr script inside the qemu-run folder, this script runs QEMU using the root file system built by Buildroot. The script is the following:

    #!/bin/bash
    MYDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    . $MYDIR/../set-env.sh
    cd $MYDIR
    export QEMU_AUDIO_DRV="none"
    qemu-system-arm -M        vexpress-a9                                                    \
                    -cpu      cortex-a9                                                      \
                    -m        1024                                                           \
                    -nographic                                                               \
                    -kernel   $BRIMAGES/zImage                                               \
                    -drive    file=$BRIMAGES/rootfs.ext2,index=0,media=disk,format=raw,if=sd \
                    -dtb      $BRIMAGES/vexpress-v2p-ca9.dtb                                 \
                    -net      nic                                                            \
                    -net      user,hostfwd=tcp::2222-:22,hostfwd=tcp::9000-:9000             \
                    -append   "rw console=ttyAMA0 console=tty root=/dev/mmcblk0"
    

    The first three lines set environment variables and change directory to that of the script, the fourth line disables the audio driver (the emulated board doesn't emulate audio hardware), the qemu-system-arm options select:

    • board vexpress-a9 with processor cortex-a9 and 1Gb of RAM
    • the -nographic option prevents the opening of another window: the console input/output go to the terminal
    • the -kernel option selects the kernel generated by Buildroot
    • the -drive option selects the root file system image generated by Buildroot emulated as an SD disk
    • the -dtb option selects the Device Tree Blob generated by Buildroot and describing the board devices to the kernel
    • the -net options

Tag summary

Content type

Image

Digest

Size

226.2 MB

Last updated

about 7 years ago

docker pull digiampietro/buildroot-armv7