Arm1136 Kernel For Raspberry PI

qemu-system-arm可以直接使用内核用于加载系统。通常情况下我们可以用预编译好的第三方提供的内核来启动系统,然而如果我们需要用到定制的内核,就需要对内核进行编译了。下面的步骤将讲述如何编译出基于arm1136架构的raspberry PI内核。

1. 安装交叉编译链。

ArchLinux中,可以直接从Yaourt仓库里通过“yaourt gnueabihf”查找对应的包,编译的过程不再详述。安装完后,在终端输入arm-(Tab)应该可以看到arm-linux-gnueabihf-开头的编译器。

2. 准备内核源码。

# 从github下载源码
$ git clone https://github.com/raspberrypi/linux.git
# Apply Patch
$ wget http://xecdesign.com/downloads/linux-qemu/linux-arm.patch
$ patch -p1 -d linux/ < linux-arm.patch

3. 配置、编译内核。

# 加载默认配置
$ cd linux
$ make ARCH=arm versatile_defconfig

# 自定义内核
$ make ARCH=arm menuconfig

# 设置编译器
General Setup --->
Cross-compiler tool prefix
(arm-linux-gnueabihf-)

# 选择正确的CPU
System Type --->
[*] Support ARM V6 processor
[*] ARM errata: Invalidation of the Instruction Cache operation can fail
[*] ARM errata: Possible cache data corruption with hit-under-miss enabled

# 激活浮点运算
Floating point emulation  --->
[*] VFP-format floating point maths

# 激活ARM EABI
Enable ARM EABI:
Kernel Features --->
[*] Use ARM EABI to compile the kernel
[*] Allow old ABI binaries to run with this kernel

# 激活QEMU磁盘支持
Bus Support --->
[*] PCI Support
Device Drivers --->
SCSI Device Support --->
[*] SCSI Device Support
[*] SCSI Disk Support
[*] SCSI CDROM support
[*] SCSI low-lever drivers --->
[*] SYM53C8XX  Version 2 SCSI support

# 激活devtmpfs
Device Drivers --->
Generic Driver Options--->
[*] Maintain a devtmpfs filesystem to mount at /dev
[*] Automount devtmpfs at /dev, after the kernel mounted the root

# 激活重要的文件系统
Enable the important file systems:
<*> Ext3 journalling file system support
 <*> The Extended 4 (ext4) filesystem

# 激活tmpfs
File systems --->
Pseudo filesystems--->
[*] Virtual memory file system support (former shm fs)

# 激活event接口
Device Drivers --->
Input device support--->
[*] Event interface

# 激活/proc/config.gz
General Setup --->
[*] Kernel .config support
[*] Enable access to .config through /proc/config.gz

# 启动时字体配置和LOGO配置
Device Drivers --->
Graphics Support --->
Console display driver support --->
[ ] Select compiled-in fonts
[*] Bootup logo (optional)

现在退出并保存.config

#开始编译内核
$ cd linux
$ make ARCH=arm
$ make ARCH=arm INSTALL_MOD_PATH=../modules modules_install

4. 使用新编译出的内核启动系统

$ cp arch/arm/boot/zImage /Your_Qemu_Directory
$ qemu-system-arm -kernel zImage //Your Options.

使用自定义内核的好处是可以方便的激活某些高阶功能,例如NFS, Netfilter等等,一般情况下,默认提供的内核就已经可以满足我们的需要了。

Qemu For RaspberryPI

我用Qemu来仿真RaspberryPI以便快速测试内核模块的开发。下面是仿真的步骤:

1. 下载镜像文件2013-07-26-wheezy-raspbian.img,并更改其配置使得可以被qemu-system-arm加载:

$ fdisk -l 2013-07-26-wheezy-raspbian.img 
Disk 2013-05-25-wheezy-raspbian.img: 1939 MB, 1939865600 bytes, 3788800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000c7b31

                         Device Boot      Start         End      Blocks   Id  System
2013-05-25-wheezy-raspbian.img1            8192      122879       57344    c  W95 FAT32 (LBA)
2013-05-25-wheezy-raspbian.img2          122880     3788799     1832960   83  Linux

#从上面可以看到,根文件分区的地址偏移为512*122880=62914560

#更改根分区文件里preload信息:
$ sudo mount ./2013-07-26-wheezy-raspbian.img -o offset=62914560 /mnt3
$ sudo vim /mnt3/etc/ld.so.preload 
#注释掉这一行,否则在qemu启动完系统后将自动提示配置rpi而造成系统无法登陆
#/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so
$ sudo umount /mnt3

2. 拷贝一个此时的img文件以便将来备用

$ cp 2013-07-26-wheezy-raspbian.img 2.img

3. 配置qemu为bridge网络

qemu启动时需要调用的脚本:

$ cat /etc/qemu-ifup 
#!/bin/sh
  
echo "Executing /etc/qemu-ifup"
echo "Bringing up $1 for bridged mode..."
sudo /usr/bin/ip link set $1 up promisc on
echo "Adding $1 to br0..."
sudo /usr/bin/brctl addif br0 $1
sleep 2

qemu关闭时自动调用的脚本:

$ cat /etc/qemu-ifdown
#!/bin/sh
 
echo "Executing /etc/qemu-ifdown"
sudo /usr/bin/ip link set $1 down
sudo /usr/bin/brctl delif br0 $1
sudo /usr/bin/ip link delete dev $1

