小米路由核心支持包

来自Jack's Lab
2014年8月7日 (四) 18:48Comcat (讨论 | 贡献)的版本

跳转到: 导航, 搜索
小米路由R1D系统框图

目录

1 缘起

5月底拿到一个兄弟用了一月的带硬盘版的路由,想想也就放家里 7x24 搜集各种智能设备的数据合适。

对于一个好动手的极客,没有内核代码、不能定制、控制自己的路由器是不能容忍的。


手头有原来用perl写的用于服务传感器数据推送 (REST) 的进程,部署需要catalyst和MySql,很自然地想到内核源码搞定后,在原ROM系统里叠加一个Debian 核心系统还是很爽的


于是仔细分析了其硬件实现,借助社区公开的代码,修修改改,6月6日很快就有了一个可启动的内核代码版本

然后断断续续完善到7月底,总算有了一个高度可用的版本



2 概览

现有的核心支持包包括一个2.6的内核源码包,一个工具链和一个叠加了 Debian 核心系统的混合系统 (ROOT FS)


小米路由的无线部分,2.5G和5G用的芯片和华硕 ASUS RT-AC56U 一致,处理器部分也和 RT-AC56U 相似,因此核心包的内核是基于 RT-AC56U 的官方开源版本开发,后期发现其实博通(Broadcom) 的这个系列的WiFi芯片给的Linux驱动都一样,业界惯例,都没有源码,只有预编译好的二进制文件


WiFi驱动编译后是名为 wl.ko 的模块,位于:kernel/linux-2.6.36/drivers/net/wl/ 下,这个与博通(Broadcom)官方SDK一致,应该也与小米拿到的一致,最多有些小Bug的fix

BCM4709 带的以太网,其 Linux 驱动是有源码的,位于:kernel/linux-2.6.36/drivers/net/et/ 下,这个也与博通(Broadcom)官方SDK一致


更多信息,可参考这个页面: 小米路由核心分析


整个系统除支持原ROM的核心功能外,自带 Debian 核心环境,可用apt-get install 直接安装你想要的软件包,相当方便


小米路由内核(Jack Tan开发的社区版)编译、TFTP部署、NFS文件系统部署视频演示: http://v.youku.com/v_show/id_XNzQ4OTU2Njg4.html

小米路由内核(Jack Tan开发的社区版)启动及核心功能视频演示: http://v.youku.com/v_show/id_XNzQ4OTkzNDgw.html


小米路由核心包源码置于个人的github帐号下: http://github.com/comcat/miwifi

核心包编译出的 rootfs 可直接部署在路由内硬盘的第四个分区上,亦可部署在 NFS server 上,详情可参考本页使用指南或者github源码目录下的README





3 尝试使用指南

初次尝试建议使用 tftp 加载内核,挂载 NFS 文件系统,内核和rootfs都在PC上,不会改变原路由的结构

待得测试、调试稳定后,再将内核裁减后部署到flash.os分区上(可在miwifi目录下执行 'make nonfs' 即可生成裁减后的内核),NFS文件系统打包后,部署到 /dev/sda4 上,详细参考本页的“注意事项”


以下在 Ubuntu 12.04 验证通过

3.1 源码下载编译

  $ sudo apt-get install lzma
  $ git clone git://github.com/comcat/miwifi.git
  $ cd miwifi/
  $ make

vmlinuz 为可直接被 CFE 加载的内核镜像(内含ramfs)

jarvis-rootfs.tgz 为 rootfs 包。用户 'root' 的默认密码为 'admin',WiFi 的SSID 为 Jarvis 和 Jarvis_5G,密码为 'qwer1234'


3.2 配置网络

我们在PC上部署 tftp server 和 NFS server,因此需要一根网线连接路由WAN口边上的LAN口到PC网口连接的HUB上,保证PC和路由在局域网内能通信

小米路由启动时,CFE (bootloader) 会检测 nvram 中的 flag_tftp_bootup 这个参数,如果其值为 on,其会首先尝试tftp加载 192.168.1.2:/vmlinuz 这个路径。因此我们要为 PC 配一个 192.168.1.2 的IP:

$ sudo ifconfig eth0:0 192.168.1.2


另,路由启动后,其为LAN口配的地址为 192.168.31.1 ,为保证PC能访问其 web 配置界面,也为 PC 配一个 192.168.31.2 的IP:

$ sudo ifconfig eth0:1 192.168.31.2



