• Mini2440之linux内核移植之yaffs2根文件系统移植


    什么是根文件系统?理论上说一个嵌入式设备如果内核能运行起来,且不需要用户进程的话(估计这种情况很少),是不需要文件系统的。文件系统简单的说就是一种目录结构,由于linux操作系统的设备在系统中是以文件的形式存在,将这些文件分类管理以及提供和内核交互的接口,就形成了一定的目录结构也就是文件系统。文件系统是为用户反映系统的一种形式,为用户提供一个检测控制系统的接口。

    而根文件系统,就是一种特殊的文件系统。那么根文件系统和普通的文件系统有什么区别呢?借用书上的话说就是,根文件系统就是内核启动时挂载的第一个文件系统。由于根文件系统是启动时挂载的第一个文件系统,那么根文件系统就要包括Linux启动时所必须的目录和关键性的文件,例如Linux 启动时都需要有用户进程 init 对应的文件,在Linux挂载分区时一定要会找 /etc/fstab这个挂载文件等,根文件系统中还包括了许多的应用程序,如 /bin目录下的命令等。任何Linux启动时所必须的文件的文件系统都可以称为根文件系统。

    一个典型的嵌入式Linux根文件系统目录如下所示:

    目录 内容
    bin 系统命令和工具
    dev 系统设备文件
    etc 系统初始化脚本和配置文件
    lib 系统运行库文件
    proc proc文件系统
    sbin 系统管理员命令和工具
    sys sysfs文件系统
    tmp 临时文件
    usr 用户命令和工具,下分usr/bin和usr/sbin目录
    var 系统运行产生的可变数据

    要构建一个可用的Linux根文件系统,需要的二进制和库都不少,完全从零开始也是不现实的,推荐参考其它现有可用的文件系统,在原基础上按需修改;或者使用文件系统制作工具如 BusyBox 来实现文件系统的生成。

    一、编译、安装、配置 busybox

    busybox编译和环境和有很大的关系,我的操作系统版本为:

    root@zhengyang:/work/sambashare/drivers/1.hello_dev# lsb_release -a
    LSB Version:    core-9.20160110ubuntu0.2-amd64:core-9.20160110ubuntu0.2-noarch:security-9.20160110ubuntu0.2-amd64:security-9.20160110ubuntu0.2-noarch
    Distributor ID: Ubuntu
    Description:    Ubuntu 16.04.7 LTS
    Release:        16.04
    Codename:       xenial

    我尝试了不同版本buybox和arm-linux-gcc后,发现有些版本编译成功后,做成的根文件系统,在linux-5.2.8挂载时会失败。最终发现:

    • busybox-1.25.0 + arm-linux-gcc 4.8.3

    编译运行成功了,下面我们就介绍这个环境的搭建。

    1.1 下载源码

    根文件系统是根据busybox来制作的。下载地址:https://busybox.net/downloads/

    这里我们就以1.31版本为例进行编译安装介绍:

    注意:一般你使用什么版本的交叉编译器来编译linux内核时,文件系统中的所有程序也要使用同样的交叉编译器来编译。

    下载完成后解压:

    tar -jxvf busybox-1.25.0.tar.bz2

    1.2 配置busybox

    在路径busybox-1.25.0下运行如下命令,使用默认配置:

    cd ./busybox-1.25.0
    make defconfig # 使用默认配置

    然后进入图像化配置页面,修改配置 :

    make menuconfig

    进入Busybox Settings,配置如下参数:

    Build Options --->

    • Cross compile prefix:/usr/local/arm/4.8.3/bin/arm-linux-

    • additional CFLAGS: -march=armv4t; s3c2440支持的指令集
    • []Build BusyBox as a static binary(no shared libs)  静态编译,取消动态库
    •  [*] Build Shared libbusybox 使用动态库

    编译方式有两种:

    • 第一种是以静态方式编译,即生成的busybox不需要动态库的支持就能运行。这样做我们就不需要部署动态库了,缺点就是自己写的程序在这个根文件系统中是不能运行的,因为缺少动态库库的支持。
    • 第二种方式使用动态编译,这样的话我们就需要部署动态库了,在linux动态库文件是以so为后缀,而windows下文件是以dll为后缀。

    这里我们指定了arm-linux-gcc 4.8.3编译器的路径,这里就不具体介绍编译器如何安装了。

    继续配置:

    Linux System Utilities --->

    • [] nsenter

    Coreutils --->

    • []sync

    1.3 修改源码

    因为编译时会出现错误,所以需要进行源码修改,这里参考文章64位ubuntu 12.04系统编译busybox遇到的问题处理办法进行修改。

    复制/usr/include/linux/fs.h拷贝到busybox的include文件中:

    cp /usr/include/linux/fs.h ./include

    修改include/fs.h,屏蔽以下3个头文件(否则编译时会提示找不到头文件):

    //#include <linux/limits.h>
    //#include <linux/ioctl.h>
    //#include <linux/types.h>

    屏蔽以下几个结构体(否则编译时会提示找不到类型定义):

    #if 0
    struct fstrim_range {
            __u64 start;
            __u64 len;
            __u64 minlen;
    };
    
    /* And dynamically-tunable limits and defaults: */
    struct files_stat_struct {
            unsigned long nr_files;         /* read only */
            unsigned long nr_free_files;    /* read only */
            unsigned long max_files;                /* tunable */
    };
    
    struct inodes_stat_t {
            long nr_inodes;
            long nr_unused;
            long dummy[5];          /* padding for sysctl ABI compatibility */
    };
    #endif

    修改util-linux/blkdiscard.c中对fs.h头文件的包含方式:

    #include <linux/fs.h>修改为#include "fs.h"。

    1.4 编译

    运行命令:

    make

    然后查看当前路径下是否存在busybox:

    root@zhengyang:/work/sambashare/busybox-1.25.0# ll busybox
    -rwxr-xr-x 1 root root 1093048 1月  22 22:12 busybox*

    执行make install:

    make install

    make install的目的就是将编译生成的可执行程序及其依赖的库文件、配置文件、头文件安装到当前系统中指定(一般都可以自己指定安装到哪个目录下,如果不指定一般都有个默认目录)的目录下,生成_install 文件夹:

    root@zhengyang:/work/sambashare/busybox-1.25.0# ll _install/
    总用量 24
    drwxr-xr-x  6 root root 4096 2月   9 21:45 ./
    drwxr-xr-x 38 root root 4096 2月   9 21:45 ../
    drwxr-xr-x  2 root root 4096 2月   9 21:45 bin/
    drwxr-xr-x  2 root root 4096 2月   9 21:45 lib/
    lrwxrwxrwx  1 root root   11 2月   9 21:36 linuxrc -> bin/busybox*
    drwxr-xr-x  2 root root 4096 2月   9 21:36 sbin/
    drwxr-xr-x  4 root root 4096 2月   9 21:36 usr/

    里面有5个文件: bin lib linuxrc sbin usr ,linuxrc -> bin/busybox这个linuxrc其实就是个符号链接。bin、sbin、usr这三个目录里都是二进制命令工具,lib里面是库文件,这还不足以构成 一个可用的根文件系统,必须进行其它完善工作,才能构建一个可用的根文件系统。

    二、构建根文件系统

    新建一个目录用来存放制作的根文件系统,可以命名为rootfs。将利用BusyBox生成的二进制文件及目录,即_install目录下的所有文件及目录复制到rootfs目录下。

    mkdir ../rootfs
    cp
    -a _install/* ../rootfs/

    2.1 添加库文件

    切换到rootfs路径下:

    cd ../rootfs

    找到交叉编译工具里的动态库复制到lib目录下:

    cp -a /usr/local/arm/4.8.3/arm-none-linux-gnueabi/libc/armv4t/lib/*so* ./lib

    -a保留权限,复制软链接本身,递归复制。

    查看库文件:

    root@zhengyang:/work/sambashare/rootfs# ls lib
    ld-2.17.so               libgomp.so.1.0.0       libnss_db.so.2          libpthread.so.0
    ld-2.18.so               libid3tag.so           libnss_dns-2.17.so      libresolv-2.17.so
    ld-2.9.so                libid3tag.so.0         libnss_dns-2.18.so      libresolv-2.18.so
    ld-linux.so.3            libid3tag.so.0.3.0     libnss_dns-2.9.so       libresolv-2.9.so
    libanl-2.17.so           libjpeg.so             libnss_dns.so.2         libresolv.so.2
    libanl-2.18.so           libjpeg.so.62          libnss_files-2.17.so    librt-2.17.so
    libanl-2.9.so            libjpeg.so.62.0.0      libnss_files-2.18.so    librt-2.18.so
    libanl.so.1              libm-2.17.so           libnss_files-2.9.so     librt-2.9.so
    libBrokenLocale-2.17.so  libm-2.18.so           libnss_files.so.2       librt.so.1
    libBrokenLocale-2.18.so  libm-2.9.so            libnss_hesiod-2.17.so   libSegFault.so
    libBrokenLocale-2.9.so   libmad.so              libnss_hesiod-2.18.so   libssp.so
    libBrokenLocale.so.1     libmad.so.0            libnss_hesiod-2.9.so    libssp.so.0
    libbusybox.so.1.25.0     libmad.so.0.2.1        libnss_hesiod.so.2      libssp.so.0.0.0
    libc-2.17.so             libmemusage.so         libnss_nis-2.17.so      libstdc++.so
    libc-2.18.so             libm.so.6              libnss_nis-2.18.so      libstdc++.so.6
    libc-2.9.so              libmudflap.so          libnss_nis-2.9.so       libstdc++.so.6.0.13
    libcidn-2.18.so          libmudflap.so.0        libnss_nisplus-2.17.so  libstdc++.so.6.0.16
    libcidn.so.1             libmudflap.so.0.0.0    libnss_nisplus-2.18.so  libstdc++.so.6.0.16-gdb.py
    libcrypt-2.17.so         libmudflapth.so        libnss_nisplus-2.9.so   libthread_db-1.0.so
    libcrypt-2.18.so         libmudflapth.so.0      libnss_nisplus.so.2     libthread_db.so.1
    libcrypt-2.9.so          libmudflapth.so.0.0.0  libnss_nis.so.2         libts-0.0.so.0
    libcrypt.so.1            libnsl-2.17.so         libpcprofile.so         libts-0.0.so.0.1.1
    libc.so.6                libnsl-2.18.so         libpng12.so             libts.so
    libdl-2.17.so            libnsl-2.9.so          libpng12.so.0           libutil-2.17.so
    libdl-2.18.so            libnsl.so.1            libpng12.so.0.35.0      libutil-2.18.so
    libdl-2.9.so             libnss_compat-2.17.so  libpng.so               libutil-2.9.so
    libdl.so.2               libnss_compat-2.18.so  libpng.so.3             libutil.so.1
    libgcc_s.so              libnss_compat-2.9.so   libpng.so.3.35.0        libuuid.so
    libgcc_s.so.1            libnss_compat.so.2     libpthread-2.17.so      libuuid.so.1
    libgomp.so               libnss_db-2.17.so      libpthread-2.18.so      libuuid.so.1.2
    libgomp.so.1             libnss_db-2.18.so      libpthread-2.9.so

    随便查看一个文件的属性信息,可以看到都是基于armv4t指令集:

    root@zhengyang:/work/sambashare/rootfs# arm-linux-readelf -A ./lib/libc.so.6
    Attribute Section: aeabi
    File Attributes
      Tag_CPU_name: "4T"
      Tag_CPU_arch: v4T
      Tag_ARM_ISA_use: Yes
      Tag_THUMB_ISA_use: Thumb-1
      Tag_ABI_PCS_wchar_t: 4
      Tag_ABI_FP_rounding: Needed
      Tag_ABI_FP_denormal: Needed
      Tag_ABI_FP_exceptions: Needed
      Tag_ABI_FP_number_model: IEEE 754
      Tag_ABI_align_needed: 8-byte
      Tag_ABI_align_preserved: 8-byte, except leaf SP
      Tag_ABI_enum_size: int

    这里只是拷贝动态链接库。一般开发程序使用动态编译需要板子上动态库的支持才能运行,所以拷贝动态库。

    一般使用gcc编译后的可执行文件、目标文件和动态库都带有调试信息和符号信息,这些在调试的时候用到,但是却增大了文件的大小。通常在PC上调试,或者调试时使用这些带有调试信息和符号信息的库文件,程序发布后使用去掉这些信息的库文件,可以大大缩小根文件系统的体积。这里我们去掉这些信息,方法是使用strip工具:

     cd ./lib
    arm-linux-strip ./*

    2.2 构建etc目录

    初始化配置脚本放在在/etc目录下,用于系统启动所需的初始化配置脚本。BusyBox提供了一些初始化范例脚本,在examples/bootfloppy/etc/目录下:

    root@zhengyang:/work/sambashare/busybox-1.25.0# ll examples/bootfloppy/etc/
    总用量 24
    drwxr-xr-x 3 root root 4096 12月  5  2018 ./
    drwxr-xr-x 3 root root 4096 12月  5  2018 ../
    -rw-r--r-- 1 root root   33 12月  5  2018 fstab
    drwxr-xr-x 2 root root 4096 12月  5  2018 init.d/
    -rw-r--r-- 1 root root  100 12月  5  2018 inittab
    -rw-r--r-- 1 root root  133 12月  5  2018 profile

    在rootfs目录,创建etc文件夹:

    mkdir etc

    将这些配置文件复制到新制作的根文件系统etc目录下。

    root@zhengyang:/work/sambashare/rootfs# cp -a ../busybox-1.25.0/examples/bootfloppy/etc/* ./etc
    /root@zhengyang:/work/sambashare/rootfs# ll etc 总用量 24 drwxr-xr-x 3 root root 4096 1月 23 22:05 ./ drwxr-xr-x 13 root root 4096 1月 23 21:54 ../ -rw-r--r-- 1 root root 33 12月 5 2018 fstab drwxr-xr-x 2 root root 4096 12月 5 2018 init.d/ -rw-r--r-- 1 root root 100 12月 5 2018 inittab -rw-r--r-- 1 root root 133 12月 5 2018 profile

    1. 修改/etc/inittab文件

    /etc/inittab文件是init进程解析的配置文件,通过这个配置文件决定执行哪个进程,何时执行。将文件修改为:

    # 系统启动时
    ::sysinit:/etc/init.d/rcS
    
    # 系统启动按下Enter键时
    ::askfirst:-/bin/sh
    
    # 按下Ctrl+Alt+Del键时
    ::ctrlaltdel:/sbin/reboot
    
    # 系统关机时
    ::shutdown:/sbin/swapoff -a
    ::shutdown:/bin/umount -a -r
    
    # 系统重启时
    ::restart:/sbin/init

    以上内容定义了系统启动时,关机时,重启时,按下Ctrl+Alt+Del键时执行的进程。

    2. 修改/etc/init.d/rcS文件

    #!/bin/sh
    
    # 挂载 /etc/fstab 中定义的所有文件系统
    /bin/mount -a
    
    # 挂载虚拟的devpts文件系统用于用于伪终端设备
    /bin/mkdir -p /dev/pts
    /bin/mount -t devpts devpts /dev/pts
    
    # 使用mdev动态管理u盘和鼠标等热插拔设备
    /bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
    
    # 扫描并创建节点
    /sbin/mdev -s

    修改init.d文件权限:

     chmod -R 777 init.d/*

    3. 修改/etc/fstab 

    /etc/fstab文件存放的是文件系统信息。在系统启动后执行/etc/init.d/rcS文件里/bin/mount -a命令时,自动挂载这些文件系统。

    # <file system>    <mount point>    <type>    <options>    <dump>    <pass>     
    proc                  /proc          proc     defaults       0         0
    sysfs                 /sys           sysfs    defaults       0         0
    tmpfs                 /tmp           tmpfs    defaults       0         0
    tmpfs                 /dev           tmpfs    defaults       0         0

    这里我们挂载的文件系统有三个proc、sysfs和tmpfs,在内核中proc和sysfs默认都支持,而tmpfs是没有支持的,我们需要添加tmpfs的支持。

    4. 修改/etc/profile文件

    /etc/profile文件作用是设置环境变量,每个用户登录时都会运行它,将文件内容修改为:

    # 主机名
    export HOSTNAME=zy
    
    # 用户名
    export USER=root
    
    # 用户目录
    export HOME=/root
    
    # 终端默认提示符
    export PS1="[$USER@$HOSTNAME:\$PWD]\# "    
    
    # 环境变量
    export PATH=/bin:/sbin:/usr/bin:/usr/sbin
    
    # 动态库路径
    export LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH

    2.3 构建dev目录

    在rootfs目录,创建dev文件夹:

    mkdir dev

    创建终端文件:

    sudo mknod dev/console c 5 1
    sudo mknod dev/null c 1 3

    2.4 构建其他文件

    mkdir mnt proc tmp sys root

    三、根文件系统类型

    如果文件系统已经布局完成, 则可以发到目标中了。通常会制作一个镜像然后通过某种方式固化到目标系统中,具体采用哪种根文件系统类型发布需要根据资源状况、内核情况和系统需求等方面进行裁决:

    • 硬件方面:至少需要考虑主存储介质的类型和大小如FLASH是NOR FLASH还是NAND FLASH,RAM的大小等;
    • 内核方面: 则需考虑所裁剪后的内核支持哪些文件系统,采用哪根文件系统最合适, 能满足性、速度等要求;
    • 系统需求方面:要考虑运行速度、是否可写压缩等因素;

    常见的可用于根文件系统类型有ramdisk 、cramfs、jffs2 、yaffs/yaffs2和 ubifs等,各类型的特性如表所列:

    类型 介质 是否压缩 是否可写 掉电保存 存在于RAM中
    ramdisk  
    cramfs   -
    jffs2 NOR FLASH
    yaffs/yaffs2 NAND FLASH
    ubifs NAND FLASH

    尽管文件系统固件以某一种文件系统的镜像发布,但是整个文件系统实际上还是并存多种逻辑文件系统的。例如,一个系统根文件系统以ubifs挂载,但是/dev目录却是以tmpfs挂载的、/sys目录挂载的是sysfs文件系统。

    四、制作.yaffs2根文件系统

    YAFFS目前有yaffs、yaffs2两个版本,一般来说:

    • yaffs对小页(512B+16B/页)的NAND FLASH(64M)有很好的支持;
    • yaffs2对大页(2K+64B/页)的NAND FLASH(128M、256M或者更大)支持更好;

    Mini2440开发板就是将采用了的256MB的Nand Flash(型号K9F2G08U0C)

    4.1 下载yaffs2源码

    下载:

    git clone git://www.aleph1.co.uk/yaffs2
    root@zhengyang:/work/sambashare# git clone git://www.aleph1.co.uk/yaffs2
    正克隆到 'yaffs2'...
    remote: Enumerating objects: 9284, done.
    remote: Counting objects: 100% (9284/9284), done.
    remote: Compressing objects: 100% (5813/5813), done.
    remote: Total 9284 (delta 7389), reused 4363 (delta 3374)
    接收对象中: 100% (9284/9284), 3.85 MiB | 6.00 KiB/s, 完成.
    处理 delta 中: 100% (7389/7389), 完成.
    检查连接... 完成。
    root@zhengyang:/work/sambashare# ll
    总用量 165132
    drwxr-xr-x 26 root root      4096 1月  23 22:49 ./
    drwxr-xr-x  7 root root      4096 1月  22 23:37 ../
    drwxrwxrwx  5 root root      4096 1月  23 00:05 10.bootloader/
    drwxrwxrwx  6 root root      4096 1月  23 00:05 11.dm9000/
    drwxrwxrwx  2 root root      4096 1月  23 00:05 1.led_asm/
    drwxrwxrwx  2 root root      4096 1月  23 00:05 2.led_c/
    drwxrwxrwx  2 root root      4096 1月  23 00:05 3.clock/
    drwxrwxrwx  6 root root      4096 1月  23 00:05 4.uart/
    drwxrwxrwx  5 root root      4096 1月  23 00:05 5.int/
    drwxrwxrwx  5 root root      4096 1月  23 00:05 6.nand_flash/
    drwxrwxrwx  7 root root      4096 1月  23 00:05 7.lcd/
    drwxrwxrwx  5 root root      4096 1月  23 00:05 8.adc/
    drwxrwxrwx  5 root root      4096 1月  23 00:05 9.sdram/
    drwxr-xr-x 37 root root      4096 1月  23 00:25 busybox-1.25.0/
    drwxrwxrwx  2 root root      4096 1月  22 23:56 images/
    drwxrwxr-x 24 root root      4096 1月  23 20:58 linux-5.2.8/
    -rw-r--r--  1 root root 164485696 8月  10  2019 linux-5.2.8.tar.gz
    drwxrwxrwx  2 root root      4096 1月  22 23:56 mini2440.jflash/
    drwxr-xr-x 13 root root      4096 1月  23 21:54 rootfs/
    -rw-r--r--  1 root root   4493588 1月  23 22:27 rootfs-jffs2.bin
    drwxrwxrwx  3 root root      4096 1月  22 23:56 SJF2440烧写工具/
    drwxr-xr-x  2 root root      4096 1月  23 00:23 tools/
    drwxrwxrwx 23 root root      4096 1月  23 00:12 u-boot-2016.05-crop/
    drwxrwxrwx 23 root root      4096 1月  23 00:21 u-boot-2016.05-linux/
    drwxrwxrwx 23 root root      4096 1月  23 00:14 u-boot-2016.05-nand-flash/
    drwxrwxrwx 23 root root      4096 1月  23 00:05 u-boot-2016.05-nor-flash/
    drwxr-xr-x  9 root root      4096 1月  23 22:56 yaffs2/
    drwxrwxrwx  5 root root      4096 1月  23 00:05 zk/
    -rwxrw-rw-  1 root root        91 10月 17 23:19 问题解决.txt*

    4.2 配置内核支持yaffs2

    将yaffs文件夹复制到linux-5.2.8/fs路径下,使内核支持yaffs2文件系统。,:

    cd yaffs2
    ./patch-ker.sh c m /work/sambashare/linux-5.2.8   // 将yaffs2文件夹copy到linux-5.2.8/fs下

    我的linux内核路径在/work/sambashare/linux-5.2.8,修改成你们自己的。

    进入linux内核源码目录:

    cd ../linux-5.2.8
    make s3c2440_defconfig 
    make menuconfig

    在上一节配置的基础上,继续配置linux内核使其支持yaffs2根文件系统:

    File systems  --->

     [*] Miscellaneous filesystems  --->

     <*>   yaffs2 file system support

    Kernel Features --->

    [*] Use the ARM EABI to compile the kernel

    [*]   Allow old ABI binaries to run with this kernel (EXPERIMENTAL)

    选中后按下Y,并保存为s3c2440_defconfig:

    存档:

    mv s3c2440_defconfig ./arch/arm/configs/

    重新编译linux内核,记得切换交叉编译环境为arm-linux-gcc 4.6.4版本:

    make s3c2440_defconfig    // 必须执行,不然配置的不会生效
    make uImage

    编译内核,将会出现一些错误:

    出现错误的原因,主要是由于yaffs2的更新速度跟不上内核的更新速度,所以只能自己做一些修改。

     在fs/yaffs2/yaffs_vfs.c文件中,yaffs2对不同版本的linux做了适配,但是当前我下载yaffs2仅仅支持到4.16版本的内核,再高版本就需要自己做适配。这里我们参考移植linux-5.4.26到jz2440进行修改。

    4.3 内核编译错误解决

    1. current_kernel_time64被移除:

    fs/yaffs2/yaffs_vfs.c:1411:3: error: implicit declaration of function 'current_kernel_time64' [-Werror=implicit-function-declaration]

    从上述信息来看,很可能是current_kernel_time64这个接口被移除了,那我们就需要找到其替代者。最快速的解决方法就是去网上搜索,大概率这类错误已经被前人解决。这里给结论:使用ktime_get_coarse_real_ts64替代。其实最权威的资料是内核文档,遇到这类问题直接搜文档,比如这里的时间接口,见linux-5.2.28\Documentation\core-api\timekeeping.rst:

     修改yaffs_vfs.c文件:

    #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0))
    #define update_dir_time(dir) do {\
            (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
        } while (0)
    #elif (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0))
    #define update_dir_time(dir) do {\
            (dir)->i_ctime = (dir)->i_mtime = current_kernel_time(); \
        } while (0)
    #else
    #define update_dir_time(dir) do {\
            ktime_get_coarse_ts64(&(dir)->i_mtime); \
            (dir)->i_ctime = (dir)->i_mtime; \
        } while (0)
    #endif

    2. MS_RDONLY未声明

    再次编译内核,错误信息为:

    fs/yaffs2/yaffs_vfs.c:2741:25: error: 'MS_RDONLY' undeclared (first use in this function)
    fs/yaffs2/yaffs_vfs.c:2741:25: note: each undeclared identifier is reported only once for each function it appears in
    fs/yaffs2/yaffs_vfs.c: In function 'yaffs_internal_read_super':
    fs/yaffs2/yaffs_vfs.c:2918:17: error: 'MS_NOATIME' undeclared (first use in this function)
    fs/yaffs2/yaffs_vfs.c:2920:30: error: 'MS_RDONLY' undeclared (first use in this function)
    scripts/Makefile.build:278: recipe for target 'fs/yaffs2/yaffs_vfs.o' failed
    make[2]: *** [fs/yaffs2/yaffs_vfs.o] Error 1
    scripts/Makefile.build:489: recipe for target 'fs/yaffs2' failed
    make[1]: *** [fs/yaffs2] Error 2
    Makefile:1074: recipe for target 'fs' failed
    make: *** [fs] Error 2

    解决方案很简单, 修改yaffs_vfs.c文件:添加头文件:

    #include <uapi/linux/mount.h>

    3. current_kernel_time被移除

    再次编译内核,错误信息为:

    fs/yaffs2/yaffs_attribs.c: In function 'yaffs_load_current_time':
    fs/yaffs2/yaffs_attribs.c:55:2: error: implicit declaration of function 'current_kernel_time' [-Werror=implicit-function-declaration]
    fs/yaffs2/yaffs_attribs.c:55:19: error: request for member 'tv_sec' in something not a structure or union
    cc1: some warnings being treated as errors
    scripts/Makefile.build:278: recipe for target 'fs/yaffs2/yaffs_attribs.o' failed
    make[2]: *** [fs/yaffs2/yaffs_attribs.o] Error 1
    scripts/Makefile.build:489: recipe for target 'fs/yaffs2' failed
    make[1]: *** [fs/yaffs2] Error 2
    Makefile:1074: recipe for target 'fs' failed
    make: *** [fs] Error 2

    定位到fs/yaffs2/yaffs_attribs.c报错的函数:

    void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c)
    {
        obj->yst_mtime = Y_CURRENT_TIME;
        if (do_a)
            obj->yst_atime = obj->yst_mtime;
        if (do_c)
            obj->yst_ctime = obj->yst_mtime;
    }

    搜索关键字Y_CURRENT_TIME:

    root@zhengyang:/work/sambashare/linux-5.2.8# grep "Y_CURRENT_TIME" fs/yaffs2/* -nR
    fs/yaffs2/yaffs_attribs.c:55:   obj->yst_mtime = Y_CURRENT_TIME;
    fs/yaffs2/yportenv.h:67:#define Y_CURRENT_TIME CURRENT_TIME.tv_sec
    fs/yaffs2/yportenv.h:69:#define Y_CURRENT_TIME current_kernel_time().tv_sec
    fs/yaffs2/yportenv.h:74:#define Y_CURRENT_TIME CURRENT_TIME
    fs/yaffs2/yportenv.h:76:#define Y_CURRENT_TIME current_kernel_time()

    用新的接口重新定义这个宏即可,修改fs/yaffs2/yportenv.h文件:

    #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
    #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0))
    #define Y_CURRENT_TIME CURRENT_TIME.tv_sec
    #else
    //#define Y_CURRENT_TIME current_kernel_time().tv_sec
    #define Y_CURRENT_TIME ({ struct timespec64 ts64; ktime_get_coarse_ts64(&ts64); ts64.tv_sec; })
    #endif
    #define Y_TIME_CONVERT(x) (x).tv_sec
    #else
    #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0))
    #define Y_CURRENT_TIME CURRENT_TIME
    #else
    #define Y_CURRENT_TIME current_kernel_time()
    #endif
    #define Y_TIME_CONVERT(x) (x)
    #endif

    进行上述修改后,重新执行make uImage,编译通过。

    4.4  制作工具mkyaffs2image

    yaffs2文件系统是针对NAND FLASH的文件系统,其制作工具为mkyaffs2image。不同容量的NAND FLASH,工具也是不一样的。

    mkyaffs2image是在yaffs2文件系统的utils目录下,只把其中的chunkSize 、spareSize与 pagesPerBlock几个变量,按照你使用的NAND FLASH芯片参数的改一下就可以用。

    cd yaffs2/utils/
    vim mkyaffs2image.c

    修改为:

    // Adjust these to match your NAND LAYOUT:
    #define chunkSize 2048
    #define spareSize 64
    #define pagesPerBlock 64

    然后在当前路径下进行编译:

    make

    出现若干错误,错误信息如下:

    root@zhengyang:/work/sambashare/yaffs2/utils# make
    gcc -c -O2 -Wall -Werror -DCONFIG_YAFFS_UTIL -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline mkyaffsimage.c -o mkyaffsimage.o
    In file included from mkyaffsimage.c:30:0:
    yaffs_guts.h:497:2: error: unknown type name ‘YTIME_T’
      YTIME_T yst_uid;
      ^
    yaffs_guts.h:498:2: error: unknown type name ‘YTIME_T’
      YTIME_T yst_gid;
      ^
    yaffs_guts.h:499:2: error: unknown type name ‘YTIME_T’
      YTIME_T yst_atime;
      ^
    yaffs_guts.h:500:2: error: unknown type name ‘YTIME_T’
      YTIME_T yst_mtime;
      ^
    yaffs_guts.h:501:2: error: unknown type name ‘YTIME_T’
      YTIME_T yst_ctime;
      ^
    yaffs_guts.h:1076:1: error: unknown type name ‘YTIME_T’
     YTIME_T yaffs_oh_ctime_fetch(struct yaffs_obj_hdr *oh);
     ^
    yaffs_guts.h:1077:1: error: unknown type name ‘YTIME_T’
     YTIME_T yaffs_oh_mtime_fetch(struct yaffs_obj_hdr *oh);
     ^
    yaffs_guts.h:1078:1: error: unknown type name ‘YTIME_T’
     YTIME_T yaffs_oh_atime_fetch(struct yaffs_obj_hdr *oh);
     ^
    Makefile:56: recipe for target 'mkyaffsimage.o' failed
    make: *** [mkyaffsimage.o] Error 1

    定义到../yaffs_guts.h文件错误信息所在行:

    #ifdef CONFIG_YAFFS_WINCE
        //these are always 64 bits
        u32 win_ctime[2];
        u32 win_mtime[2];
        u32 win_atime[2];
    #else
        //these can be 32 or 64 bits
        YTIME_T yst_uid;
        YTIME_T yst_gid;
        YTIME_T yst_atime;
        YTIME_T yst_mtime;
        YTIME_T yst_ctime;
    #endif

    这个好解决,在../yaffs_guts.h中加上如下定义::

    #ifndef YTIME_T
    #define YTIME_T  time_t             
    #endif

    再次编译,出现新的错误:

    In file included from mkyaffs2image.c:35:0:
    yaffs_endian.h:28:15: error: unknown type name ‘u64’
     static inline u64 swap_u64(u64 val)
                   ^
    yaffs_endian.h:28:28: error: unknown type name ‘u64’
     static inline u64 swap_u64(u64 val)
                                ^
    yaffs_endian.h: In function ‘swap_ytime_t’:
    yaffs_endian.h:43:32: error: ‘u64’ undeclared (first use in this function)
      if (sizeof(YTIME_T) == sizeof(u64))
                                    ^
    yaffs_endian.h:43:32: note: each undeclared identifier is reported only once for each function it appears in
    yaffs_endian.h:44:10: error: implicit declaration of function ‘swap_u64’ [-Werror=implicit-function-declaration]
       return swap_u64(val);
              ^
    yaffs_endian.h:44:3: error: nested extern declaration of ‘swap_u64’ [-Werror=nested-externs]
       return swap_u64(val);
       ^
    cc1: all warnings being treated as errors
    Makefile:56: recipe for target 'mkyaffs2image.o' failed
    make: *** [mkyaffs2image.o] Error 1

    在../yaffs_endian.h文件添加如下定义:

    typedef unsigned long long u64;

    再次编译,编译成功:

    root@zhengyang:/work/sambashare/yaffs2/utils# make
    gcc -c -O2 -Wall -Werror -DCONFIG_YAFFS_UTIL -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline mkyaffsimage.c -o mkyaffsimage.o
    gcc -c -O2 -Wall -Werror -DCONFIG_YAFFS_UTIL -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline yaffs_hweight.c -o yaffs_hweight.o
    gcc -c -O2 -Wall -Werror -DCONFIG_YAFFS_UTIL -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline yaffs_ecc.c -o yaffs_ecc.o
    gcc -o mkyaffsimage  mkyaffsimage.o yaffs_hweight.o yaffs_ecc.o
    gcc -c -O2 -Wall -Werror -DCONFIG_YAFFS_UTIL -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline mkyaffs2image.c -o mkyaffs2image.o
    gcc -c -O2 -Wall -Werror -DCONFIG_YAFFS_UTIL -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline yaffs_packedtags2.c -o yaffs_packedtags2.o
    gcc -o mkyaffs2image mkyaffs2image.o yaffs_packedtags2.o yaffs_hweight.o yaffs_ecc.o
    root@zhengyang:/work/sambashare/yaffs2/utils# ll
    总用量 124
    drwxr-xr-x 2 root root  4096 1月  25 00:34 ./
    drwxr-xr-x 9 root root  4096 1月  24 22:04 ../
    -rw-r--r-- 1 root root  2164 1月  23 22:56 Makefile
    -rwxr-xr-x 1 root root 19400 1月  25 00:34 mkyaffs2image*
    -rw-r--r-- 1 root root 14193 1月  23 22:56 mkyaffs2image.c
    -rw-r--r-- 1 root root 11440 1月  25 00:34 mkyaffs2image.o
    -rwxr-xr-x 1 root root 18696 1月  25 00:34 mkyaffsimage*
    -rw-r--r-- 1 root root 13787 1月  23 22:56 mkyaffsimage.c
    -rw-r--r-- 1 root root 10408 1月  25 00:34 mkyaffsimage.o
    lrwxrwxrwx 1 root root    14 1月  24 21:56 yaffs_ecc.c -> ../yaffs_ecc.c
    lrwxrwxrwx 1 root root    14 1月  24 21:56 yaffs_ecc.h -> ../yaffs_ecc.h
    -rw-r--r-- 1 root root  3376 1月  25 00:34 yaffs_ecc.o
    lrwxrwxrwx 1 root root    17 1月  24 21:56 yaffs_endian.h -> ../yaffs_endian.h*
    lrwxrwxrwx 1 root root    15 1月  24 21:56 yaffs_guts.h -> ../yaffs_guts.h*
    lrwxrwxrwx 1 root root    25 1月  24 21:56 yaffs_hweight.c -> ../direct/yaffs_hweight.c
    lrwxrwxrwx 1 root root    25 1月  24 21:56 yaffs_hweight.h -> ../direct/yaffs_hweight.h
    -rw-r--r-- 1 root root  2096 1月  25 00:34 yaffs_hweight.o
    lrwxrwxrwx 1 root root    22 1月  24 21:56 yaffs_list.h -> ../direct/yaffs_list.h
    lrwxrwxrwx 1 root root    22 1月  24 21:56 yaffs_packedtags2.c -> ../yaffs_packedtags2.c
    lrwxrwxrwx 1 root root    22 1月  24 21:56 yaffs_packedtags2.h -> ../yaffs_packedtags2.h
    -rw-r--r-- 1 root root  3112 1月  25 00:34 yaffs_packedtags2.o
    lrwxrwxrwx 1 root root    16 1月  24 21:56 yaffs_trace.h -> ../yaffs_trace.h
    lrwxrwxrwx 1 root root    20 1月  24 21:56 yportenv.h -> ../direct/yportenv.h
    -rw-r--r-- 1 root root   962 1月  23 22:56 yutilsenv.h

    4.5 生成yaffs2类型的根文件系统

    切换到顶层路径运行命令制作根文件系统:

    cd /work/sambashare
    ./yaffs2/utils/mkyaffs2image ./rootfs/ rootfs.yaffs2

    查看制作好的根文件系统:

    五、编译下载

    5.1 下载到开发版

    5.2 设置u-boot启动参数

    u-boot启动后,在倒计时结束前按下空格键,设置machid:

    SMDK2440 # set machid 0xA8
    SMDK2440 # save
    Saving Environment to NAND...
    Erasing NAND...
    
    Erasing at 0x40000 -- 100% complete.
    Writing to NAND... OK
    SMDK2440 # 

    设置启动参数:

    set bootargs "root=/dev/mtdblock3 console=ttySAC0,115200 rootfstype=yaffs2 init=/linuxrc"
    save

    5.3 重新启动u-boot、引导linux内核

    重新启动开发板,NAND启动,运行,在串口输出的最后有如下错误:

    使用自己制作的mkyaffs2image工具生成的yaffs2根文件系统总是出现这个错误。后来我尝试将友善之家提供的根文件系统rootfs_rtm_2440.img下载到开发板运行,发现可以正常运行,从这里说明我们的linux内核程序是没有问题的,但是根文件系统存在问题。

    5.4 第三方根文件系统源码及工具

    为了排查根文件系统的问题,我从网上下载了mkyaffs2image 256M工具,并复制到/work/sambashare路径下,然后重新制作yaffs2根文件系统:

    cd /work/sambashare
    ./mkyaffs2image ./rootfs/ rootfs.yaffs2

    再次下载到开发板启动,发现运行成功了:

    六、代码下载

    Young / s3c2440_project[u-boot-2016.05-linux、linux-5.2.8、yaffs2、busybox-1.25.0]

    参考文章:

    [1]二十.Linux开发之根文件系统构建及过程详解

    [2]制作嵌入式Linux根文件系

    [3]JZ2440:yaffs2 格式根文件系统制作 - 程序员大本营

    [4]S3C6410使用---13mkyaffs2image

    [5]S3C2440移植linux3.4.2内核之支持YAFFS文件系统

    [6]嵌入式Linux构建yaffs根文件系统

    [7]yaffs2移植到内核linux-4.4.16的修改记录

  • 相关阅读:
    [转] 使用C#开发ActiveX控件
    [转] error LNK2026: 模块对于 SAFESEH 映像是不安全的
    Struts2详细说明
    a web-based music player(GO + html5)
    oracle_单向函数_数字化功能
    UVA 1364
    ORA-12545: Connect failed because target host or object does not exist
    左右v$datafile和v$tempfile中间file#
    二十9天 月出冲击黑鸟 —Spring的AOP_AspectJ @annotation
    Shell编程入门(再版)(在)
  • 原文地址:https://www.cnblogs.com/zyly/p/15835218.html
Copyright © 2020-2023  润新知