在镜像的当前目录下,创建run-qemu文件:

#!/bin/bash
USERID=$(whoami)

# Get name of newly created TAP device; see https://bbs.archlinux.org/viewtopic.php?pid=1285079#p1285079
precreationg=$(/usr/bin/ip tuntap list | /usr/bin/cut -d: -f1 | /usr/bin/sort)
sudo /usr/bin/ip tuntap add user $USERID mode tap
postcreation=$(/usr/bin/ip tuntap list | /usr/bin/cut -d: -f1 | /usr/bin/sort)
IFACE=$(comm -13 <(echo "$precreationg") <(echo "$postcreation"))

# This line creates a random mac address. The downside is the dhcp server will assign a different ip each time
printf -v macaddr "52:54:%02x:%02x:%02x:%02x" $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff ))
# Instead, uncomment and edit this line to set an static mac address. The benefit is that the dhcp server will assign the same ip.
# macaddr='52:54:be:36:42:a9'
 
qemu-system-arm -net nic,macaddr=$macaddr -net tap,ifname="$IFACE" $*
  
sudo ip link set dev $IFACE down &> /dev/null
sudo ip tuntap del $IFACE mode tap &> /dev/null 

因为tap需要用到tun模块,所以增加tun到自动加载的模块中

$ cat /etc/modules-load.d/tun.conf 
# Load tun at boot
tun

添加visudo条目:

Cmnd_Alias      QEMU=/usr/bin/ip,/usr/bin/modprobe,/usr/bin/brctl
%kvm     ALL=NOPASSWD: QEMU

添加用户到kvm组:

$ usermod -a -G kvm username

4. 启动qemu,使用两个镜像,以调整磁盘大小。

# 增加2G大小给镜像
$ qemu-img resize ./2013-07-26-wheezy-raspbian.img +2G
$ ./run-qemu -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1" -hda ./2.img -hdb ./2013-07-26-wheezy-raspbian.img 
进入Qemu后,
$ sudo apt-get install gparted
$ sudo gparted /dev/sdb
调整到自己想要的大小即可。

5. 重新启动后用下列命令启动Qemu:

$ ./run-qemu -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1" -hda ./2013-07-26-wheezy-raspbian.img 

使用上列步骤所启动起来的RaspberryPI镜像,具备完整的网络支持和足够的存储空间,而运行速度也令人满意。对比于真实的RaspberryPI板,编译、验证、烧写过程都较为简单,大部分研发工作可以基于这个平台来做。

Add Netfilter NAT for pogoplug

Pogoplug上了debian wheezy后,想配置成VPN服务器,在最后一步配置iptables时发现无法激活NAT表。

显示结果为:

$ iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
can't initialize iptables table 'NAT': Table does not exist (do you need to insmod?)

解决方法:重新编译NetFilter模块。

下载Linux3.1.10内核并解压到/usr/src

$ make menuconfig

{% img img /images/2013_09_03_12_53_06_868x411.jpg %}

而后:

{% img img /images/2013_09_03_12_54_08_749x362.jpg %}

确保以下选项被激活:

	CONFIG_NF_CONNTRACK
	CONFIG_NF_CONNTRACK_IPV4
	CONFIG_NF_NAT
	CONFIG_IP_NF_IPTABLES

而后编译,由于在嵌入式系统上编译速度较慢,所以只是编译目录下对应的模块,其他的则不编:

$ make M=net/netfilter modules  # Make all modules in specified dir
$ make M=net/netfilter          # Same as 'make M=dir modules'
$ make M=net/netfilter  modules_install # Install modules

这样就应该可以了,具体的验证等回家再看。

ArchLinux Ntp update time

1. 安装ntpd

$ pacman -S ntpd

2. 配置ntp服务器

$ vim /etc/ntp.conf
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst

3. 同步时间

$ sudo ntpd -gq

4. 加入守护进程运行

$ sudo systemctl enable ntpd

Using tsocks for acrossing the company firewall

1. 在家庭主机上配置DDNS服务,可以从no-ip.com申请一个免费的动态域名。no-ip同时提供了适用于不同平台的客户端,可以在其主页下载,并在家庭主机上安装之。家里的路由器上也可以配置DDNS,国内的可以用花生壳服务,而后开放DMZ主机给内网的主机即可。家庭主机需要开启sshd服务,这方面可以参考网上的有关ssh服务器的配置攻略

2. 在公司主机上,使用下列命令即可建立ssh代理

ssh -qTfnN -D 1394 xxx@xxx.no-ip.biz

命令详解:

-q Quite模式
-T 不分配伪终端
-f ssh后台运行
-n 将标准输入重定向到/dev/null
-N 不执行远程命令
-D 绑定本地端口1394

接下来我们就可以使用本地的端口127.0.0.1:1394作为socket代理服务器了。

3. 安装tsocks, 并配置.

$ pacman -S tsocks
$ vim /etc/tsocks.conf
server = 127.0.0.1
server_type = 5
server_port = 1394

4. 使用tsocks运行出一个完全自由的终端:

$ tsocks gnome-terminal

在新弹出的终端内,无需设置任何代理即可自由访问各处资源,衍生于该终端的应用程序也可以直接享用家庭网络的自由权限。enjoy it!