缘起
无意间在单位的一堆旧资料里发现了这本书,一直想了解操作系统方面的知识,以前曾尝试读过《操作系统的概念》、《30天自制操作系统》等书,一直没有坚持下来,感觉没有好的切入点,单凭纸上谈兵很难有所收获,而且正好这本书给了一个具体的实验环境,于是乎开干。
1、硬件环境。
硬件环境为linksys e2100l路由器,二手50大洋左右,拆掉底下四颗螺钉,把前盖撬下来,可能需要用点力。拆开以后就可以看到电路板。右边红白绿黑四条线的地方就是本机的控制口,共5根线,从天线一侧开始,依次为Vcc、Tx,Rx,未使用,Gnd,电平为TTL电平,波特率为115200,其他参数为8,N,1。
2、交叉编译环境。
我使用的是uClibc提供的MIPS大端交叉编译环境,链接如下。
https://uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-mips.tar.bz2
3、源码编译。
源码可以从本书的官方网站http://xinu.cs.purdue.edu/files/Xinu-code-MIPS.tar.gz下载。linksys版本对应的本书的第一版,目前最新版是第二版,不过貌似没有看到中文版的第二版。本书作者建议使用新的硬件环境学习本书(But we recommend using a modern board like a BBB or Orange PI.)。
不知道什么原因,我下载的源码在使用我的交叉编译环境生成elf文件的时候会出现链接错误。最开始报错的地方在intdispatch.S文件的savestate标签中,不过start.S也会有warning。于是我对比了tarball里的start.o和编译出来的start.o,发现在函数调用这块确实存在差别,不知道编译选项哪里不对,尝试使用CFLAGS编译.S文件,然后再对比,发现新旧文件比较像,索性干掉原来的汇编编译选项,使ASFLAGS = ${CFLAGS},重新编译make xinu.elf,竟然成功了。于是马不停蹄的make xinu.boot,一切顺利,只待下载。
4、镜像下载。
我使用的是usb转uart的一个小模块,通过杜邦线连接路由器的控制口,其中只连接了Tx,Rx,Gnd三根线,收发交叉连接。连接完成之后给路由器加电,路由器使用U-Boot引导,可以在终端看到路由器的输出信息,在第47行会打印“Hit any key to stop autoboot:”,此时按下任意键终止自动启动,接下会出现命令提示符“ar7100>”,在命令提示符后输入“bootp 0x81000000”并回车(0x81000000为下载地址,与U-Boot制作的镜像对应),接下来可以看到bootp的过程,镜像传输完成之后会打印“done”并在之后一行打印本次传输情况“Bytes transferred = 141008 (226d0 hex)”,镜像大小可能会有所差异。接下来在命令提示符后输入“bootm”并回车,不出意外的话你可以看到“## Booting image at 81000000 ...”。启动成功界面如下。
5、bootp工具。
bootp过程需要bootp服务器和tftp服务器,尝试使用bootp-dhcp server 2.3.2,这个版本的程序,没找到在哪里能设置tftp的地址和启动镜像的名称,默认的tftp服务器为本机,如果本地有多块网卡,不一定能命中你想用的地址;默认的镜像名称是%IPStr%.bin,IPStr为dhcp得到的ip地址的十六进制表示,比如dhcp得到的ip地址为192.168.0.1,则镜像名称为C0A80001.bin。
使用的tftp工具为tftp64(http://tftpd64.codeplex.com/),后来发现这款工具也自带了DHCP服务器,也就是说如果使用bootp-dhcp server需要tftp64配合,而是用tftp64一个软件也可以搞定。
然而过程并不是那么顺利,使用tftp自带的DHCP服务器,路由器会一直发送DHCP Discover,后来抓包发现DHCP Discover确实得到了响应,但是后面发的DHCP Request没有得到响应,幸好这是个开源软件,下载源码(版本tftpd64-e38b210d298e25e601ccaa091fb6551dc1c28bd6.zip),经过分析发现在_services文件夹下Bootp.c中第633行和634行,对于带地址(非广播或全0)的请求做了返回处理,注释掉此两行(可能欠妥),重新编译后可以解决此问题。本软件可以在“Setting”中的DHCP标签页配置tftp服务器地址和镜像名称,使用起来比较方便。