A Step-by-Step Guide to Customizing System Images Using Deepin

Have you ever thought about creating a custom operating system image by yourself? Whether it’s for a geek project to tailor a development environment or to breathe new life into old devices, customizing system images is an essential skill for enthusiasts.

So how can you customize a dedicated system image for the device you have?

Thanks to community user @空木蓮華 for their contribution. This article will demonstrate the creation, flashing, and operation of a Raspberry Pi image using the Deepin operating system, sharing practical ideas and valuable experiences for customizing system images.

1

Installing the Basic Toolchain

Before starting to create the image, you need to install the basic toolchain. You can install the necessary packages using the following command:

sudo apt update -y
sudo apt-get install -y qemu-user-static binfmt-support mmdebstrap arch-test usrmerge usr-is-merged fdisk dosfstools
sudo systemctl restart systemd-binfmt  # Restart the binfmt service to load ARM support

Among them, qemu-user-static and binfmt-support are used to achieve cross-architecture emulation, allowing an X86 host to directly execute ARM programs.

2

Building the Root Filesystem

Use mmdebstrap to create the base system, with the following command:

mkdir -p rootfs
sudo mmdebstrap \ 
    --hook-dir=/usr/share/mmdebstrap/hooks/merged-usr \ 
    --include="ca-certificates,locales,sudo,apt,adduser,polkitd,systemd,network-manager,dbus-daemon,apt-utils,bash-completion,curl,vim,bash,deepin-keyring,init,ssh,net-tools,iputils-ping,lshw,iproute2,iptables,procps,wpasupplicant,dmidecode,ntpsec-ntpdate,linux-firmware" \ 
    --architectures=arm64 \ 
    beige \ 
    rootfs \ 
    "deb https://community-packages.deepin.com/beige/ beige main commercial community" \ 
    "deb https://proposed-packages.deepin.com/beige-testing/ unstable/25 main commercial community"

This command specifies the creation of a root filesystem for the ARM64 architecture, including necessary software packages such as system tools, network tools, and debugging tools.

3

Creating the Disk Image

3.1 Creating a Blank Image and Partitioning

Use the following command to create a blank image and partition it:

dd if=/dev/zero of=deepin-raspberrypi.img bs=1M count=4096
sudo fdisk deepin-raspberrypi.img << EOF
np1
+300M
t
p2
w
EOF

The above command creates a 4GB blank image file and partitions it into two partitions: a 300MB FAT32 formatted boot partition and a Linux partition for the remaining space.

3.2 Formatting and Mounting Partitions

Bind the image file to a loop device using losetup, then format and mount the two partitions:

