Production of embedded Linux root file system (BusyBox+Initramfs)

Making rootfs with BusyBox

This article introduces how to use BusyBox to build rootfs, including BusyBox installation, configuration, compilation, related modifications to files and directories and points needing attention
Introduction to current system environment:
OS:Ubuntu20.04.1 LTS
BusyBox: BusyBox 1.32.0
Corss compiler: riscv64 unknown Linux GNU [note]: This is a compiler for riscv64 architecture. The abi mode supported by the tool chain is lp64d
ARCH:rv64imafdc [note]: this means that the architecture is based on RISC-V 64 bit IMAFDC(RV64GC), which is competent for general tasks
[detailed explanation]:
"I" basic integer set, which contains the basic calculation, Load/Store and control flow of integers. All hardware implementations must include this part.
The "M" standard integer multiplication and division extension set adds the multiplication and division instruction in the integer register.
"A" standard operation atomic extension set, which increases atomic reading, writing, modification of memory and synchronization between processors.
"F" standard single precision floating-point extension set, adding floating-point register, calculation instruction and L/S instruction.
"D" standard double precision extension set, extended double precision floating-point register, double precision calculation instruction and L/S instruction.
I+M+F+A+D is abbreviated as "G", which together form a general scalar instruction.
RV32G and RV64G always remain unchanged during subsequent ISA version iterations.

1. Get BusyBox source code

Enter BusyBox's official website https://www.busybox.net , you can see the latest version of BusyBox, which can be downloaded to the local directory by clicking directly.

As shown in the figure above, the latest version is BusyBox 1.32.0. Click directly to download to the local directory and unzip it

imaginemiracle@:busybox-1.32.0$ ls
busybox-1.32.0.tar.bz2
imaginemiracle@:busybox-1.32.0$ tar -jxvf busybox-1.32.0.tar.bz2
imaginemiracle@:busybox-1.32.0$ ls
busybox-1.32.0  busybox-1.32.0.tar.bz2
imaginemiracle@:busybox-1.32.0$ cd busybox-1.32.0/
imaginemiracle@:busybox-1.32.0$ ls
applets     configs        editors    klibc-utils  Makefile                modutils           qemu_multiarch_testing  size_single_applets.sh
applets_sh  console-tools  examples   libbb        Makefile.custom         networking         README                  sysklogd
arch        coreutils      findutils  libpwdgrp    Makefile.flags          NOFORK_NOEXEC.lst  runit                   testsuite
archival    debianutils    include    LICENSE      Makefile.help           NOFORK_NOEXEC.sh   scripts                 TODO
AUTHORS     docs           init       loginutils   make_single_applets.sh  printutils         selinux                 TODO_unicode
Config.in   e2fsprogs      INSTALL    mailutils    miscutils               procps             shell                   util-linux

2. Configure BusyBox

(1) Create directory structure

This directory is used to save the directory files compiled by BusyBox

imaginemiracle@:busybox-1.32.0$ mkdir rootfs_install
imaginemiracle@:busybox-1.32.0$ ls
busybox-1.32.0  busybox-1.32.0.tar.bz2  rootfs_install

(2) menuconfig configuration

imaginemiracle@:busybox-1.32.0$ cd busybox-1.32.0/
imaginemiracle@:busybox-1.32.0$ make menuconfig

Enter Settings

Cancel unnecessary configuration, and mainly set the installation paths of Cross Compiler Perfix and make install, that is, the directory path just created Destination path for 'make install'

3. Compile

imaginemiracle@:busybox-1.32.0$ make ARCH=rv64imafdc
imaginemiracle@:busybox-1.32.0$ make install
imaginemiracle@:busybox-1.32.0$ cd ../rootfs_install
imaginemiracle@:rootfs_install$ ls
bin  linuxrc  sbin  usr