3.3 部署内核和文件系统

3.3.1 安装配置 tftp 服务器

$ sudo apt-get install tftpd tftp

$ cat /etc/xinetd.d/tftp
service tftp
{
    socket_type = dgram
    protocol = udp
    wait = yes
    user = root
    server = /usr/sbin/in.tftpd
    server_args = -s /tftpboot
    disable = no
    per_source = 11
    cps = 100 2
    flags = IPv4
}

$ sudo mkdir /tftpboot
$ sudo chmod 777 /tftpboot

$ sudo /etc/init.d/xinetd restart


到此 tftp Server 安装成功,把编译好的内核 vmlinuz 拷到 /tftpboot 目录下:

$ cp /path/to/miwifi/vmlinuz /tftpboot/


用 tftp 测试 tftp server 是否正常:

$ tftp
> connect 192.168.1.2
> get vmlinuz           # 获取tftp server 上的根目录下的 vmlinuz 文件



3.3.2 安装配置 nfs 服务器

$ sudo apt-get install nfs-kernel-server

Config the nfs directory:

$ sudo mkdir -p /tftpboot/rootfs
$ cat /etc/exports
/tftpboot/rootfs    *(async,rw,insecure,insecure_locks,no_root_squash)

$ sudo /etc/init.d/nfs-kernel-server restart


验证 NFS Server:

$ sudo mount -t nfs 192.168.31.2:/tftpboot/rootfs /mnt



3.4 设置nvram变量

PC 上 SSH 登录已经打开SSH服务的小米路由:

comcat@jackslab:$ ssh root@192.168.31.1
root@192.168.31.1's password: 


BusyBox v1.19.4 (2014-04-26 02:37:48 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

 -----------------------------------------------------
	Welcome to XiaoQiang!
 -----------------------------------------------------
root@XiaoQiang:/# nvram get flag_tftp_bootup
off
root@XiaoQiang:/# nvram set flag_tftp_bootup=on

root@XiaoQiang:/# nvram set rootfs=nfs              # 指示内核从NFS启动
root@XiaoQiang:/# nvram commit

root@XiaoQiang:/# reboot



3.5 加载内核启动

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)
 
...........
 
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
********** flag_tftp_bootup=on **********
tftp network: ifconfig eth0 -addr=192.168.1.1 -mask=255.255.255.0 -gw=192.168.1.1
Device eth0:  hwaddr 8C-BE-BE-20-B7-48, ipaddr 192.168.1.1, mask 255.255.255.0
        gateway 192.168.1.1, nameserver not set