LOOP=$(sudo losetup -Pf --show deepin-raspberrypi.img)
sudo mkfs.fat -F32 "${LOOP}p1"
sudo dosfslabel "${LOOP}p1" bootfs
sudo mkfs.ext4 "${LOOP}p2"
sudo e2label "${LOOP}p2" rootfs
mkdir tmp
sudo mount "${LOOP}p2" tmp
sudo cp -a rootfs/* tmp
sudo mkdir tmp/boot/firmware
sudo mount "${LOOP}p1" tmp/boot/firmware
sudo mount --bind /dev tmp/dev
sudo mount -t proc proc tmp/proc
sudo mount -t sysfs sys tmp/sys
sudo mount -t tmpfs -o "size=99%" tmpfs tmp/tmp
sudo mount -t tmpfs -o "size=99%" tmpfs tmp/var/tmp
sudo mount --bind /etc/resolv.conf tmp/etc/resolv.conf
sudo mount -t devpts devpts tmp/dev/pts

4

Adapting to Raspberry Pi Hardware

4.1 Installing Firmware and Kernel

Download the precompiled firmware from the official Raspberry Pi repository[1] and copy it to the appropriate directory.

git clone --depth=1 https://github.com/raspberrypi/firmware.git
sudo cp -r firmware/boot/* tmp/boot/firmware

4.2 Configuring config.txt

Configure the config.txt file[2] to enable audio, auto-load overlays, set 64-bit mode, etc.

sudo tee tmp/boot/firmware/config.txt <<EOF  # For more options and information see  # http://rptl.io/configtxt  # Some settings may impact device functionality. See link above for details
  # Uncomment some or all of these to enable the optional hardware interfaces  #dtparam=i2c_arm=on  #dtparam=i2s=on  #dtparam=spi=on
  # Enable audio (loads snd_bcm2835)  dtparam=audio=on
  # Additional overlays and parameters are documented  # /boot/firmware/overlays/README
  # Automatically load overlays for detected cameras  camera_auto_detect=1
  # Automatically load overlays for detected DSI displays  display_auto_detect=1
  # Automatically load initramfs files, if found  auto_initramfs=1
  # Enable DRM VC4 V3D driver  dtoverlay=vc4-kms-v3d  max_framebuffers=2
  # Don't have the firmware create an initial video= setting in cmdline.txt.  # Use the kernel's default instead.  disable_fw_kms_setup=1
  # Run in 64-bit mode  arm_64bit=1
  # Disable compensation for displays with overscan  disable_overscan=1
  # Run as fast as firmware / board allows  arm_boost=1
  [cm4]  # Enable host mode on the 2711 built-in XHCI USB controller.  # This line should be removed if the legacy DWC2 controller is required  # (e.g. for USB device mode) or if USB support is not required.  otg_mode=1
  [cm5]  dtoverlay=dwc2,dr_mode=host
  [all]  EOF

4.3 Adding Raspberry Pi Official Sources

mkdir -p tmp/etc/apt/sources.list.d
# Add Raspberry Pi's source, some tools provided by Raspberry Pi need to be downloaded from this software source
echo "deb [trusted=yes] http://archive.raspberrypi.org/debian/ bookworm main" | sudo tee tmp/etc/apt/sources.list.d/raspberrypi.list

4.4 Installing Additional Packages and Kernel

# raspi-config will depend on libfmt9, which is not available in the deepin source as it has been upgraded to libfmt10, download the deb package from Debian
curl -L http://ftp.cn.debian.org/debian/pool/main/f/fmtlib/libfmt9_9.1.0+ds1-2_arm64.deb -o tmp/tmp/libfmt9.deb
curl -L http://ftp.cn.debian.org/debian/pool/main/d/device-tree-compiler/libfdt1_1.6.1-4+b1_arm64.deb -o tmp/tmp/libfdt1.deb

4.5 Entering chroot and Installing Configuration Tools and Kernel

sudo chroot tmp bash
(chroot) apt update -y && apt install -y /tmp/libfmt9.deb /tmp/libfdt1.deb
(chroot) apt install -y raspi-config raspberrypi-sys-mods firmware-brcm80211 raspi-firmware bluez-firmware
(chroot) apt install -y \ 
    linux-image-rpi-v8 \ 
    linux-image-rpi-2712 \ 
    linux-headers-rpi-v8 \ 
    linux-headers-rpi-2712

5

Configuring Boot Parameters

Set the kernel parameters in cmdline.txt to specify the console, root filesystem, and other information.

# Configure cmdline.txt kernel parameters
(chroot) echo "console=serial0,115200 console=tty1 root=LABEL=rootfs rootfstype=ext4 fsck.repair=yes rootwait quiet init=/usr/lib/raspberrypi-sys-mods/firstboot splash plymouth.ignore-serial-consoles" | tee /boot/firmware/cmdline.txt

6

Editing the Partition Table

Configure the /etc/fstab file to ensure the partitions are mounted correctly at system startup.

(chroot) tee /etc/fstab << EOF
proc          /proc           proc    defaults          0       0
LABEL=bootfs  /boot/firmware  vfat    defaults          0       2
LABEL=rootfs  /               ext4    defaults,rw,errors=remount-ro,x-systemd.growfs  0       1
EOF

7

Personalizing the System Configuration

Create a user and configure localization settings, including language, timezone, etc.

# Create user and set password
(chroot) useradd -m deepin && usermod -aG sudo deepin
(chroot) echo 'deepin:deepin' | chpasswd
(chroot) chsh -s /bin/bash deepin
# Uncomment
(chroot) sed -i -E 's/#[[:space:]]*(en_US.UTF-8[[:space:]]+UTF-8)/\1/g' /etc/locale.gen
(chroot) sed -i -E 's/#[[:space:]]*(zh_CN.UTF-8[[:space:]]+UTF-8)/\1/g' /etc/locale.gen
# Generate language settings
(chroot) locale-gen
# Set Chinese
(chroot) tee /etc/locale.conf << EOF
LANG=zh_CN.UTF-8
LANGUAGE=zh_CN
EOF
# Set Shanghai timezone
(chroot) ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

8

Cleaning and Compressing

After completing the above configurations, you can clean the package cache and unmount the mount points.

# Clean package cache
(chroot) apt clean && rm -rf /var/cache/apt/archives/*
(chroot) exit
# Unmount mount points
sudo umount -l tmp
# Force filesystem check
sudo e2fsck -f "${LOOP}p2"
# Detach loop device
sudo losetup -D $LOOP

9

Flashing the Image

This step is recommended to be done using the official Raspberry Pi flashing tool, following the system prompts to flash the created image onto the Raspberry Pi’s storage device.

For detailed steps, please refer to:“Deepin 25 Raspberry Pi Universal Image Launch”

10

Installing the Desktop Environment

If you need to install a desktop environment, you can do so via APT after the system starts, or directly build a complete image with a desktop on the Raspberry Pi device.

export DEBIAN_FRONTEND=noninteractive
sudo apt update
# Packages related to DDE desktop environment
sudo apt install deepin-desktop-environment-{base,cli,core,extras}
# After installing, lightdm is disabled from starting automatically, allow it to start on reboot
sudo systemctl enable lightdm
# Linglong environment
sudo apt install deepin-desktop-environment-ll
# UOS AI, Firefox browser
sudo apt install uos-ai firefox
# If you need to use treeland window manager
sudo apt install treeland ddm
# Disable lightdm auto-start, allow ddm to auto-start
sudo systemctl disable lightdm && sudo systemctl enable ddm
# Stop lightdm, start ddm
sudo systemctl stop lightdm && sudo systemctl enable ddm

11

Creating the Image Script

You can clone the GitHub repository to obtain the script for creating images, facilitating batch creation or automation.

git clone --depth=1 https://github.com/deepin-community/deepin-raspberrypi.git
# Build an image without a desktop environment
cd deepin-raspberrypi
./build.sh
# Build an image with a desktop environment, needs to be built on Raspberry Pi
cd deepin-raspberrypi
./build.sh desktop

A Step-by-Step Guide to Customizing System Images Using Deepin

The above is the complete process of customizing the Deepin system image on the Raspberry Pi. This tutorial concludes here. For detailed explanations of the commands involved in the tutorial, you can click “Read the original text” to view.

Through the above explanation, I believe everyone has understood the process of creating a system disk image. Here, using Deepin and Raspberry Pi as examples, customizing systems for other architectures (such as X86_64, LoongArch64, RISC-V64, etc.) can also refer to this approach.

Thanks again to @空木蓮華 for their contribution and sharing! If you encounter any issues during practice or have any suggestions for our tutorial, feel free to communicate with us on the Deepin community forum.

Related Reading:

[1] Official Raspberry Pi Repositoryhttps://github.com/raspberrypi/firmware/tree/master/boot[2] config.txt

https://www.raspberrypi.com/documentation/computers/config_txt.html

Past Selections | Selection in the past

A Step-by-Step Guide to Customizing System Images Using Deepin

A Step-by-Step Guide to Customizing System Images Using Deepin

Leave a Comment