Back to Blog

Yaffs2 File System Porting to mini2440

#LinuxKernel#Bash#Script#System#Makefile#Compiler

Yaffs2 File System Porting to mini2440

Most development boards now support the Yaffs2 file system. It is a file system specifically created for embedded devices, especially those using NAND flash as storage. Earlier Yaffs versions only supported small-page (512-byte/page) NAND flash, while Yaffs2 supports large-page NAND flash.

The so-called root file system involves creating various directories and files within them. For example, executable programs are stored in /bin and /sbin directories, configuration files in /etc, and library files in /lib. Let's begin the file system porting process.

I. Preparation

  1. Obtaining Yaffs2 Source Code

    The latest Yaffs2 source code can be downloaded from http://www.yaffs.net/node/346. If using the git tool, enter the following command in the terminal:

    #git clone git://www.aleph1.co.uk/yaffs2
    

    This will download the Yaffs2 source code to the current directory.

  2. Download Busybox-1.13.3

    Busybox-1.13.3 can be downloaded from http://www.busybox.net/downloads/.

  3. Download Yaffs2 Creation Tools

    You can download mkyaffs2image.tgz from the FriendlyARM website. After decompression, there are two executable files: one for small pages and one for large-page NAND flash, named mkyaffs2image-128M. I initially made a mistake here; my NAND flash is 128MB, but I followed online instructions using mkyaffs2image, which kept giving "fake bad block" warnings. After careful analysis, it was clear that the NAND flash couldn't have so many bad blocks at once, and the root file system provided by their company worked without issues. The problem was with the Yaffs2 creation tool. This is because the ECC checksums for these two NAND flash sizes are different, meaning the spare area sizes are different, leading to ECC checksum errors.

  4. Link Libraries

    When creating the root file system, link libraries are needed. Here, we directly use the link libraries from FriendlyARM's root file system. Download root_qtopia.tgz from the website and use the libraries under its lib directory.

  5. Patching the Kernel with Yaffs2

    Then, navigate to the Yaffs2 source code directory and execute:

    #cd yaffs2
    #./patch-ker.sh c /opt/mini2440/linux-2.6.33.3
    

    Now, enter the linux-2.6.32.2/fs directory, and you will see a new yaffs2 directory.

    The command above performs three actions:

    (1) Modifies fs/Kconfig in the kernel. Adds the line: source "fs/yaffs2/Kconfig"

    (2) Modifies fs/Makefile in the kernel. Adds the line: obj-$(CONFIG_YAFFS_FS) += yaffs2/

    (3) Creates the yaffs2 directory under fs/ in the kernel. Copies Makefile.kernel from the Yaffs2 source directory to fs/yaffs2/Makefile in the kernel. Copies the Kconfig file from the Yaffs2 source directory to fs/yaffs2/ in the kernel. Copies *.c and *.h files from the Yaffs2 source directory to fs/yaffs2/ in the kernel.

  6. Configuring the Kernel to Support Yaffs2 File System

    In the Linux kernel source code root directory, run make menuconfig. Navigate to "File Systems", then "Miscellaneous filesystems", find "YAFFS2 file system support", and select it (as shown in the figure above). This adds Yaffs2 file system support to the kernel. Save and exit. Then, in the command line, execute make uImage. Do not execute make mini2440_defconfig again, as doing so would invalidate the previous configuration. I made this basic mistake myself.