After successful compilation, this directory structure will be generated in the directory just created. Normally, three directories and one file will be generated, namely bin, sbin and usr directories and a linuxrc file;
Compared with the common file system, there are a lot less things, so you need to add and modify these files manually.
Of course, if the specified directory is not added in menuconfig or during make install, make install will save the generated directory structure in the "_install" directory under the busybox source code by default, and the default value of Destination path for 'make install' is/_ install.

4. Add other common directories

imaginemiracle@:rootfs_install$ mkdir bin dev etc lib proc sbin sys usr mnt tmp var
imaginemiracle@:rootfs_install$ mkdir usr/bin usr/lib usr/sbin lib/modules

5. Add a basic configuration file for the / etc directory

There are many ways to add these basic configuration files. Here, you can directly use the examples in busybox to modify them.

imaginemiracle@:rootfs_install$ cp -a ../busybox-1.32.0/examples/bootfloppy/etc/ ./
imaginemiracle@:rootfs_install$ ls etc/
fstab  init.d  inittab  profile

It is worth noting that the inittab file is the first script accessed after the file system is started, and the subsequent files are made by it.

  • Open and modify the inittab file (modify according to the actual situation)
##########Copied source file
#The startup script of the specified system is / etc / init d/rcS
::sysinit:/etc/init.d/rcS
#Specifies to open a login session
::respawn:-/bin/sh
#Specify to open a shell without login authentication in the third virtual terminal
tty2::askfirst:-/bin/sh
#Specifies the command to execute when ctrl+alt+del is pressed
::ctrlaltdel:/bin/umount -a -r

======================================Split line=========================================

##########Modified inittab
# Startup the system                                                                                                                                                                   
::sysinit:/bin/mount -t proc proc /proc                                                                                                                                                
::sysinit:/bin/mount -o remount,rw /                                                                                                                                                  
::sysinit:/bin/mkdir -p /dev/pts                                                                                                                                                       
::sysinit:/bin/mkdir -p /dev/shm                                                                                                                                                     
::sysinit:/bin/mount -a                                                                                                                                                           
::sysinit:/bin/hostname -F /etc/hostname                                                                                                                                           
# now run any rc scripts                                                                                                                                                            
::sysinit:/etc/init.d/rcS                                                                                                                                                          
                                                                                                                                                                                   
# Put a getty on the serial port                                                                                                                                                    
console::respawn:/sbin/getty -L  console 0 vt100 # GENERIC_SERIAL                                                                                                                    
                                                                                                                                                                                   
# Stuff to do for the 3-finger salute                                                                                                                                            
#::ctrlaltdel:/sbin/reboot                                                                                                                                                    
                                                                                                                                                                                  
# Stuff to do before rebooting                                                                                                                                                     
::shutdown:/etc/init.d/rcK                                                                                                                                                         
::shutdown:/sbin/swapoff -a                                                                                                                                                         
::shutdown:/bin/umount -a -r 
  • fstab file, which defines each mount point in the file system (modified according to the actual situation)
##########Copied source file
proc        /proc   proc    defaults    0   0 

======================================Split line=========================================

##########Modified fstab
# <file system> <mount pt>  <type>  <options>   <dump>  <pass>                                                                                   
 /dev/root   /           ext2    rw,noauto   0   1
 proc        /proc       proc    defaults    0   0
 devpts      /dev/pts    devpts  defaults,gid=5,mode=620 0   0
 tmpfs       /dev/shm    tmpfs   mode=0777   0   0
 tmpfs       /tmp        tmpfs   mode=1777   0   0
 tmpfs       /run        tmpfs   mode=0755,nosuid,nodev  0   0
 sysfs       /sys        sysfs   defaults    0   0
  • profile file, which will be the first script to run after entering the terminal login. This file should be familiar with. The usual system environment variables are modified here (according to the actual situation)
##########Copied source file
# /etc/profile: system-wide .profile file for the Bourne shells                                                                                                                          
 
 echo
 echo -n "Processing /etc/profile... "
 # no-op
 echo "Done"
 echo

