zoukankan      html  css  js  c++  java
  • 【转载】Mini6410启动过程

      这段时间在尝试使用uBoot来替代友善的Superboot,让板子支持从SD卡启动,所以就仔细研究了一下友善提供的内核和它的启动参数,发现 友善真的蛮聪明,把电脑的启动方式借鉴到它们自己的开发板上了。现在就把6410启动的过程分享出来,可能还有不完善的地方,希望了解的人也能指出我文章 里面的不足。

    initramfs启动

    以前在X86平台上做过一个最小的U盘启动小系统,用的就是initramfs的方式,只是在最后阶段不要让它切换根目录。对于initramfs 的启动方式网上有很多相关的文章,Linux内核的文档也有相应的介绍。这里只简单说一下它的原理,initramfs将归档好的文件系统添加到img 中,在启动的时候就只需要指定少量的内核启动参数,在启动过程中的临时文件系统所运行的脚本都是此文件系统中的程序和脚本,当然,这个文件系统其实就是一 个简单的linux系统,可以进行简单的操作,如果要扩展功能又不想把img做得很大,可以考虑用mount文件系统然后转换的方式来做。

    这样就将启动过程分成两个阶段,第一阶段就是用编入内核的文件系统做初始化,然后用定制的文件系统来跑应用程序。不仅减少了更新内核的负担,而且在更新的时候不需要更新应用程序的文件系统,文件系统和内核的更新可以分开来做,提高了效率。

    init脚本

    Linux启动后执行的第一个程序就根目录下的ini,友善通过init脚本来完成启动过程。其主要工作就是声明一些环境,加载要运行的文件系统,然后做文件系统的切换。因为不像X86下那么复杂,所以设备的初始化相对而言较为简单。启动脚本和注释如下:

    001    #! /bin/sh
    002     
    003    #初始化环境变量
    004    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    005    runlevel=S
    006    prevlevel=N
    007    umask 022
    008    export PATH runlevel prevlevel
    009     
    010    #
    011    #       Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
    012    #
    013    trap ":" INT QUIT TSTP
    014    #设置主机名
    015    /bin/hostname FriendlyARM
    016    #mount proc文件系统
    017    /bin/mount -n -t proc proc /proc
    018     
    019    #获取U-boot启动参数,主要设置文件系统内型、根目录、init等
    020    cmdline=`cat /proc/cmdline`
    021     
    022    #声明初始化启动相关参数,并设置默认值
    023    ROOT=none
    024    ROOTFLAGS=
    025    ROOTFSTYPE=
    026    NFSROOT=
    027    IP=
    028    INIT=/sbin/init
    029     
    030    #从获取的命令中获取启动参数
    031    for x in $cmdline ; do
    032            case $x in
    033            root=*)
    034                    ROOT=${x#root=}
    035                    ;;
    036            rootfstype=*)
    037                    ROOTFSTYPE="-t ${x#rootfstype=}"
    038                    ;;
    039            rootflags=*)
    040                    ROOTFLAGS="-o ${x#rootflags=}"
    041                    ;;
    042            init=*)
    043                    INIT=${x#init=}
    044                    ;;
    045            nfsroot=*)
    046                    NFSROOT=${x#nfsroot=}
    047                    ;;
    048            ip=*)
    049                    IP=${x#ip=}
    050                    ;;
    051     
    052            esac
    053    done
    054     
    055    if [ ! -z $NFSROOT ] ; then
    056        #网络文件系统启动
    057        echo $NFSROOT | sed s/:/ /g  > /dev/x ;  read sip dir < /dev/x   echo $IP | sed s/:/ /g > /dev/x;  read cip sip2 gip netmask hostname device autoconf < /dev/x
    058        rm /dev/x
    059     
    060        mount -t nfs $NFSROOT /r -o nolock,proto=tcp
    061     
    062    elif [ ! -z $run_fs_image ] ; then
    063        #制定的文件系统启动,这个环境变量还不知道是如何导出的,所以还需要了解,
    064        #看到友善提供的配置文件需要制定启动的文件系统,感觉应该是和那个地方相关,
    065        #但是又不能确定,高手可以指点一下
    066        ROOTFSTYPE="-t ext3" #设置文件系统类型
    067        #重复加载SD卡,重复尝试5次
    068        for i in 1 2 3 4 5 ; do
    069        /bin/mount -n -o sync -o noatime -o nodiratime -t vfat /dev/mmcblk0p1 /sdcard && break
    070        echo Waiting for SD Card...
    071        sleep 1
    072        done
    073        #加载文件系统
    074        /sbin/losetup /dev/loop0 /sdcard/$run_fs_image
    075        /bin/mount $ROOTFSTYPE /dev/loop0 /r
    076        mount -o move /sdcard /r/sdcard
    077    else
    078        #直接用指定的启动参数加载文件系统
    079        /bin/mount -n $ROOTFLAGS $ROOTFSTYPE $ROOT /r
    080    fi
    081     
    082    #检测并设置触摸屏的校正参数,可无
    083    ONE_WIRE_PROC=/proc/driver/one-wire-info
    084    ETC_BASE=/r/etc
    085    [ -d /r/system/etc ] && ETC_BASE=/r/system/etc
    086    [ -e $ETC_BASE/ts.detected ] && . $ETC_BASE/ts.detected
    087    [ -z $CHECK_1WIRE ] && CHECK_1WIRE=Y
    088    if [ $CHECK_1WIRE = "Y" -a -e $ONE_WIRE_PROC ] ; then
    089            if read lcd_type fw_ver tail < $ONE_WIRE_PROC ; then                 if [ x$lcd_type = "x0" -a x$fw_ver = "x0" ] ; then                         TS_DEV=/dev/touchscreen                 else                         TS_DEV=/dev/touchscreen-1wire                         echo "1Wire touchscreen OK"                 fi                 if [ -e $ETC_BASE/friendlyarm-ts-input.conf ]; then                         sed "s:^(TSLIB_TSDEVICE=).*:1$TS_DEV:g" $ETC_BASE/friendlyarm-ts-input.conf > $ETC_BASE/ts-autodetect.conf
    090                            mv $ETC_BASE/ts-autodetect.conf $ETC_BASE/friendlyarm-ts-input.conf -f
    091                            echo "CHECK_1WIRE=N" > $ETC_BASE/ts.detected
    092                            sync
    093                    fi
    094            fi
    095    fi
    096     
    097    [ -e /r/etc/friendlyarm-ts-input.conf ] && . /r/etc/friendlyarm-ts-input.conf
    098    [ -e /r/system/etc/friendlyarm-ts-input.conf ] && . /r/system/etc/friendlyarm-ts-input.conf
    099    export TSLIB_TSDEVICE
    100     
    101    #exec /bin/sh
    102     
    103    #文件系统替换
    104    umount /proc
    105    exec switch_root /r $INIT /r/dev/console 2>&1

    被“欺骗”的脚本

    当初以为ext3的文件系统就是实际启动时执行的操作,但是那个却是一个错误的认识,之所以认为那个是启动的文件系统,是因为内核的一个配置参数和此文件系统包含了一些脚本,所以在启动时走了不少的弯路。

    首先是对initramfs的认识不够,内核中有下面一个配置项:

    1 General setup  --->
    2     (scripts/FriendlyARM.cpio) Initramfs source file(s)

    看了文件后,我以为是友善的一个加密程序,是为了保护自己的知识产权,所以以为它只是打包进去,到了加载初始化文件系统的时候从内核配置的地址读取文件系统,然后再用这个程序解密。其次那个启动的参数加深了我的这个认识,让我误入歧途,脚本如下:

    1 Boot options  --->
    2     (console=ttySAC0,115200 root=/dev/ram init=/linuxrc initrd=0x51000000,6M ramdisk_size=6144)

    所以我一直以为是我的文件系统没有拷贝到正确的物理地址,导致内核死掉;一直在尝试文件系统到内存并设置u-boot的环境变量,然后反复重新启 动,但是一直是无解,最后我绝望了。在网上看了很多资料,发现Initramfs source file配置的应该是文件系统,再看看这个配置项就感觉像是一个cpio命令归档的文件系统,然后果断尝试能否将他解压。用如下命令解压它的归档文件:

    1 cpio -ivmd < FriendlyARM.cpio

    发现神奇般的解压开了,然后发现它就是一个文件系统,只是友善打包好了,然后配合它的Superboot来启动它的文件系统。然后就可以看到友善的 第一步启动过程,其脚本也在上一节做了一些注释(一开始我还是死脑子地认为init也是一个可执行文件,琢磨一段时间后才考虑直接打开的)。其实上面的 Boot options是使用ramdisk启动Linux所用到的配置项,用initramfs这个配置项是不必要的。

    这样也就知道了mini6410的全部启动过程,前面走过的弯路总算有一个较好的结局了。

    总结

    其实Linux启动过程的介绍网上有很多,制作自己的最小启动系统的资料也不少,但是用了友善的开发板后总觉得它会保密,所以在理解它的一些机制的 时候总会有定向思维,不敢放手去做,总是觉得自己哪里做错了。其实应该大胆去尝试,毕竟搞开发的人不会去把简单问题复杂化。冷静的思考其实也很重要,看到 那个FriendlyARM.cpio时,我没有想到他是一个文件系统的归档文件,以为是和cpio命令相关的应用程序,这才让我走了很多弯路,其实可以 通过file命令查看一下它到底是什么文件,那样也不至于走那么多的弯路。还是自己的经验尚浅啊~~不过走了一些弯路应该会记得更加清楚。

  • 相关阅读:
    Echarts图表 相关技术点
    Jquery off() on() data()
    Js 正则表达式
    Java jar项目获取配置文件的项
    Java String.split 的坑,会忽略空值
    C# 工作流 状态机 门控制
    二维码SDK,高效率,高识别率,甩zxing,zbar几条街
    C#文本转语音,可导出在本地mp3或者wav文件
    api接口签名验证(MD5)
    C# 站点IP访问频率限制 针对单个站点的实现方法
  • 原文地址:https://www.cnblogs.com/cxd2014/p/4476250.html
Copyright © 2011-2022 走看看