II. Building the Root File System

  1. Root File System Directory Structure

    • bin: Stores basic commands usable by all users.
    • sbin: Stores basic system commands used for system startup, repair, etc.
    • usr: Stores shared, read-only programs and data.
    • proc: An empty directory, often used as a mount point for the proc file system.
    • dev: Stores device files and other special files.
    • etc: Stores system configuration files, including startup files.
    • lib: Stores shared libraries and loadable modules (i.e., drivers). Shared libraries are used to start the system and run executables in the root file system.
    • boot: Static files used by the boot loader.
    • home: User home directories, including home directories for service accounts like FTP.
    • mnt: A mount point for temporarily mounting a file system, usually an empty directory. Empty subdirectories can also be created within it.
    • opt: Directory for additional software installations on the host.
    • root: Home directory for the root user.
    • tmp: Stores temporary files, usually an empty directory.
    • var: Stores variable data.
  2. Creating Root File System Directories

    Navigate to opt/mini2440/fs, create a shell script named create_rootfs_bash to build the root file system directories, and change its execution permissions.

    #chmod +x create_rootfs_bash
    

    In the kernel directory, run ./create_rootfs_bash. The script content is as follows:

    #!/bin/sh
    echo "------Create rootfs directons start...--------"
    mkdir rootfs
    cd rootfs
    echo "--------Create root,dev....----------"
    mkdir root dev etc boot tmp var sys proc lib mnt home usr
    mkdir etc/init.d etc/rc.d etc/sysconfig
    mkdir usr/sbin usr/bin usr/lib usr/modules
    echo "make node in dev/console dev/null"
    mknod -m 600 dev/console c 5 1
    mknod -m 600 dev/null c 1 3
    mkdir mnt/etc mnt/jffs2 mnt/yaffs mnt/data mnt/temp
    mkdir var/lib var/lock var/run var/tmp
    chmod 1777 tmp
    chmod 1777 var/tmp
    echo "-------make direction done---------"
    

    The permissions for the tmp directory are changed to enable the sticky bit. Enabling this bit for the tmp directory ensures that only the user who created a file within tmp has the right to delete it.

  3. Creating Dynamic Link Libraries

    We directly use FriendlyARM's dynamic link libraries. First, download FriendlyARM's root file system, decompress it to get root_qtopia, and then copy all files from its Lib directory to our lib/ folder.

  4. Compiling and Installing Busybox

    Busybox is an open-source project under the GPL v2 license. During its development, file size was optimized, and limited system resources (such as memory) were considered. Busybox can automatically generate the bin, sbin, usr directories and the linuxrc file required for the root file system.

    Decompress Busybox, then:

    #cd busybox-1.13.3
    

    // Modify the Makefile in this directory to set the platform to ARM and the compiler to the default cross-compiler.

    CROSS_COMPILE ?=arm-linux-  // Approximately line 164
    ARCH ?=arm  // Approximately line 189
    

    Configure Busybox in the busybox-1.13.3 directory. We will only focus on the changes. Execute make menuconfig. The configuration options (only changed ones are listed) are as follows:

    (1) Busybox Settings---> Build Options---> [*] Build BusyBox as a static binary (no shared libs) Busybox Library Tuning ---> (1024) Maximum length of input [*] vi-style line editing commands [*] Fancy shell prompts

    (2) Linux System Utilities ---> [*] Support /etc/mdev.conf [*] Support command execution at device addition/removal

    (3) Linux Module Utilities---> [ ] simplified modutils [*] insmod [*] rmmod [*] lsmod [*] modprobe

  5. Compiling Busybox

    Compile Busybox to the specified directory: #cd /opt/mini2440/busybox-1.13.3

    make CONFIG_PREFIX=/opt/kernel/rootfs install
    

    That is: execute make CONFIG_PREFIX=<root_file_system_directory> install

    This will generate the bin, sbin, usr directories and the linuxrc file in the rootfs directory.

  6. Creating the etc Directory

    The init process creates other child processes based on the /etc/inittab file, such as calling scripts to configure IP addresses, mounting other file systems, and finally starting the shell.

    (1) Copy passwd, group, shadow files from the host's etc directory to rootfs/etc.

    (2) Create mdev.conf file under etc/.

    Content:

    # system all-writable devices
    full  0:0  0666
    null  0:0  0666
    ptmx  0:0  0666
    random  0:0  0666
    tty  0:0  0666
    zero  0:0  0666
    
    # console devices
    tty[0-9]* 0:5 0660
    vc/[0-9]* 0:5 0660
    
    # serial port devices
    s3c2410_serial0  0:5  0666  =ttySAC0
    s3c2410_serial1  0:5  0666  =ttySAC1
    s3c2410_serial2  0:5  0666  =ttySAC2
    s3c2410_serial3  0:5  0666  =ttySAC3
    
    # loop devices
    loop[0-9]*  0:0  0660  =loop/
    
    # i2c devices
    i2c-0  0:0  0666  =i2c/0
    i2c-1  0:0  0666  =i2c/1
    
    # frame buffer devices
    fb[0-9]  0:0  0666
    
    # input devices
    mice  0:0  0660  =input/
    mouse.*  0:0  0660  =input/
    event.*  0:0  0660  =input/
    ts.*  0:0  0660  =input/
    
    # rtc devices
    rtc0  0:0  0644  >rtc
    rtc[1-9]  0:0  0644
    
    # misc devices
    mmcblk0p1  0:0  0600  =sdcard */bin/hotplug.sh
    sda1  0:0  0600  =udisk * /bin/hotplug.sh
    

    (3) etc/inittab file: Following the example of Busybox's examples/inittab file, create an inittab file in etc/ with the following content:

    #etc/inittab
    ::sysinit:/etc/init.d/rcS
    ::askfirst:-/bin/sh
    ::ctrlaltdel:/sbin/reboot
    ::shutdown:/bin/umount -a -r
    

    (4) Create etc/init.d/rcS file:

    This is a script file where automatic execution commands can be added.

    #!/bin/sh
    
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    
    runlevel=S    // Run level
    prevlevel=N
    
    umask 022     // Folder umask
    export PATH runlevel prevlevel
    echo"--------- munt all--------"
    mount –a      // Mount all file systems specified in /etc/fstab
    echo /sbin/mdev>/proc/sys/kernel/hotplug
    mdev -s
    echo "*************************"
    echo "***********yuyang ARM************"
    echo "Kernel version:linux-2.33.3"
    echo "Author:yuyang"
    echo "Data:2010,05,08"
    echo "*************************"
    /bin/hostname -F /etc/sysconfig/HOSTNAME  // Hostname
    

    Finally, change its attributes to make it executable:

    sudo chmod +x etc/init.d/rcS
    

    (5) Create a new file HOSTNAME in etc/sysconfig with the content "yuyang-mini2440".

    (6) Create etc/fstab file:

    The content is as follows, indicating that after executing the "mount -a" command, proc, tmpfs, and all other file systems included in this file will be mounted.

    #device mount-point type option dump fsck order
    proc /proc proc defaults 0 0
    tmpfs /tmp tmpfs defaults 0 0
    none /tmp ramfs defaults 0 0
    sysfs /sys sysfs defaults 0 0
    mdev /dev ramfs defaults 0 0
    

    (7) Create etc/profile file:

    #Ash profile
    #vim:syntax=sh
    #No core file by defaults
    #ulimit -S -c 0>/dev/null 2>&1
    USER="id -un"
    LOGNAME=USER
    PS1='[\u@\h\W]#'
    PATH=USER PS1='[\u@\h\W]#' PATH=PATH
    HOSTNAME='/bin/hostname'
    export USER LOGNAME PS1 PATH
    

III. Creating the Root File System Image File

As mentioned earlier, my NAND flash is 128MB, so I need to use FriendlyARM's mkyaffs2image-128M executable to generate the image file. Use the command mkyaffs2image-128M rootfs rootfs.img to create the root file system image file.

Download the generated rootsfs.img file to the root file system area of the NAND flash. Then, boot from NAND flash to see the boot information. However, this is currently just a very basic Linux system; it still lacks drivers for networking, LCD, etc. So, there's still a lot to port, which will be the next task.