======================================Split line=========================================

##########Modified profile
export PATH=/bin:/sbin:/usr/bin:/usr/sbin                                                                                                        
 
 if [ "$PS1" ]; then
     if [ "`id -u`" -eq 0 ]; then
         export PS1='# '
     else
         export PS1='$ '
     fi
 fi
 
 export PAGER='/bin/more '
 export EDITOR='/bin/vi'
 
 # Source configuration files from /etc/profile.d
 for i in /etc/profile.d/*.sh ; do
     if [ -r "$i" ]; then
         . $i
     fi
     unset i
 done

5.1. Addition of user login authentication related documents of the terminal

[note]: if the shadow function is enabled in the compilation option of BusyBox, these files need to be added in the etc directory
Add method
(1) Prepare the document content according to the format;
(2) Generated using BusyBox's adderuser tool.

  • passwd file (the content shall be modified according to the actual situation)
#The format of passwd file and the meaning of each field (the seven fields are separated by ":)
#[user name]: [whether to use encryption password, x means yes, not filled in means none, use MD5 and DES encryption]: [user ID]: [group ID]: [comment field]: [login directory]: [shell used]
root:x:0:0:root:/root:/bin/sh                                                                                                                        
daemon:x:1:1:daemon:/usr/sbin:/bin/false
bin:x:2:2:bin:/bin:/bin/false
sys:x:3:3:sys:/dev:/bin/false
sync:x:4:100:sync:/bin:/bin/sync
mail:x:8:8:mail:/var/spool/mail:/bin/false
www-data:x:33:33:www-data:/var/www:/bin/false
operator:x:37:37:Operator:/var:/bin/false
nobody:x:99:99:nobody:/home:/bin/false
  • group file
#group file editing format and the meaning of each field (the four fields are separated by ":")
#[group name]: [whether to use encryption password]: [group ID]: [array pointing to each user name pointer]
root:x:0:                                                                                                                                           
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
kmem:x:9:
wheel:x:10:root
cdrom:x:11:
dialout:x:18:
floppy:x:19:
video:x:28:
audio:x:29:
tape:x:32:
www-data:x:33:
operator:x:37:
utmp:x:43:
plugdev:x:46:
staff:x:50:
lock:x:54:
netdev:x:82:
nogroup:x:99:
users:x:100:
  • shadow file
#The editing format of shadow file and the meaning of each field (9 fields are separated by ":")
#[user name]: [password after encryption, empty means no password is required for login, "*" means the account is disabled]: [number of days from January 1, 1970 to the last time the password has been modified]: [number of days the password cannot be modified by the user]: [number of days after the password must be modified (0 means no modification)]: [number of days after the password expires, the user account is prohibited]: [number of days after the password expires, the user will be warned]: [number of days since January 1, 1970 when the password is prohibited]: [reserved fields]
#[Note 1]: the encrypted string in the second field is generated according to the password set by yourself. The following string represents the password encrypted by the current root user password
#[Note 2]: UNIX stipulates that 0 o'clock on January 1, 1970 is the era of time
root:$1$W.ejfkhq$v0bHAgc4RxSgzFtjRKggP.:10933:0:99999:7:::                                                                                          
daemon:*:10933:0:99999:7:::
bin:*:10933:0:99999:7:::
sys:*:10933:0:99999:7:::
sync:*:10933:0:99999:7:::
mail:*:10933:0:99999:7:::
www-data:*:10933:0:99999:7:::
operator:*:10933:0:99999:7:::
nobody:*:10933:0:99999:7:::

6. Add basic device files to the / dev directory

During debugging, you need to print and send messages to the terminal display through the serial port. Therefore, the two device files (specifically, the device node here) of the serial port console and the terminal under / dev are necessary.

#If the created file system does not have a / dev directory, create a dev directory with mkdir first
#Create console device node
imaginemiracle@:dev$ sudo mknod -m 666 console c 5 1
#Create device node of terminal
imaginemiracle@:dev$ sudo mknod -m 666 null c 1 3
imaginemiracle@:dev$ ls
console  null

7. Create init

Create init in the root directory

imaginemiracle@:rootfs_install$ ln -s ./bin/busybox init
imaginemiracle@:rootfs_install$ ls
bin  dev  etc  init  lib  lib64  linuxrc  media  mnt  opt  proc  root  run  sbin  sys  tmp  usr  var

8. Making root file system with Initramfs

To view the detailed introduction of Initramfs, please click this link: Initramfs-Ubuntu
[note] use the cross compilation tool chain tool to compile it to generate its own applicable kernel image and the loading method through bootloader. This paper will not elaborate too much, but operate according to the actual situation
After completing the construction of rootfs, vmliunx with file system can be compiled by configuring the kernel to support Initramfs and setting the path of rootfs

(1) Use the make menuconfig command to enter the kernel configuration menu
(2) Configure General setup - > [*] initial ram file system and RAM disk (initramfs / initrd) support
(3) Configure General setup - > () initramfs source file (s) [note] write the built rootfs path in parentheses, both absolute and relative

(4) make recompile to generate kernel image
(5) Since the environment I use is the Linux kernel supported by the risc-v architecture provided by sifive and the Berkeley Boot Loader(BBL) written by the University of Berkeley, the generated image will package the BBL and the kernel file vmliux into a BBL In the bin file (vmlinux here is reduced by using striped in the cross compilation tool chain).
(6) Run on the board. Since the kernel does not add support for NETWorking, some exception information will be printed in the execution of some scripts in the file system.

##This completes the introduction of how to generate Linux root file system by using BusyBox and Initramfs

##Attach

#The following is the directory structure of the current rootfs, which is based on the actual needs
imaginemiracle@:rootfs_install$ tree
.
├── bin
│   ├── ash -> busybox
│   ├── busybox
│   ├── cat -> busybox
│   ├── catv -> busybox
│   ├── chattr -> busybox
│   ├── chgrp -> busybox
│   ├── chmod -> busybox
│   ├── chown -> busybox
│   ├── cp -> busybox
│   ├── cpio -> busybox
│   ├── date -> busybox
│   ├── dd -> busybox
│   ├── df -> busybox
│   ├── dmesg -> busybox
│   ├── dnsdomainname -> busybox
│   ├── dumpkmap -> busybox
│   ├── echo -> busybox
│   ├── egrep -> busybox
│   ├── false -> busybox
│   ├── fdflush -> busybox
│   ├── fgrep -> busybox
│   ├── getopt -> busybox
│   ├── grep -> busybox
│   ├── gunzip -> busybox
│   ├── gzip -> busybox
│   ├── hostname -> busybox
│   ├── kill -> busybox
│   ├── linux32 -> busybox
│   ├── linux64 -> busybox
│   ├── ln -> busybox
│   ├── login -> busybox
│   ├── ls -> busybox
│   ├── lsattr -> busybox
│   ├── mkdir -> busybox
│   ├── mknod -> busybox
│   ├── mktemp -> busybox
│   ├── more -> busybox
│   ├── mount -> busybox.
├── bin
│   ├── ash -> busybox
│   ├── busybox
│   ├── cat -> busybox
│   ├── catv -> busybox
│   ├── chattr -> busybox
│   ├── chgrp -> busybox
│   ├── chmod -> busybox
│   ├── chown -> busybox
│   ├── cp -> busybox
│   ├── cpio -> busybox
│   ├── date -> busybox
│   ├── dd -> busybox
│   ├── df -> busybox
│   ├── dmesg -> busybox
│   ├── dnsdomainname -> busybox
│   ├── dumpkmap -> busybox
│   ├── echo -> busybox
│   ├── egrep -> busybox
│   ├── false -> busybox
│   ├── fdflush -> busybox
│   ├── fgrep -> busybox
│   ├── getopt -> busybox
│   ├── grep -> busybox
│   ├── gunzip -> busybox
│   ├── gzip -> busybox
│   ├── hostname -> busybox
│   ├── kill -> busybox
│   ├── linux32 -> busybox
│   ├── linux64 -> busybox
│   ├── ln -> busybox
│   ├── login -> busybox
│   ├── ls -> busybox
│   ├── lsattr -> busybox
│   ├── mkdir -> busybox
│   ├── mknod -> busybox
│   ├── mktemp -> busybox
│   ├── more -> busybox
│   ├── mount -> busybox
│   ├── mountpoint -> busybox
│   ├── mt -> busybox
│   ├── mv -> busybox
│   ├── netstat -> busybox
│   ├── nice -> busybox
│   ├── pidof -> busybox
│   ├── ping -> busybox
│   ├── pipe_progress -> busybox
│   ├── printenv -> busybox
│   ├── ps -> busybox
│   ├── pwd -> busybox
│   ├── rm -> busybox
│   ├── rmdir -> busybox
│   ├── run-parts -> busybox
│   ├── sed -> busybox
│   ├── setarch -> busybox
│   ├── setserial -> busybox
│   ├── sh -> busybox
│   ├── sleep -> busybox
│   ├── stty -> busybox
│   ├── su -> busybox
│   ├── sync -> busybox
│   ├── tar -> busybox
│   ├── touch -> busybox
│   ├── true -> busybox
│   ├── umount -> busybox
│   ├── uname -> busybox
│   ├── usleep -> busybox
│   ├── watch -> busybox
│   └── zcat -> busybox
├── dev
│   ├── console
│   └── null
├── etc
│   ├── dropbear -> /var/run/dropbear
│   ├── fstab
│   ├── group
│   ├── hostname
│   ├── hosts
│   ├── init.d
│   │   ├── rcK
│   │   ├── rcS
│   │   ├── S01logging
│   │   ├── S10mdev
│   │   ├── S20urandom
│   │   ├── S40network
│   │   └── S50dropbear
│   ├── inittab
│   ├── inittab_NoLogin
│   ├── issue
│   ├── mdev.conf
│   ├── mtab
│   ├── network
│   │   ├── if-down.d
│   │   ├── if-post-down.d
│   │   ├── if-pre-up.d
│   │   │   └── wait_iface
│   │   ├── if-up.d
│   │   ├── interfaces
│   │   └── nfs_check
│   ├── nsswitch.conf
│   ├── os-release
│   ├── passwd
│   ├── profile
│   ├── profile.d
│   │   └── umask.sh
│   ├── protocols
│   ├── services
│   └── shadow
├── init -> /bin/busybox
├── lib
│   ├── ld-2.26.so
│   ├── ld-linux-riscv64-lp64d.so.1 -> ld-2.26.so
│   ├── libatomic.so.1 -> libatomic.so.1.2.0
│   ├── libatomic.so.1.2.0
│   ├── libc-2.26.so
│   ├── libcrypt-2.26.so
│   ├── libcrypt.so.1 -> libcrypt-2.26.so
│   ├── libc.so.6 -> libc-2.26.so
│   ├── libdl-2.26.so
│   ├── libdl.so.2 -> libdl-2.26.so
│   ├── libgcc_s.so.1
│   ├── libm-2.26.so
│   ├── libm.so.6 -> libm-2.26.so
│   ├── libnsl-2.26.so
│   ├── libnsl.so.1 -> libnsl-2.26.so
│   ├── libnss_files-2.26.so
│   ├── libnss_files.so.2 -> libnss_files-2.26.so
│   ├── libpthread-2.26.so
│   ├── libpthread.so.0 -> libpthread-2.26.so
│   ├── libresolv-2.26.so
│   ├── libresolv.so.2 -> libresolv-2.26.so
│   ├── librt-2.26.so
│   ├── librt.so.1 -> librt-2.26.so
│   ├── libutil-2.26.so
│   └── libutil.so.1 -> libutil-2.26.so
├── lib64 -> lib
├── linuxrc -> bin/busybox
├── media
├── mnt
├── opt
├── proc
├── root
│   └── Miracle
│       └── test
│           ├── helloworld
│           ├── helloworld.c
│           ├── test
│           └── test.c
├── run
├── sbin
│   ├── arp -> ../bin/busybox
│   ├── blkid -> ../bin/busybox
│   ├── devmem -> ../bin/busybox
│   ├── fdisk -> ../bin/busybox
│   ├── freeramdisk -> ../bin/busybox
│   ├── fsck -> ../bin/busybox
│   ├── fstrim -> ../bin/busybox
│   ├── getty -> ../bin/busybox
│   ├── halt -> ../bin/busybox
│   ├── hdparm -> ../bin/busybox
│   ├── hwclock -> ../bin/busybox
│   ├── ifconfig -> ../bin/busybox
│   ├── ifdown -> ../bin/busybox
│   ├── ifup -> ../bin/busybox
│   ├── init -> ../bin/busybox
│   ├── ip -> ../bin/busybox
│   ├── ipaddr -> ../bin/busybox
│   ├── iplink -> ../bin/busybox
│   ├── iproute -> ../bin/busybox
│   ├── iprule -> ../bin/busybox
│   ├── iptunnel -> ../bin/busybox
│   ├── klogd -> ../bin/busybox
│   ├── loadkmap -> ../bin/busybox
│   ├── losetup -> ../bin/busybox
│   ├── makedevs -> ../bin/busybox
│   ├── mdev -> ../bin/busybox
│   ├── mkswap -> ../bin/busybox
│   ├── modprobe -> ../bin/busybox
│   ├── nameif -> ../bin/busybox
│   ├── pivot_root -> ../bin/busybox
│   ├── poweroff -> ../bin/busybox
│   ├── reboot -> ../bin/busybox
│   ├── route -> ../bin/busybox
│   ├── runlevel -> ../bin/busybox
│   ├── setconsole -> ../bin/busybox
│   ├── start-stop-daemon -> ../bin/busybox
│   ├── sulogin -> ../bin/busybox
│   ├── swapoff -> ../bin/busybox
│   ├── swapon -> ../bin/busybox
│   ├── switch_root -> ../bin/busybox
│   ├── sysctl -> ../bin/busybox
│   ├── syslogd -> ../bin/busybox
│   ├── udhcpc -> ../bin/busybox
│   ├── uevent -> ../bin/busybox
│   ├── vconfig -> ../bin/busybox
│   └── watchdog -> ../bin/busybox
├── sys
├── tmp
├── usr
└── var
    ├── cache
    ├── lib
    │   └── misc
    ├── lock
    ├── log
    ├── run
    ├── spool
    ├── tmp
    └── www
#The total size is 2.9M, which is caused by the large occupation of related library files
imaginemiracle@:rootfs_install$ du -h
614K	./bin
1.0K	./dev
18K	./etc/init.d
0	./etc/network/if-down.d
0	./etc/network/if-post-down.d
1.0K	./etc/network/if-pre-up.d
0	./etc/network/if-up.d
9.5K	./etc/network
512	./etc/profile.d
66K	./etc
2.2M	./lib
0	./media
0	./mnt
0	./opt
0	./proc
25K	./root/Miracle/test
25K	./root/Miracle
25K	./root
0	./run
31K	./sbin
0	./sys
0	./tmp
0	./usr
0	./var/cache
0	./var/lib/misc
0	./var/lib
0	./var/lock
0	./var/log
0	./var/run
0	./var/spool
0	./var/tmp
0	./var/www
4.0K	./var
2.9M	.

Tags: Linux kernel risc-v

Posted by gotDNS on Mon, 02 May 2022 12:20:39 +0300