Table of Contents
- Hi3798MV200 Entu N2 NS-1 (1): Device introduction and flashing instructions
- Hi3798MV200 Entu N2 NS-1 (2): HiNAS use and modification
- Hi3798MV200 Entu N2 NS-1 (3): Make Ubuntu rootfs
- Hi3798MV200 Entu N2 NS-1 (4): Make Debian rootfs
About the root file system rootfs
In Linux, all files and directories are organized into a tree structure, and the root file system, rootfs, the root filesystem, is located at the top of the file tree (path ‘/’). The Linux kernel passes root =
The root file system contains key files for system startup and operation. The system bootloader will execute initialization scripts (such as rcS, init.d, profile) after the root file system is mounted.
If the entire Linux operating system is regarded as a hierarchical relationship, the root file system is a module located above the kernel. For the same hardware and architecture, the difference between various Linux distributions lies in the root file system, while the underlying kernel part is almost the same . By making the root file system, you can replace it with other distributions and customize your own minimal installation.
File preparation
Bottom bag
This example uses a new version of Debian 10, replaced by Ubuntu20.04.
Extract driver parts from stretch.tar.bz2, located in /lib/modules/4.4.35-hi3798mv2x/
Download ubuntu-base
Download the ubuntu-base package from the domestic mirror site
- https://mirrors.ustc.edu.cn/ubuntu-cdimage/ubuntu-base/releases/
- https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cdimage/ubuntu-base/releases/
Unzip
Create a working directory locally, extract the compressed package to the working directory, pay attention to use sudo
+ -p
(-p, --preserve-permissions) parameters, keep the original owner and original permissions
mkdir workroot sudo tar -xpf ubuntu-base-20.04.5-base-arm64.tar.gz -C workroot/
The initial directory size is about 77MB. You can check the file directory under workroot and see if the owner is root.
About why use sudo
Even if you use tar’s --same-owner flag, you will still need to extract the files as root to preserve ownership.
--same-owner flag is on by default for root.
–no-same-owner, extract files as yourself, which is default for ordinary users
Prepare resolv.conf
The resolv.conf in the base system is empty, and nameserver needs to be set, otherwise the domain name cannot be resolved when the target system apt install after chroot
Option one, copy
Copy resolv.conf to the target system
sudo cp /etc/resolv.conf workroot /etc/resolv.conf
Option 2, write directly
echo "nameserver 127.0.0.53" | sudo tee workroot /etc/resolv.conf
Copy qemu-xxx-static
Install qemu-user-static, this package contains binary executable files of various architectures, which will be installed to /usr/bin
sudo apt install qemu-user-static
For armhf, copy qemu-arm-static; for arm64 copy qemu-aarch64-static
#armhf sudo cp /usr/bin/qemu-arm-static workroot /usr/bin/ #arm64 sudo cp /usr/bin/qemu-aarch64-static workroot /usr/bin/
Check whether the file format is correct before proceeding to the next step, use qemu-arm-static for 32-bit armhf, use qemu-aarch64-static for 64-bit arm64
#armhf sudo chroot workroot/ /usr/bin/qemu-arm-static /bin/ls #arm64 sudo chroot workroot/ /usr/bin/qemu-aarch64-static /bin/ls
If the file architecture does not match, it will prompt - /bin/ls: Invalid ELF image for this architecture
Modify the target system software source
vi workroot/etc/apt/sources.list
Replace with USTC source
: %s/http:\/\/ports.ubuntu.com\/ubuntu-ports\//http:\/\/mirrors.ustc.edu.cn\/ubuntu-ports\//gc
Mount the target system
Option 1: Mount manually
mount directory
sudo mount -t proc /proc workroot/proc sudo mount -t sysfs /sys workroot/sys sudo mount -o bind /dev workroot/dev sudo mount -o bind /dev/pts workroot /dev/pts
switch root directory
sudo chroot workroot/
If the previous checks are ok, but this step always prompts '/bin/bash': Exec format error
, check whether binfmts is enabled
update-binfmts --display
Normally it should be displayed as follows, the corresponding format is enabled,
qemu-aarch64 (enabled): package = qemu-user-static ... qemu-arm (enabled): package = qemu-user-static ...
If it is displayed as disabled, you need to check whether any software is not installed. There may be conflicts in the Ubuntu environment where Docker is installed.
$ mount | grep binfmt systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=29,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=18150) binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)
Option 2: Mount using script
The above operations can be simplified by a script
#!/bin/bash mnt() {<!-- --> echo "MOUNTING" sudo mount -t proc /proc ${2}proc sudo mount -t sysfs /sys ${2}sys sudo mount -o bind /dev ${2}dev sudo mount -o bind /dev/pts ${2}dev/pts sudo chroot ${2} } umnt() {<!-- --> echo "UNMOUNTING" sudo umount ${2}proc sudo umount ${2}sys sudo umount ${2}dev/pts sudo umount ${2}dev } if [ "$1" == "-m" ] & amp; & amp; [ -n "$2" ] ; then mnt $1 $2 elif [ "$1" == "-u" ] & amp; & amp; [ -n "$2" ]; then umnt $1 $2 else echo "" echo "Either 1'st, 2'nd or both parameters were missing" echo "" echo "1'st parameter can be one of these: -m(mount) OR -u(umount)" echo "2'nd parameter is the full path of rootfs directory(with trailing '/')" echo "" echo "For example: ch-mount -m /media/sdcard/" echo "" echo 1st parameter : ${1} echo 2nd parameter : ${2} the fi
When the target system environment is required
./mount.sh -m workroot/
Custom rootfs content
root@Box:/# uname -a Linux Box 5.15.0-52-generic #58~20.04.1-Ubuntu SMP Thu Oct 13 13:09:46 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux # check mount root@Box:/# mount /proc on /proc type proc (rw,relatime) /sys on /sys type sysfs (rw,relatime) udev on /dev type devtmpfs (rw,nosuid,noexec,relatime,size=6965676k,nr_inodes=1741419,mode=755,inode64) devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
Add driver file
Rootfs can be started only by using the built-in driver of the kernel, but some onboard peripherals, such as SATA hard disk and USB, will not be recognized because there is no driver. These drivers need to be manually put into rootfs.
Through uname -r
, you can see that the architecture of the target system is 4.4.35-hi3798mv2x
, so you can determine the path of the driver as
/lib/modules/4.4.35-hi3798mv2x/
From the bottom package prepared earlier, extract the driver file and put it in this directory. The structure is similar to
modules └── 4.4.35-hi3798mv2x ├── kernel │ ├── crypto │ ├── drivers │ ├── fs │ ├── lib │ └── net ├── modules.alias ├── modules.alias.bin ├── modules. builtin ├── modules.builtin.alias.bin ├── modules.builtin.bin ├── modules.dep ├── modules.dep.bin ├── modules.devname ├── modules. order ├── modules.softdep ├── modules.symbols └── modules.symbols.bin
Install basic software
# 77M -> 300M apt update # 300M -> 304M apt install nano sudo vim-tiny
Modify the software source vi /etc/apt/sources.list
, replace it with USTC source
: %s/http:\/\/ports.ubuntu.com\/ubuntu-ports\//http:\/\/mirrors.ustc.edu.cn\/ubuntu-ports\//gc
It is much faster to install other software
apt upgrade # 304M -> 440M apt install openssh-server # 440M -> 445M apt install u-boot-tools net-tools sysstat smartmontools network-manager
in the installed package
- openssh-server provides ssh service
- u-boot-tools provides fw_printenv and fw_setenv methods for modifying UBOOT boot parameters
- net-tools provides common tools such as ifconfig and netstat
- sysstat provides common tools such as iostat
Basic settings
set network
mkdir /etc/network/interfaces.d echo auto eth0 > etc/network/interfaces.d/eth0 echo iface eth0 inet dhcp >> etc/network/interfaces.d/eth0
Set a password for the root user Note Don't forget this step
passwd
Open root user ssh access, edit /etc/ssh/sshd_config, find
#PermitRootLogin prohibit-password
replace with
PermitRootLogin yes
Configure the serial port for login, modify the file /etc/systemd/system/getty.target.wants/[email protected]
vi /etc/systemd/system/getty.target.wants/getty\@tty1.service
Will
ConditionPathExists=/dev/tty0
change to actual name
ConditionPathExists=/dev/ttyAMA0
Clean up files
After the installation is complete, clean up apt
apt autoremove apt-get autoclean apt-get clean apt clean # 368M after the end
Unmount the target system
On the target system, exit exits
After the end, you must first cancel the mount
Option 1: Unmount manually
sudo umount workroot/proc sudo umount workroot/sys sudo umount workroot /dev/pts sudo umount workroot /dev
Option 2: Unmount via script
If passed by script, it is
./mount.sh -u workroot/
Make rootfs image file
# Generate an empty image of appropriate size, this size refers to du -h workroot dd if=/dev/zero of=rootfs.img bs=1M count=1024 # format mkfs.ext4 rootfs.img # or mkfs -t ext4 rootfs.img # Mount an empty image mkdir rootfs sudo mount rootfs.img rootfs/ # write to file, preserve permissions sudo cp -rfp workroot/* rootfs/ # unmount sudo umount rootfs/ # Check the file system and automatically repair it e2fsck -p -f rootfs.img # make the image compact resize2fs -M rootfs.img
Problems and solutions
Root can log in via serial port, but cannot log in via ssh
This is because ssh prohibits root login by default, edit /etc/ssh/sshd_config, find
#PermitRootLogin prohibit-password
replace with
PermitRootLogin yes
Then systemctl restart sshd
restarts the sshd service
Partition free space is 0
This is because the image is compressed and written, the partition size is the image size, and the partition needs to be expanded by resize2fs /dev/[partition]
Option 1: Use scripts, execute manually
Create /usr/bin/local_resize.sh, the content is as follows, chmod + x
is set to executable
#!/bin/bash rootfs_partition=/dev/$(lsblk -l|grep /|awk '{print $1}') logger -t "resize-disk[$$]" "resizing $rootfs_partition" if [ "$(echo $rootfs_partition | grep "mmc")" = "" ]; then rootfs_disk=$(echo "$rootfs_partition" |sed -E -e 's/^(.*)[0-9] + /\1/g') else rootfs_disk=$(echo "$rootfs_partition" |sed -E -e 's/^(.*)p[0-9] + /\1/g') the fi if [ "$rootfs_disk" = "/dev/mmcblk0" ]; then resize2fs $rootfs_partition 2> & 1 > /dev/null else rootfs_partition_num=$(echo "$rootfs_partition" |sed -E -e 's/^.*([0-9] + )/\1/g') startfrom=$(fdisk -l ${<!-- -->rootfs_disk} -o device,start|grep ${<!-- -->rootfs_partition}|awk '{print $2}') (echo d; echo $rootfs_partition_num; echo n; echo p; echo $rootfs_partition_num; echo $startfrom; echo ; echo p; echo w;) | fdisk $rootfs_disk sync resize2fs $rootfs_partition the fi logger -t "resize-disk[$$]" "resized $rootfs_partition"
Solution 2: Use systemd service to execute at first startup
Add /usr/sbin/local-resize2fs.sh , chmod + x
set as executable
#!/bin/bash if [ ! -f /etc/first_init ]; then rootfs_partition=/dev/$(lsblk -l|grep /|awk '{print $1}') logger -t "resize-disk[$$]" "resizing $rootfs_partition" if [ "$(echo $rootfs_partition | grep "mmc")" = "" ]; then rootfs_disk=$(echo "$rootfs_partition" |sed -E -e 's/^(.*)[0-9] + /\1/g') else rootfs_disk=$(echo "$rootfs_partition" |sed -E -e 's/^(.*)p[0-9] + /\1/g') the fi if [ "$rootfs_disk" = "/dev/mmcblk0" ]; then resize2fs $rootfs_partition 2> & 1 > /dev/null else rootfs_partition_num=$(echo "$rootfs_partition" |sed -E -e 's/^.*([0-9] + )/\1/g') startfrom=$(fdisk -l ${<!-- -->rootfs_disk} -o device,start|grep ${<!-- -->rootfs_partition}|awk '{print $2}') #lastsector=$(fdisk -l ${rootfs_disk} -o device,end|grep ${rootfs_partition}|awk '{print $2}') (echo d; echo $rootfs_partition_num; echo n; echo p; echo $rootfs_partition_num; echo $startfrom; echo ; echo p; echo w;) | fdisk $rootfs_disk sync resize2fs $rootfs_partition the fi echo `date + %s%N` > /etc/first_init logger -t "resize-disk[$$]" "resized $rootfs_partition" the fi exit 0
Add service: /etc/systemd/system/resize2fs.service
[Unit] Description=resize2fs local filesystem Before=local-fs-pre.target DefaultDependencies=no [Service] Type=oneshot TimeoutSec=infinity ExecStart=/usr/sbin/local-resize2fs.sh RemainAfterExit=true [Install] RequiredBy=local-fs-pre.target
Add the soft link of resize2fs.service under /etc/systemd/system/local-fs-pre.target.wants/ to make it effective
Reference
- https://wiki.t-firefly.com/en/ROC-RK3399-PC/linux_build_ubuntu_rootfs.html