我雖然喜歡研究老東西, 不過也是有選擇的, 通常都是在這個時代還可以運用的技術。對於 cpu 我不想深入研究這已經退出舞台的機器。
需要做什麼準備工作呢? 我得去搞定 pdp 模擬器 simh (我可不想去弄台 pdp 機器, 家裡可沒大到擺這台), 可不是執行起來就夠, 還得能讓我 single step source code 才行。再來還有 pdp 的硬體架構, mmu, pre K&R c 語法, 研究 pdp-11 組合語言, 搞定 pdp-11 組譯器、老舊的 c 編譯器, 長長附錄 A 裡頭的參考資料可不是這麼容易就可以搞定的, 還沒開始看 code 就去半條命了。學到的 pdp 硬體架構也許有所幫助, 但以 cp 值來說實在是太低了, 這些東西都不好學, 要運用在目前流行的 x86/arm 還是要重頭學習一次, 能在目前流行的 x86/arm 學一次那就太好了。
xv6 就這麼出現了, 這是 mit 老師們為了教學和解除我上述的問題而在 x86 上開發的移植版本, 也大概是 10000 行左右 (組合語言和 c 語言), 我有了之前的學習, 應該可以看懂這 source code, 這比學習 linux 大怪物成功的機會大了不少, 和 linux 0.11 很類似。
安裝 xv6 到模擬器上
get source code git clone git://pdos.csail.mit.edu/xv6/xv6.git打個 make 很順利的產生需要的檔案。
在 qemu 執行 xv6
修改 Makefile
QEMU = qemu-system-i386 make qemu
實際上執行的指令是:
qemu-system-i386 -serial mon:stdio -hdb fs.img xv6.img -smp 2 -m 512執行訊息:
xv6... cpu1: starting cpu0: starting init: starting sh乖乖, 還真的支援多 cpu, 真的厲害, 當然, 拿掉 smp 就沒有 cpu1 了。
bochs 的話, 我沒有使用這個 dot-bochsrc, 我新增了一個可以在 bochs 2.6.6 使用的設定檔 bochsrc-266-conf。
/usr/local/bin/bochs -f bochsrc-266-conf
我真羨慕能上這個課程的學生, 我只能自己辛苦打拚了。
我 clone 一份, 放在 github
git@github.com:descent/xv6.git
該從什麼地方開始研究呢? booting 好了, 從 Makefile 就可以看出端倪。
xv6.img: bootblock kernel fs.img dd if=/dev/zero of=xv6.img count=10000 dd if=bootblock of=xv6.img conv=notrunc dd if=kernel of=xv6.img seek=1 conv=notrunc
由 qemu/bochs 指令可以得知需要 xv6.img, fs.img, 而 xv6.img 就是這樣產生的, 需要 bootblock。
bootblock: bootasm.S bootmain.c $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o $(OBJDUMP) -S bootblock.o > bootblock.asm $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock ./sign.pl bootblock
看到熟悉的 0x7c00, legacy bios booting 方式, 那 bootasm.S bootmain.c 就是開機的精華所在了。
我看不懂 perl, 似乎只是加上 0x55aa。
bootmain.c
void readsect(void *dst, uint offset)
{
// Issue command.
waitdisk();
outb(0x1F2, 1); // count = 1
outb(0x1F3, offset);
outb(0x1F4, offset >> 8);
outb(0x1F5, offset >> 16);
outb(0x1F6, (offset >> 24) | 0xE0);
outb(0x1F7, 0x20); // cmd 0x20 - read sectors
// Read data.
waitdisk();
insl(0x1F0, dst, SECTSIZE/4);
}
這是用 LBA mode 讀寫硬碟的程式碼, x86汇编语言:从实模式到保护模式 8.3.5 有詳細的說明, 這樣就不用 bios call, 可在 x86 protected mode 存取硬碟。不過不知道在真實機器上是不是可以正常執行?
ref:
- http://wapbaike.baidu.com/view/4715931.htm
- xv6文件系统详解
- xv6引导及初始化详解
- http://pdos.csail.mit.edu/6.828/2012/xv6.html
- http://zoo.cs.yale.edu/classes/cs422/2010/xv6-book/boot.pdf
readsect() 硬碟讀寫方式不使用 bios call:
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。