Overview

Below you can find how to setup and run emulated RDK-B from image build for Raspberry Pi 4. It can be useful for CICD systems, for the first run after the new image build or some new features tests. Currently ETH interface is functional.

System requirements

  • Ubuntu 22.04 64-bit

  • At least 8GB of RAM

  • 256GB hard drive

Docker install

Please follow the guide: Ubuntu | Docker Docs

Use docker without sudo: Post-installation steps | Docker Docs

Prepare the RPI 4 image

Build your RDK-B Raspberry Pi 4 64-bit image, example: https://wiki.rdkcentral.com/pages/viewpage.action?pageId=292335921

Setup scripts

Follow below steps:

mkdir ~/vRDK-B
cd ~/vRDK-B
mkdir qemu_files

Copy RPI 4 image to ~/vRDK-B/qemu_files:

  • Image-raspberrypi4-64-rdk-broadband.bin

  • rdk-generic-broadband-tdk-image-raspberrypi4-64-rdk-broadband.wic.bz2

Create Dockerfile and paste:

FROM ubuntu:22.04

ARG QEMU_USER=dev QEMU_UID=1001

ENV TZ=US
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y && \
    apt-get install -y \
      bzip2 \
      fdisk \
      locales \
      mtools \
      net-tools \
      openssh-client \
      slirp \
      sudo \
      wget \
      xz-utils \
      build-essential \
      python3 \
      python3-pip \
      ninja-build \
      libglib2.0-dev \
      git \
      flex \
      bison \
      libslirp-dev \
      && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install \
    pyvenv \
    tomli \
    sphinx \
    sphinx_rtd_theme \
    termcolor

ARG QEMU_VERSION=9.2.0
RUN wget https://download.qemu.org/qemu-${QEMU_VERSION}.tar.xz && \
    tar xvJf qemu-${QEMU_VERSION}.tar.xz && \
    cd qemu-${QEMU_VERSION} && \
    ./configure \
      --enable-slirp \
      --target-list=aarch64-softmmu

RUN cd qemu-${QEMU_VERSION} && \
    make install && \
    cd .. && \
    sudo rm -rf qemu-${QEMU_VERSION}*

RUN locale-gen "en_US.UTF-8" && dpkg-reconfigure locales

Create run-vrdk-b.sh and paste:

#!/usr/bin/env bash
set -eu

echo "$(id)"
mkdir ${HOME}/qemu || ls -la ${HOME}/qemu/

cd ${HOME}/qemu

