5. Root File System (rootfs)¶
5.1. Overview of Root File System¶
The kernel is the core of the Linux operating system and the file system is the main tool for communication between the user and the operating system. So to use Linux, it is important to understand the file system principles first.
The root file system structure is a tree directory structure starting with “/” as the “root”, and a device (ex: eMMC) is mounted on the root directory when the kernel program image (uImage) is booted. The root file system is usually stored in internal memory (DRAM) or non-volatile memory (FLASH), or in a file system accessible via the network (NFS). All applications and libraries are placed in the file system according to categories, and the following diagram shows the root file system directory structure.
/ Root directory
├── bin Executable file
├── dev Device file
├── etc System configuration file (ex: startup file)
├── home User Directory
├── init Script executed at boot
├── kdump Kernel debugging directory
├── lib Libraries include glibc, shared library and kernel modules
├── mnt Mount points for temporary file systems
├── proc Virtual file system for kernel and process information
├── sbin System managed executable file
├── sys System device and file hierarchy, providing kernel data
├── usr This directory contains user-defined applications and files
└── var Store system logs and service program files
5.2. Rootfs¶
This section describes how the file system is composed, and the detailed path is in ramdisk/rootfs/
5.2.1. Pre-build Rootfs Structure¶
The structure of the file system is divided into three main types of directories, which are iterated over Rootfs layer by layer, and are described below:
Basic rootfs:
At this stage, we provide pre-build rootfs files based on the following four types of Arch
Arch |
Libc |
Pre-build ramdisk path |
---|---|---|
Arm |
glibc |
ramdisk/rootfs/common_arm/ |
Arm |
uclibc |
ramdisk/rootfs/common_uclibc/ |
Aarch64 |
glibc |
ramdisk/rootfs/common_arm64/ |
Riscv64 |
glibc |
ramdisk/rootfs/common_riscv64/ |
Riscv64 |
musl |
ramdisk/rootfs/common_musl64/ |
Processor configuration rootfs:
We place all Processorset dependent boot settings in ramdisk/rootfs/overlay/$CHIP
Third-party rootfs:
We place all third-party software compiled library, utility, and related file in
ramdisk/rootfs/public/

It can be decided by means of a menu which Third-party software should be placed in Rootfs
$ menuconfig


5.2.2. Compile the rootfs from buildroot¶
This section is an example of how to generate the rootfs from buildroot and run it on EVB. If the pre-build rootfs described in the previous section is used, this section can be ignored.
Get buildroot repository
https://github.com/sophgo/buildroot-2021.05
Configure buildroot
$ cd buildroot-2021.05
$ make menuconfig

Set Arch Info & Toolchain & Packages
There are some default configuration files in the configs directory, which can be quickly configured by running make cvitek_XXX_defconfig
Set the architecture
ARM

RISCV

Set the Toochain
ARM

RISCV

Set the software package

