小米路由系统启动过程

来自Jack's Lab
(版本间的差异)
跳转到: 导航, 搜索
(以“== Bootloader == Broadcom 出的片子,一直用自己的 Bootloader,叫 CFE,全称 Common Firmware Environment 原来写过一个 CFE Quick Start,在这...”为内容创建页面)
 
(/init 启动脚本)
第175行: 第175行:
 
         klogger "Switch to SQUASHFS..."
 
         klogger "Switch to SQUASHFS..."
  
#      gpio 1 1
 
#      gpio 3 1
 
#      gpio 2 0
 
 
        # red led is error
 
        #move red light to boot_check
 
        #gpio 1 0
 
 
#      nvram set flag_boot_type=2
 
 
         reboot
 
         reboot
  

2014年6月2日 (一) 19:43的版本

1 Bootloader

Broadcom 出的片子,一直用自己的 Bootloader,叫 CFE,全称 Common Firmware Environment

原来写过一个 CFE Quick Start,在这:http://www.jackslab.org/?portfolio=cfe-quick-start

小米路由系统 0.5.41 的 CFE 启动过程:

CFE version v1.0.4
BSP: 6.37.14.34 (r415984) based on BBP 1.0.37 for BCM947XX (32bit,SP,)
Build Date: Wed Apr 30 18:03:21 CST 2014 (szy@shenzhiyong-ct)
Copyright (C) 2000-2008 Broadcom Corporation.
 
Init Arena
Init Devs.
Boot up from NOR flash...
Boot partition size = 262144(0x40000)
Can't find nandflash! ccrev = 42, chipst= 0
DDR Clock: 800 MHz
Info: DDR frequency set from clkfreq=1000,*800*
et0: Broadcom BCM47XX 10/100/1000 Mbps Ethernet Controller 6.37.14.34 (r415984)
CPU type 0x0: 1000MHz
Tot mem: 262144 KBytes
 
CFE mem:    0x00F00000 - 0x0179FE38 (9043512)
Data:       0x00F58390 - 0x00F588C8 (1336)
BSS:        0x00F588D8 - 0x00F9DE38 (284000)
Heap:       0x00F9DE38 - 0x0179DE38 (8388608)
Stack:      0x0179DE38 - 0x0179FE38 (8192)
Text:       0x00F00000 - 0x00F4CCC4 (314564)
Boot:       0x017A0000 - 0x017E0000
Reloc:      I:00000000 - D:00000000
 
Device eth0:  hwaddr 8C-BE-BE-20-B7-48, ipaddr 192.168.1.1, mask 255.255.255.0
        gateway not set, nameserver not set
bootargs: boot -raw -z -addr=0x8000 -max=0xef8000 flash0.os:
Loader:raw Filesys:raw Dev:flash0.os File: Options:(null)
Loading: ..... 5372256 bytes read
Entry at 0x00008000
Closing network.
Starting program at 0x00008000

可以看到其启动后,直接加载 flash0.os 分区(/dev/mtdblock2 名为 'os')的 raw 格式的内核文件到地址 0x8000 处,然后直接跳转到这个地址开始执行



2 内核启动参数

# cat /proc/cmdline
root=/dev/ram rw console=ttyS0,115200 init=/init libata.force=3.0Gbps earlyprintk debug

从这可以看到,内核启动时首先挂载的是一个 initrd/initramfs 内存文件系统,执行的第一个程序是 /init 这个脚本



3 /init 启动脚本

#!/bin/sh
# Copyright (C) 2006-2012 OpenWrt.org
#
#

klogger(){
        local msg="$@"
        test -z "$msg" && return 1

        echo "$msg" >> /dev/kmsg 2>/dev/null
}

usb_check_for_rescure(){
        local gpiobtn

        gpiobtn=`cat /proc/xiaoqiang/reset`
        rst=`gpio $gpiobtn | awk '{print $3}'`
        if [ "$rst" = "<0>" ]; then
                nvram set flag_reboot_system=2
                exec /sbin/init
        fi
}