IMAGE_WIC="${IMAGE_FILE%.*}"
if [ ! -f "${IMAGE_WIC}" ]; then
  cp -v /qemu/* .
fi

wait_for_sshd () {
  while true;
  do
    (ssh -o ConnectTimeout=5 \
         -o HostKeyAlgorithms=+ssh-rsa \
         -o StrictHostKeyChecking=no \
         -p 2223 root@localhost /bin/true) && break || \
    echo "<<< Please wait ... >>>"
    sleep 5
  done
}

run_qemu () {
  set +e
  QEMU_LOG="${HOME}/qemu-$(date +%Y%m%d.%H%M.%s).log"
  echo "<<< Run RDK-B with QEMU >>>"
  timeout -v 900 bash <<-EOF
    set -x
    qemu-system-aarch64 \
      -machine virt \
      -cpu cortex-a72 \
      -m 2G \
      -smp 4 \
      -nographic \
      -kernel "${KERNEL_FILE}" \
      -drive file="${IMAGE_WIC},if=none,id=hd0,cache=writeback,format=raw" \
      -device virtio-blk-device,drive=hd0 \
      -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 root=/dev/vda2 rootdelay=1" \
      -device "virtio-net-device,netdev=eth0" \
      -netdev "user,id=eth0,${HOST_FWD}" \
      >> "${QEMU_LOG}" 2>&1 &
    set +x
    echo "<<< Waiting for RDK-B to fully initialise >>>"
    sleep 5
    ( tail -f -n0 "${QEMU_LOG}" & ) | while IFS= read -r line; do
      echo "\${line}"
      if \$(echo "\${line}" | grep -q "Apache License") ; then
        echo "Apache service has been started!"
        break
      fi
    done
EOF
}

echo "Starting QEMU ..."

set -e
run_qemu
wait_for_sshd
ssh -p 2223 -o StrictHostKeyChecking=no root@localhost /sbin/reboot
sleep 10
wait_for_sshd

echo "<<< RDK-B fully initialised >>>"

chmod +x run-vrdk-b.sh

Build and run

Build docker image:

cd ~/vRDK-B
docker build -t vrdk-b \
  --build-arg QEMU_VERSION=9.2.0 \
  --build-arg QEMU_USER=dev \
  --build-arg QEMU_UID=${USER_ID} \
  -f Dockerfile .

Run container:

docker run -d \
  --name vrdk-b \
  --privileged \
  -e KERNEL_FILE=Image-raspberrypi4-64-rdk-broadband.bin \
  -e IMAGE_FILE=rdk-generic-broadband-tdk-image-raspberrypi4-64-rdk-broadband.wic.bz2 \
  -e HOST_FWD=hostfwd=tcp::2223-:22,hostfwd=tcp::8081-:80 \
  -p 2223:2223 \
  -p 8081:8081 \
  -v /dev:/dev \
  -v ${PWD}/qemu_files:/qemu \
  --mount type=bind,source=$(pwd)/run-vrdk-b.sh,target=/run-vrdk-b.sh \
  -it vrdk-b

Run qemu:

docker exec -it vrdk-b /run-vrdk-b.sh

Wait until vRDK-B boot.

Testing UI

In a web browser on your host paste:

localhost:8081 

Example:

Testing SSH

Connect via SSH from host to vRDK-B:

ssh -p 2223 root@localhost

Example:

 

Demo Video

vRDK-B.mp4

  • No labels

3 Comments

  1. For sure you should modify QEMU parameters like cpu, memory. And of course all file names and paths (e.g. KERNEL_FILE=Image-raspberrypi4-64-rdk-broadband.bin)

  2. Hi Chandrakanth Pokuru , required changes for running RDK-B Banana Pi R4 on QEMU below.

    1.  Building RDK-B Banana Pi Image

    Follow build instructions of RDK-B Banana Pi R4 - Beta Engineering Release(05 Feb 2025) for SD card target.

    Additional changes are required to enable VIRT support.

    Before starting bitbake build, edit meta-cmf-bananapi/meta-rdk-mtk-bpir4/recipes-kernel/linux/files/rdkb_cfg/sdmmc.cfg file in your RDK workspace and add the following lines:

    CONFIG_VIRTIO=y

    CONFIG_VIRTIO_FS=y

    CONFIG_VIRTIO_PCI=y

    CONFIG_VIRTIO_MMIO=y

    CONFIG_VIRTIO_BLK=y

    CONFIG_VIRTIO_SCSI=y

    CONFIG_VIRTIO_NET=y

    CONFIG_VIRTIO_INPUT=y

    CONFIG_VIRTIO_CONSOLE=y

    CONFIG_HW_RANDOM_VIRTIO=y

    CONFIG_VIRTIO_BALLOON=y

    CONFIG_VIRTIO_INPUT=y

    2.  Copy image files

    Copy generated image files to ~/vRDK-B/qemu_files:

    • fitImage-bananapi4-rdk-broadband.bin
    • rdk-generic-broadband-image-bananapi4-rdk-broadband.wic.bz2

    3.  Create script for BPI

    Create run-vrdk-b_bpi.sh in ~/vRDK-B and paste:

    #!/usr/bin/env bash
    set -eu
    
    qemu-system-aarch64 --version
    
    echo "$(id)"
    mkdir ${HOME}/qemu || ls -la ${HOME}/qemu/
    
    cd ${HOME}/qemu
    
    update_fstab () {
      MOUNT_DIR="./image"
      DEV_LOOP=`sudo losetup --find --show --partscan $1 |head -1`
      mkdir -p "$MOUNT_DIR"
      sudo mount "${DEV_LOOP}p4" "${MOUNT_DIR}"
      sudo sed -i 's/mmcblk0p3/vda3/' "${MOUNT_DIR}/etc/fstab"
      echo "SUBSYSTEM==\"net\", ACTION==\"add\", ATTR{address}==\"52:54:00:12:34:56\", NAME=\"lan0\"" \
        >> "${MOUNT_DIR}/etc/udev/rules.d/70-persistent-net.rules"
      sudo umount "${MOUNT_DIR}"
      sudo losetup -d ${DEV_LOOP}
    }
    
    IMAGE_WIC="${IMAGE_FILE%.*}"
    if [ ! -f "${IMAGE_WIC}" ]; then
      cp -v /qemu/* .
      dd if="${KERNEL_FILE}" bs=1 skip=296 of=linux.bin
      bzip2 -d "${IMAGE_FILE}"
      qemu-img resize -f raw "${IMAGE_WIC}" 4G
      update_fstab "${IMAGE_WIC}"
    else
      echo "Found: ${IMAGE_WIC}" 
    fi
    
    wait_for_sshd () {
      while true;
      do
        (ssh -o ConnectTimeout=5 \
             -o HostKeyAlgorithms=+ssh-rsa \
             -o StrictHostKeyChecking=no \
             -p 2223 root@localhost /bin/true) && break || \
        echo "<<< Waiting for sshd before running ... >>>"
        sleep 5
      done
    }
    
    run_qemu () {
      set +e
      QEMU_LOG="${HOME}/qemu-$(date +%Y%m%d.%H%M.%s).log"
      echo "<<< Run RDK-B with QEMU >>>"
      timeout -v 900 bash <<-EOF
        set -x
        qemu-system-aarch64 \
          -machine virt \
          -cpu cortex-a72 \
          -m 4G \
          -smp 4 \
          -nographic \
          -kernel linux.bin \
          -drive file="${IMAGE_WIC},if=none,id=hd0,cache=writeback,format=raw" \
          -device virtio-blk-device,drive=hd0 \
          -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 root=/dev/vda4 rootdelay=1" \
          -device "virtio-net-device,netdev=eth0,mac=52:54:00:12:34:56" \
          -netdev "user,id=eth0,${HOST_FWD}" \
          >> "${QEMU_LOG}" 2>&1 &
        set +x
        echo "<<< Waiting for RDK-B to fully initialise >>>"
        sleep 5
        ( tail -f -n0 "${QEMU_LOG}" & ) | while IFS= read -r line; do
          echo "\${line}"
          if \$(echo "\${line}" | grep -q "Apache License") ; then
            echo "Apache service has been started!"
            break
          fi
        done
    EOF
    }
    
    copy_qemu_log () {
      sudo cp -v ${HOME}/qemu-*.log "${OUT_DIR}/"
    }
    
    echo "Starting QEMU ..."
    
    set -e
    run_qemu
    wait_for_sshd
    echo "<<< Restarting services to setup CcspWebUI correctly ... >>>"
    ssh -p 2223 -o StrictHostKeyChecking=no root@localhost /sbin/reboot
    sleep 10
    wait_for_sshd
    
    echo "<<< RDK-B BPI fully initialized >>>"
    
    


    chmod +x run-vrdk-b_bpi.sh

    4.  Run QEMU

    Run container (check your KERNEL_FILE and IMAGE_FILE file names):

    docker run -d \
      --name vrdk-b_bpi \
      --privileged \
      -e KERNEL_FILE=fitImage-bananapi4-rdk-broadband.bin \
      -e IMAGE_FILE=rdk-generic-broadband-image-bananapi4-rdk-broadband.wic.bz2 \
      -e HOST_FWD=hostfwd=tcp::2223-:22,hostfwd=tcp::8081-:80 \
      -p 2223:2223 \
      -p 8081:8081 \
      -v /dev:/dev \
      -v ${PWD}/qemu_files:/qemu \
      --mount type=bind,source=$(pwd)/run-vrdk-b_bpi.sh,target=/run-vrdk-b_bpi.sh \
      -it vrdk-b

    Run qemu:

    docker exec -it vrdk-b_bpi /run-vrdk-b_bpi.sh

    Wait until vRDK-B boot.