kernel: boot -raw -z -addr=0x8000 -max=0x800000 192.168.1.2:vmlinuz
Loader:raw Filesys:tftp Dev:eth0 File:192.168.1.2:vmlinuz Options:(null)
Loading: ......... 6057024 bytes read
Entry at 0x00008000
Closing network.
Starting program at 0x00008000
Linux version 2.6.36.4jackslab (comcat@jackslab) (gcc version 4.5.3 (Buildroot 2012.02) 
) #1 SMP PREEMPT Wed Jul 30 19:44:09 CST 2014
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c53c7f
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: Northstar Prototype
Ignoring unrecognised tag 0x00000000
Memory policy: ECC disabled, Data cache writealloc
MPCORE found at 19020000
PERCPU: Embedded 7 pages/cpu @c8215000 s5504 r8192 d14976 u65536
pcpu-alloc: s5504 r8192 d14976 u65536 alloc=16*4096
pcpu-alloc: [0] 0 [0] 1 
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 60416
Kernel command line: root=/dev/ram console=ttyS0,115200 libata.force=3.0Gbps
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 128MB 128MB = 256MB total
Memory: 253592k/253592k available, 8552k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    DMA     : 0xf7e00000 - 0xffe00000   ( 128 MB)
    vmalloc : 0xd0800000 - 0xf0000000   ( 504 MB)
    lowmem  : 0xc0000000 - 0xd0000000   ( 256 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .init : 0xc0008000 - 0xc0141000   (1252 kB)
      .text : 0xc0141000 - 0xc0589000   (4384 kB)
      .data : 0xc05a8000 - 0xc05cec40   ( 156 kB)
SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
Hierarchical RCU implementation.
        RCU-based detection of stalled CPUs is disabled.
        Verbose stalled-CPUs detection is disabled.
NR_IRQS:256
MPCORE GIC init
External imprecise Data abort at addr=0x0, fsr=0x1c06 ignored.
MPCORE Global Timer Clock 500000000Hz
Calibrating delay loop... 1998.84 BogoMIPS (lpj=9994240)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
MPCORE Private timer setup CPU0
Calibrating local timer... 499.816MHz.
L310: cache controller enabled 16 ways, CACHE_ID 0x410000c8, AUX_CTRL 0x7a130000
CPU1: Booted secondary processor
MPCORE Private timer setup CPU1
Brought up 2 CPUs
SMP: Total of 2 processors activated (3997.69 BogoMIPS).
devtmpfs: initialized
atomic64 test passed
NET: Registered protocol family 16
Found a ST compatible (Marconix) serial flash with 256 64KB blocks; total size 16MB
CCA UART Clock Config: Sel=1 Ovr=1 Div=48
CCA UART Clock rate 125000000Hz
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Switching to clocksource mpcore_gtimer
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 4, 98304 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
UDP hash table entries: 128 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 128 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
PCI: no core
PCI: no core
PCI: scanning bus 0
PCI: Fixing up bus 0
PCIE1 link=1
PCIE1 switching to GEN2
PCIE1 link=1
PCI: Fixing up bus 0
PCI: bus0: Fast back to back transfers disabled
PCI: Fixing up bus 1
PCI: bus1: Fast back to back transfers disabled
pci 0001:00:00.0: BAR 8: assigned [mem 0x08000000-0x080fffff]
pci 0001:01:00.0: BAR 0: assigned [mem 0x08000000-0x08007fff 64bit]
pci 0001:01:00.0: BAR 0: set to [mem 0x08000000-0x08007fff 64bit] (PCI address [0x8000000-0x8007fff]
pci 0001:00:00.0: PCI bridge to [bus 01-01]
pci 0001:00:00.0:   bridge window [io  disabled]
pci 0001:00:00.0:   bridge window [mem 0x08000000-0x080fffff]
pci 0001:00:00.0:   bridge window [mem pref disabled]
PCIE2 link=1
PCIE2 switching to GEN2
PCIE2 link=1
PCI: Fixing up bus 0
PCI: bus0: Fast back to back transfers disabled
PCI: Fixing up bus 2
PCI: bus2: Fast back to back transfers disabled
pci 0002:00:00.0: BAR 8: assigned [mem 0x40000000-0x400fffff]
pci 0002:02:00.0: BAR 0: assigned [mem 0x40000000-0x40007fff 64bit]
pci 0002:02:00.0: BAR 0: set to [mem 0x40000000-0x40007fff 64bit] (PCI address [0x40000000-0x40007fff]
pci 0002:00:00.0: PCI bridge to [bus 02-02]
pci 0002:00:00.0:   bridge window [io  disabled]
pci 0002:00:00.0:   bridge window [mem 0x40000000-0x400fffff]
pci 0002:00:00.0:   bridge window [mem pref disabled]
PCIE3 link=1
PCIE3 switching to GEN2
PCIE3 link=1
PCI: Fixing up bus 0
PCI: bus0: Fast back to back transfers disabled
PCI: Fixing up bus 3
PCI: bus3: Fast back to back transfers disabled
pci 0003:00:00.0: BAR 8: assigned [mem 0x48000000-0x480fffff]
pci 0003:03:00.0: BAR 5: assigned [mem 0x48000000-0x480001ff]
pci 0003:03:00.0: BAR 5: set to [mem 0x48000000-0x480001ff] (PCI address [0x48000000-0x480001ff]
pci 0003:03:00.0: BAR 4: can't assign io (size 0x10)
pci 0003:03:00.0: BAR 0: can't assign io (size 0x8)
pci 0003:03:00.0: BAR 2: can't assign io (size 0x8)
pci 0003:03:00.0: BAR 1: can't assign io (size 0x4)
pci 0003:03:00.0: BAR 3: can't assign io (size 0x4)
pci 0003:00:00.0: PCI bridge to [bus 03-03]
pci 0003:00:00.0:   bridge window [io  disabled]
pci 0003:00:00.0:   bridge window [mem 0x48000000-0x480fffff]
pci 0003:00:00.0:   bridge window [mem pref disabled]
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
squashfs: version 4.0 (2009/01/31) Phillip Lougher
fuse init (API version 7.15)
msgmni has been set to 495
io scheduler noop registered (default)
io scheduler deadline registered
io scheduler cfq registered
Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x18000300 (irq = 117) is a 16550
console [ttyS0] enabled
serial8250.0: ttyS1 at MMIO 0x18000400 (irq = 117) is a 16550
brd: module loaded
loop: module loaded
PCI: Enabling device 0003:03:00.0 (0140 -> 0142)
ahci: SSS flag set, parallel bus scan disabled
ahci 0003:03:00.0: AHCI 0001.0200 32 slots 2 ports 6 Gbps 0x3 impl IDE mode
ahci 0003:03:00.0: flags: 64bit ncq sntf stag led clo pmp pio slum part ccc sxs 
scsi0 : ahci
scsi1 : ahci
ata1: FORCE: PHY spd limit set to 3.0Gbps
ata1: SATA max UDMA/133 abar m512@0x48000000 port 0x48000100 irq 175
ata2: FORCE: PHY spd limit set to 3.0Gbps
ata2: SATA max UDMA/133 abar m512@0x48000000 port 0x48000180 irq 175
Creating 9 MTD partitions on "bcmsflash":
0x000000000000-0x000000040000 : "boot"
0x000000040000-0x000000340000 : "os"
0x000000340000-0x000000640000 : "os1"
0x000000640000-0x000000ed0000 : "squashfs"
0x000000ed0000-0x000000ee0000 : "crash"
0x000000ee0000-0x000000fe0000 : "overlay"
0x000000fe0000-0x000000ff0000 : "board_data"
0x000000ff0000-0x000001000000 : "nvram"
0x000000000000-0x000000fe0000 : "firmware"
PPP generic driver version 2.4.2
PPP MPPE Compression module registered
NET: Registered protocol family 24
PPTP driver version 0.8.5
=== PPTP init ===
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
usbmon: debugfs is not available
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci_hcd 0000:00:0b.1: EHCI Host Controller
ehci_hcd 0000:00:0b.1: new USB bus registered, assigned bus number 1
ehci_hcd 0000:00:0b.1: irq 111, io mem 0x18021000
ehci_hcd 0000:00:0b.1: USB 0.0 started, EHCI 1.00
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
ohci_hcd 0000:00:0b.0: OHCI Host Controller
ohci_hcd 0000:00:0b.0: new USB bus registered, assigned bus number 2
ohci_hcd 0000:00:0b.0: irq 111, io mem 0x18022000
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 2 ports detected
xhci_hcd 0000:00:0c.0: xHCI Host Controller
xhci_hcd 0000:00:0c.0: new USB bus registered, assigned bus number 3
xhci_hcd 0000:00:0c.0: irq 112, io mem 0x18023000
xhci_hcd 0000:00:0c.0: Failed to enable MSI-X
xhci_hcd 0000:00:0c.0: failed to allocate MSI entry
usb usb3: No SuperSpeed endpoint companion for config 1  interface 0 altsetting 0 ep 129: using minimum values
hub 3-0:1.0: USB hub found
hub 3-0:1.0: 1 port detected
[xhci-hub] usb2mode:[0]
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
usbcore: registered new interface driver usbserial
USB Serial support registered for generic
usbcore: registered new interface driver usbserial_generic
usbserial: USB Serial Driver core
USB Serial support registered for pl2303
usbcore: registered new interface driver pl2303
pl2303: Prolific PL2303 USB to serial adaptor driver
u32 classifier
    Actions configured
Netfilter messages via NETLINK v0.30.
nf_conntrack version 0.5.0 (3962 buckets, 15848 max)
xt_time: kernel timezone is -0000
TCP cubic registered
NET: Registered protocol family 10
ip6_tables: (C) 2000-2006 Netfilter Core Team
NET: Registered protocol family 17
L2TP core driver, V2.0
PPPoL2TP kernel driver, V2.0
802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
All bugs added by David S. Miller <davem@redhat.com>
Registering the dns_resolver key type
Warning: unable to open an initial console.
ata1: SATA link up 3.0 Gbps (SStatus 123 SControl 320)
ata1.00: ATA-8: WDC WD1600BEKT-00PVMT0, 01.01A01, max UDMA/133
ata1.00: 312581808 sectors, multi 0: LBA48 NCQ (depth 31/32), AA
ata1.00: configured for UDMA/133
scsi 0:0:0:0: Direct-Access     ATA      WDC WD1600BEKT-0 01.0 PQ: 0 ANSI: 5
sd 0:0:0:0: [sda] 312581808 512-byte logical blocks: (160 GB/149 GiB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
 sda: sda1 sda2 sda3 sda4
sd 0:0:0:0: [sda] Attached SCSI disk
ata2: SATA link down (SStatus 0 SControl 320)
Freeing init memory: 1252K
Loading essential drivers...
Press Ctrl+C to enter RAMFS...
......
......



4 日常使用指南

TFTP + NFS 调试系统完成后,系统稳定的话,就可以将内核部署在 /dev/mtd1 (os) 或者 /dev/mtd2 (os1) 上

指示 CFE 启动时是加载 /dev/mtd1 (flash.os1) 上的内核还是 /dev/mtd2 (flash.os2) 上的内核,可以通过 nvram 变量 flag_last_success 来完成


以下在 Ubuntu 12.04 验证通过

4.1 源码下载编译

  $ sudo apt-get install lzma
  $ git clone git://github.com/comcat/miwifi.git
  $ cd miwifi/
  $ make nonfs

vmlinuz 为可直接被 CFE 加载的内核镜像(内含ramfs),大小小于 3MB,可以放入 mtd1/mtd2,这两个分区的大小为 3MB

jarvis-rootfs.tgz 为 rootfs 包。用户 'root' 的默认密码为 'admin',WiFi 的SSID 为 Jarvis 和 Jarvis_5G,密码为 'qwer1234'



4.2 部署内核和文件系统

如果是在原官方系统里部署,可以先将内核和文件系统 scp 拷贝的 /userdisk 下,这个目录默认挂载的是 /dev/sda4 是1T硬盘里最大的分区,用于用户下载等各种数据的存储

$ scp vmlinuz root@192.168.31.1:/userdisk/
root@192.168.31.1's password: 
vmlinuz

$ scp jarvis-rootfs.tgz root@192.168.31.1:/userdisk/
root@192.168.31.1's password: 
jarvis-rootfs.tgz                   

部署文件系统:

root@XiaoQiang:/# mount | grep userdisk
/dev/sda4 on /userdisk type ext4 (rw,noatime,barrier=1,data=ordered)

root@XiaoQiang:/# tar zxpf /userdisk/jarvis-rootfs.tgz -C /userdisk/


部署内核,此例中我们把自己的内核部署在 /dev/mtd2 上:

root@XiaoQiang:/# cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00040000 00010000 "boot"
mtd1: 00300000 00010000 "os"
mtd2: 00300000 00010000 "os1"
mtd3: 00890000 00010000 "squashfs"
mtd4: 00010000 00010000 "crash"
mtd5: 00100000 00010000 "overlay"
mtd6: 00010000 00010000 "board_data"
mtd7: 00010000 00010000 "nvram"
mtd8: 00fe0000 00010000 "firmware"
root@XiaoQiang:/# mtd write /userdisk/vmlinuz os1
Unlocking os1 ...

Writing from /userdisk/vmlinuz to os1 ...     



4.3 设置nvram变量



5 注意事项

核心包自带的文件系统(ROOTFS)的目的,主要是为了验证内核的各个子系统和驱动是否工作正常,主要是SATA硬盘、WiFi、Ethernet、Flash等,故而系统启动后,自动启动的服务极少,保证WiFi能联外网,局域网能工作,Web控制界面能登陆即可。其中 fw3 服务启动时加载原有规则老失败,这应该是个Bug,现有的解决方案是直接写 iptables 的规则,绕过去了,这个以后应该会解决。


初次使用的朋友,建议先按上面的步骤用 tftp 和 nfs 加载一下,看是否能工作,然后再自己调整系统服务和安装自己要用的软件包,反正所有的操作都在 nfs 上,不会改变原有的系统,待系统稳定后再把NFS的目录打个tar包部署在 /dev/sda4 上不迟


现在核心包默认使用NFS方式,这个造成了编译后生成的 vmlinuz 内核镜像超过了 3MB,如果您尝试稳定后,打算直接把内核部署到flash.os/flash.os2上,可将 kernel/linux-2.6.36/usr/ramfs/usr/bin/busybox 删除,再将内核配置里的NFS关闭,即可将内核镜像的大小控制在2.7MB左右

当然您要是让内核从 /dev/sda4 启动,记得设置 nvram:

# nvram set flag_tftp_bootup=off
# nvram set rootfs=sata
# nvram commit










个人工具
名字空间

变换
操作
导航
工具箱