Compile the buildroot package
$ make
Obtain the rootfs, which is located in output/images/rootfs.tar
Modify build/Makefile so that SDK can use rootfs generated by buildroot
buildroot-prepare:$(OUTPUT_DIR)/rootfs
$(call print_target)
#clean_all
rm -rf $(ROOTFS_DIR)/*
#extract buildroot roofs
tar xf $(BR_DIR)/output/images/rootfs.tar -C $(ROOTFS_DIR)
rootfs-pack:export CROSS_COMPILE_KERNEL=$(patsubst "%",%,$(CONFIG_CROSS_COMPILE_KERNEL))
rootfs-pack:export CROSS_COMPILE_SDK=$(patsubst "%",%,$(CONFIG_CROSS_COMPILE_SDK))
rootfs-pack:$(OUTPUT_DIR)/rawimages
#rootfs-pack:rootfs-prepare
rootfs-pack:buildroot-prepare
rootfs-pack:
$(call print_target)
${Q}printf '\033[1;36;40m Striping rootfs \033[0m\n'
ifeq (${FLASH_SIZE_SHRINK},y)
${Q}printf 'remove unneeded files'
${Q} $(COMMON_TOOLS_PATH)/spinand_tool/clean_rootfs.sh $(ROOTFS_DIR)
endif
${Q}find $(ROOTFS_DIR) -name "*.ko" -type f -printf 'striping %p\n' -exec $(CROSS_COMPILE_KERNEL)strip --strip-unneeded {} \;
${Q}find $(ROOTFS_DIR) -name "*.so*" -type f -printf 'striping %p\n' -exec $(CROSS_COMPILE_KERNEL)strip --strip-all {} \;
${Q}find $(ROOTFS_DIR) -executable -type f ! -name "*.sh" ! -path "*etc*" ! -path "*.ko" -printf 'striping %p\n' -exec $(CROSS_COMPILE_SDK)strip --strip-all {} 2>/dev/null \;
Generate the new ROOTFS burnable image files
$ pack_rootfs
Burn to the board by the steps mentioned in Chapter 3
5.2.3. Package rootfs as a Burnable Image File¶
Package the rootfs folder from the previous steps with the mksquashfs tool, compress it with XZ, and the end product is rootfs.spinor / rootfs.spinand / rootfs.emmc, which can be burned to Flash.
Refer to the rootfs-pack in build/Makefile for details:
rootfs-pack:export CROSS_COMPILE_KERNEL=$(patsubst "%",%,$(CONFIG_CROSS_COMPILE_KERNEL))
rootfs-pack:export CROSS_COMPILE_SDK=$(patsubst "%",%,$(CONFIG_CROSS_COMPILE_SDK))
rootfs-pack:$(OUTPUT_DIR)/rawimages
rootfs-pack:rootfs-prepare
rootfs-pack:
$(call print_target)
${Q}printf '\033[1;36;40m Striping rootfs \033[0m\n'
ifeq (${FLASH_SIZE_SHRINK},y)
${Q}printf 'remove unneeded files'
${Q} $(COMMON_TOOLS_PATH)/spinand_tool/clean_rootfs.sh $(ROOTFS_DIR)
endif
${Q}find $(ROOTFS_DIR) -name "*.ko" -type f -printf 'striping %p\n' -exec $(CROSS_COMPILE_KERNEL)strip --strip-unneeded {} \;
${Q}find $(ROOTFS_DIR) -name "*.so*" -type f -printf 'striping %p\n' -exec $(CROSS_COMPILE_KERNEL)strip --strip-all {} \;
${Q}find $(ROOTFS_DIR) -executable -type f ! -name "*.sh" ! -path "*etc*" ! -path "*.ko" -printf 'striping %p\n' -exec $(CROSS_COMPILE_SDK)strip --strip-all {} 2>/dev/null \;
ifeq ($(STORAGE_TYPE),spinor)
${Q}mksquashfs $(ROOTFS_DIR) $(OUTPUT_DIR)/rawimages/rootfs.sqsh -root-owned -comp xz
else
${Q}mksquashfs $(ROOTFS_DIR) $(OUTPUT_DIR)/rawimages/rootfs.sqsh -root-owned -comp xz -e mnt/cfg/*
endif
ifeq ($(STORAGE_TYPE),spinand)
${Q}python3 $(COMMON_TOOLS_PATH)/spinand_tool/mkubiimg.py --ubionly $(FLASH_PARTITION_XML) ROOTFS $(OUTPUT_DIR)/rawimages/rootfs.sqsh $(OUTPUT_DIR)/rawimages/rootfs.spinand -b $(CONFIG_NANDFLASH_BLOCKSIZE) -p $(CONFIG_NANDFLASH_PAGESIZE)
${Q}rm $(OUTPUT_DIR)/rawimages/rootfs.sqsh
else
${Q}mv $(OUTPUT_DIR)/rawimages/rootfs.sqsh $(OUTPUT_DIR)/rawimages/rootfs.$(STORAGE_TYPE)
endif
5.2.4. Linux kernel Auto-Load rootfs¶
The Linux kernel will determine which device the rootfs is located on based on the root= variable in the bootargs set by uboot
'root=...'
This argument tells the kernel what device is to be used
as the root filesystem while booting. The default of this
setting is determined at compile time, and usually is the
value of the root device of the system that the kernel was
built on. To override this value, and select the second
floppy drive as the root device, one would use
'root=/dev/fd1'.
The root device can be specified symbolically or
numerically. A symbolic specification has the form
/dev/XXYN, where XX designates the device type (e.g., 'hd'
for ST-506 compatible hard disk, with Y in 'a'–'d'; 'sd'
for SCSI compatible disk, with Y in 'a'–'e'), Y the driver
letter or number, and N the number (in decimal) of the
partition on this device.
Note that this has nothing to do with the designation of
these devices on your filesystem. The '/dev/' part is
purely conventional.
The more awkward and less portable numeric specification
of the above possible root devices in major/minor format
is also accepted. (For example, /dev/sda3 is major 8,
minor 3, so you could use 'root=0x803' as an alternative.)