getmtdblockdevbyname(){
        local name
        name="$1"
        test -z "$name" && return 1
        devnum=$(cat /proc/mtd | awk "/\"$name\"/"| awk -F':' '{print $1}' | awk -F'mtd' '{print $2}')
        test -z "$devnum" && return 1
        if [ -e "/dev/mtdblock${devnum}" ]
                then
                echo "/dev/mtdblock${devnum}"
                return 0
        else
                return 1
        fi
}

reboot() {
        nvram set flag_reboot_system=1
        exec /sbin/init
}

updone() {
        nvram set flag_package_update=0
        nvram set telnet_en=1
        nvram commit

        klogger "Update successfully!!! Reboot the System..."
        reboot
}

upnet() {
        #not vlan support in bootloader and ramfs, using trunk mode
        #set to "0 1 2 5u" for ramfs network only, do not commit
        rmmod et 2>/dev/null
        nvram set vlan1ports="0 2 5u"
        nvram set vlan2ports="4 5"

        mac=`nvram get et0macaddr`
        if [ "$mac" = "00:90:4C:0F:F2:a7" ]; then
                uuid=`cat /proc/sys/kernel/random/uuid`
                b1=`echo $uuid | cut -b 1-2`
                b2=`echo $uuid | cut -b 3-4`
                b3=`echo $uuid | cut -b 5-6`
                mac=`echo 00:90:4C:$b1:$b2:$b3`
                nvram set "pci/1/1/macaddr=$mac"

                uuid=`cat /proc/sys/kernel/random/uuid`
                b1=`echo $uuid | cut -b 1-2`
                b2=`echo $uuid | cut -b 3-4`
                b3=`echo $uuid | cut -b 5-6`
                mac=`echo 00:90:4C:$b1:$b2:$b3`
                nvram set "pci/2/1/macaddr=$mac"

                uuid=`cat /proc/sys/kernel/random/uuid`
                b1=`echo $uuid | cut -b 1-2`
                b2=`echo $uuid | cut -b 3-4`
                b3=`echo $uuid | cut -b 5-6`
                mac=`echo 00:90:4C:$b1:$b2:$b3`
                nvram set "et0macaddr=$mac"
        fi
        insmod /lib/modules/et.ko

        lip=`nvram get flag_local_ip`
        if [ "$lip" = "auto" ]; then
                /sbin/udhcpc -t 10 -n
                if [ $? -eq 1 ]; then
                        lip="192.168.31.1"

                        ifconfig eth0 $lip up
                fi
        else
                [ -n "$lip" ] || lip="192.168.31.1"
                ifconfig eth0 $lip up
        fi
        echo 1 > /proc/sys/net/ipv6/conf/eth0/forwarding

        ifconfig lo up
        nvram set vlan1ports="0 2 5*"
        nvram set vlan2ports="4 5"
}

uperror() {
        klogger "SQUASHFS Filesystem Error!!!"
        klogger "Switch to RAMFS..."

        upnet
        exec /sbin/init
}

squashfs() {
        klogger "Switch to SQUASHFS..."

        reboot

        rescuerootdev=$(getmtdblockdevbyname squashfs)
        if [ -n "$rescuerootdev" ]
                then
                mount -t squashfs $rescuerootdev /mnt
                if [ $? -ne 0 ]
                then
                        klogger "ERROR: mount -t squashfs $rescuerootdev /mnt failed."
                else
                        # boot_status: 1 sata mode
                        #              2 flash mode
                        echo 2 > /sys/power/boot_status
                        upmount
                        if [ -x /mnt/etc/rescueinit ]
                                then
                                klogger "switch to rescue system($rescuerootdev) by /etc/rescueinit ..."
                                exec switch_root /mnt /etc/rescueinit
                        fi
                        if [ -x /mnt/lib/preinit.sh ]
                                then
                                klogger "switch to rescue system($rescuerootdev) by /lib/preinit.sh ..."
                                exec switch_root /mnt /lib/preinit.sh
                        fi
                        umount -f $rescuerootdev
                fi
        fi
        uperror
}

upmount() {
        mount -n -o move /tmp /mnt/tmp
        mount -n -o move /sys /mnt/sys
        mount -n -o move /proc /mnt/proc
        mount -n -o move /dev /mnt/dev
}

[ -d /dev ] || mkdir -m 0755 /dev
[ -d /mnt ] || mkdir -m 0700 /mnt
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp

mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid none /sys 
mount -t proc -o nodev,noexec,nosuid none /proc 

klogger "Loading, please wait..."

# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
if ! mount -t devtmpfs -o mode=0755 none /dev; then
        mount -t tmpfs -o mode=0755 none /dev
        mknod -m 0600 /dev/console c 5 1
        mknod /dev/null c 1 3
fi
mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /tmp

klogger "Loading essential drivers..."
flag_usb_rootdisk_enable="$(nvram get flag_usb_rootdisk_enable)"
for i in `cat /lib/modules/mod.lst`;
do
        [ "$i" = "usb-storage.ko" -a "$flag_usb_rootdisk_enable" != 'true' ] && continue
        if [ "$i" != "et.ko" ] ; then
                insmod /lib/modules/$i || nvram set flag_package_update=5
        fi
done

# Check for USB rescure
klogger "Check for USB rescure..."
usb_check_for_rescure

model=`nvram get model`
if [ -z "$model" ]; then
        model=`cat /proc/xiaoqiang/model`
fi

if [ "$model" = "R1AC" ]; then
        insmod /lib/modules/usb-storage.ko 2>/dev/null
        sleep 3
fi

#support tftpboot from network
if [ "$(nvram get flag_tftp_bootup)" = 'on' -a "$(nvram get flag_tftp_booted)" = 'true' ]
then
        . /tftpboot.init
        tftpboot_mount_rootfs
fi

klogger "Press Ctrl+C to enter RAMFS..."
rd -w 1 && nvram set flag_package_update=5

if [ ! -b /dev/sda ]; then
        klogger "Warning: No Hard Disk"

        nvram set flag_no_hdd=1
        nvram commit

        squashfs
fi

update=`nvram get flag_package_update`
ft_mode=`cat /sys/power/ft_mode`
if [ -n "$update" -a "$update" != "0" ]; then
        #

        klogger "Prepare the system to update..."
        upnet

        if [ $update = "5" ]; then
                exec /sbin/init
        else
                /usr/sbin/autofd
                if [ $? -eq 1 ]; then
                        gpio 2 1
                        gpio 3 1
                        gpio 1 0

                        if [ "$ft_mode" = "1" ]; then
                                exec /sbin/init
                        else
                                while true
                                do
                                                /usr/sbin/update
                                                retcode=$?

                                                [ $retcode -eq 2 ] && exec /sbin/init
                                                [ $retcode -eq 0 ] && updone
                                done
                        fi
                else
                        updone
                fi
        fi
else
        klogger "Bringup the system..."

        #gpio 1 1
        #gpio 2 1
        #gpio 3 1

        flag_try_sys1=`nvram get flag_try_sys1_failed`
        flag_try_sys2=`nvram get flag_try_sys2_failed`

        if [ "$flag_try_sys1" != "1" ] || [ "$flag_try_sys2" != "1" ]; then
                # default: rootfs1
                flag=`nvram get flag_boot_rootfs`
                if [ "$flag" = "1" ]; then
                        mntdev=/dev/sda2
                else
                        mntdev=/dev/sda1
                fi
                [ -b $mntdev ] && mount -o ro $mntdev /mnt

                # flag_boot_type: 1 system in SATA   version
                #                 2 system in SQUASH version
                #                 9 system in tftp version
                nvram set flag_boot_type=1
                if [ -x /mnt/lib/preinit.sh ]; then
                        # boot_status: 1 sata mode
                        #              2 flash mode
                        upmount
                        exec switch_root /mnt /lib/preinit.sh
                else
                        if [ "$ft_mode" = "1" ]; then
                                # skip failed flag setting in FT mode
                                reboot
                        else
                                if [ "$flag" = "1" ]; then
                                        nvram set flag_try_sys2_failed=1
                                else
                                        nvram set flag_try_sys1_failed=1
                                fi
                                nvram set flag_ota_reboot=0
                                nvram commit

                                reboot
                        fi
                fi
        fi

        # reset all failed flag in FT mode
        if [ "$ft_mode" = "1" ]; then
                nvram set flag_try_sys1_failed=0
                nvram set flag_try_sys2_failed=0
                nvram commit

                reboot
        fi

        squashfs
fi























个人工具
名字空间

变换
操作
导航
工具箱