醉刀 |
2006-12-17 14:21 |
這裏介紹一個可以不用花費很多錢去購買專門的硬體但是又可以學習嵌入式Linux系統的方法。這就是利用世家(Sega Dreamcast)遊戲機來學習製作嵌入式Linux。(Embedded Linux) 這篇文章將會詳細的講解如何在Sega Dreamcast上面安裝Linux.包括Linux Kernel, Boot loader和Utility kernel patches. 同時也提供以上工具的下截連接地址。
簡介:
在學習Embedded Linux的時候,最重要的就是價錢和系統的相容性了。人人都知道,Linux在桌面電腦和伺服器上面都可以非常好的運作。但是,這些都不能稱作嵌入式系統。你知道嗎,其實利用你的Sega Dreamcast遊戲機,你就可以自己學習製作一次嵌入式的Linux了。
要學習嵌入式Linux,首先,當然你要有足夠的文件。同時,你要必須要有一個不是基於X86的硬體平臺,包括一顆不是X86的微處理器。除了電腦以外,比較理想的就是:PDA, Internet appliances 和遊戲機啦。
沒錯,就是遊戲機。那種爲了讓大家購買遊戲而幾乎不賺錢,或者虧錢在賣的東西。現在價位最合適的就應該算是Sega Dreamcast了。因爲Sega 已經出了新的産品了,目前Sega Dreamcast已經被廠家已經停止生産。所以Sega Dreamcast的價位現在非常的好。下面我們就看看如何在Sega Dreamcast上面跑Linux.
Linux 是如何運作在 Sega Dreamcast 上的: 在討論Linux 是如何運作在 Sega Dreamcast上之前,我們首先要知道是如何把Linux裝到Sega Dreamcast裏面去的。其實秘密就在於放入Sega Dreamcast裏面的那個CD的格式啦。也就是說,並不需要什么特殊的工具。
Sega Dreamcast:
Sega Dreamcast支援 Hitachi SH7750 CPU,運行速度是200MHz. 有 16MB的RAM.你可以選擇使用電視機(PAL制式或者NTSC制式)或者利用乙太網配置器(Ethernet Adapter)
直接連接到VGA的電腦螢幕上面。Saga關這種卡叫做“Broadband Adapter”或者“BBA”,也能買到專門給Saga Dreamcast使用的鍵盤和滑鼠。
在Dreamcast上安裝Linux:
在Saga Dreamcast遊戲機啓動的時候,Saga Dreamcast內建的一個啓動程式會嘗試讀取 CD-R(要確定,不能用CD-RW),嘗試找到最少兩個CD-R的recording sessions.第一個session是音軌,boot loader並不會去管它。但第二個session必須是CD/XA資料軌。(mode 2, form 1)這個資料軌必須是標準的ISO9660的文件系統,同時這個文件系統的前16個磁區必須包含一個含有啓動資訊的文件IP.BIN。IP.BIN包含啓動後,啓動程式需要開啓的檔案名。IP.BIN同時包含元資料用以識別硬體,以確定CD上的哪個程式將被執行。(例如自動選擇遊戲是在Sega Dreamcast上執行,還是在Saga其他類型的遊戲機上執行)地區標誌,會控制遊戲以那種格式顯示(PAL或者NTSC),同時也顯示遊戲所需要的控制器(遊戲手柄啦什么的)和CRC.
一但Saga Dreamcast內建的啓動程式讀到有效的IP.BIN文件。系統就會自動把命名的文件從ISO9600的文件系統讀到記憶體中,並交出全部的控制許可權。這裏,我們做的就是,當Saga Dreamcast系統開機以後,啓動程式會把Linux進去。還可以利用Saga Dreamcast的串列介面(serial port)或者乙太網介面(enthernet port)來下截一些東西。一個RTOS,好比eCos就不錯。
Saga Dreamcast的系統硬體同時提供一個類似於BIOS功能的東西用於系統可以從GD-ROM drive讀取資料,(GD-ROM drive是一種從CD-ROM改裝出來的東西,它跟CD-ROM最大的區別就是GD-ROM可以容納1GB的資料)訪問內建的flash memory等等。可惜的是目前這些東西還沒有支援。也許當你讀到這片資料的時候就已經有了這方面的支援了。
接下來做什么?
我們要知道了如何製作一個可在Saga Dreamcast上運行的系統image, 我們就必須對Linux有一定的瞭解:
Linux的Kernel本身是不能啓動的。她需要一個啓動程式,比如lilo來幫助她。Lilo會把開始系統的一些資訊,例如系統情況,系統平臺等等傳送給Kernel. Lilo同時也支援解壓縮,這樣可以把壓縮的Kernel image直接拿給用。在嵌入式系統中,我們也同樣需要一個類似於lilo的boot loader.
簡單的來說,Linux的啓動分爲以下幾個步驟:
Boot loader 最先得到系統的控制權。這個控制權是從BIOS或啓動硬體中得到的。 Boot loader 把kernel的image丟到memory裏面去並且解開壓縮。 Boot loader 進入已經解壓縮的memory image中。這個memory image裏面就是Linux的 Operation System Kernel啦。 Kernel 對自己進行初始化,然後mount root 目錄。載入device drive,初始化硬體,最後開始運行應用程式。 現在我們知道了這些,應該清楚CD上的image裏面的內容了吧。我們需要一個boot loader,和一個Linux 的 Kernel, 我們需要讓我們的boot loader在Saga Dreamcast啓動後,能得到控制權,且找到Linux的Kernel,同時轉換控制權。
Linux 和應用程式:
接下來,我們還有很多的事情要做。一旦kernel可以成功的運行了,我們還需要應用程式。桌面系統跟嵌入系統有個很大的區別。桌面系統通常系統只負責跟應用程式之間的交換。但是嵌入系統就不同了,在嵌入式系統中,通常系統和應用程式是同一個。也就是說,他們是綁在一起的。因爲他們綁的實在是太緊了,很難分辨出來,所以勉強的區分辨那個是作業系統那個是應用程式就有點不符合實際了。
Linux是一個通用性的很好的桌面作業系統,也就是說,我們需要有應用程式才可以。在這篇文章的結尾。會介紹一個類似的應用程式:shell
Linux和文件系統:
如果你觀察一下Linux的startup code,你就會發現,最後一步就是kernel尋找一個可執行的叫做“init”的檔案,並且把它截入到記憶體裏。這裏並不只是說我們需要一個叫做“init”的文件。這裏同時指出,我們需要一個文件系統去取出這個檔案。
也許你會想,Saga Dreamcast並沒有硬碟,那么如何存放系統文件呢?其實,很多的電腦工作站也是沒有硬碟----最少,在系統還沒有初始化IDE或者SCSI控制卡之前。所以,其實Linux在開機的時候是會自動類比出一個硬碟來的。
當沒Linux開機的時候,Linux會自動用ramdisk的功能,把一部分記憶體類比成一個硬碟。工作站的boot loader在開機時從軟碟中獨取image,然後後截入ramdisk,再把ramdisk的地址傳送給kernel. Kernel從ramdisk讀取磁片控制卡的的資料,然後進行初始化,載入。這時候真正的物理硬碟才工作。一旦物理硬碟工作了,ramdisk就會被釋放。
Ramdisk提供所有Linux需要的磁片導向設備。所以說,一個系統只要有足夠的存放程式和device drive的記憶體。那么這個系統可以完全不需要硬碟。Saga Dreamcast就是在用ramdisk代替傳統硬碟的。
爲Saga打造Linux,你都需要些什么:
首先,你必須擁有一台電腦,這台電腦必須是Linux或者Unix-like的作業系統。你必須有root的許可權。
其次,你需要一台CD-R的讀寫器(Writer),讀寫器和燒錄程式必須要支援 multisession CD using CD/XA data track (mode 2, form 1)格式。其實大多數的CD-R writer和程式都支援個。要注意的是:Saga Dreamcast的GD-ROM驅動器不能讀取CD-RW,不過用CD-RW燒錄的CD-R是沒有問題的。也就是說,只能用CD-R的片子,不能用CD-RW.
最後,就是需要一些工具啦,這些工具基本上你在網上都能找得到的:
下面我也把link都給了出來
binutils-2.11.2.tar.gz -- The linker, assembler, and object management utilities. gcc-3.0.1.tar.gz -- The GNU Compiler Collection. Contains the C/C++ compiler. glibc-2.2.4.tar.gz -- The GNU C runtime library. busybox-0.60.1.tar.gz -- Small, embedded versions of common Unix utilities. kernel-sh-linux-dreamcast.tar.gz -- Linux kernel for the Dreamcast. sh-boot-20010831-1455.tar.gz -- Linux bootloader for the Dreamcast. binutils-2.11.2-sh-linux.diff -- Patches for binutils. gcc-3.0.1-sh-linux.diff -- Patches for gcc. glibc-2.2.4-sh-linux.diff -- Patches for glibc. busybox-0.60.1-sh-linux.diff -- Patches for Busybox. kernel-sh-linux-dreamcast.diff -- Patches for the Linux kernel. sh-boot-20010831-1455.diff -- Patches for sh-boot.
打造我們需要的工具:
想在Saga Dreamcast上運行Linux.第一步就是我們需要打造一些工具包括:cross assembler, linker, compiler, C runtime library。下面,我們就用這些工具打造出一個Saga Dreamcast用的作業系統,並且在系統開機以後,運行一個簡單的shell。最後,我們把所有的東西方到一個ramdisk image裏。並燒錄CD.
Build cress assembler, linker, and bootstrap compiler
我們首先需要打造一個cross assembler和linker,然後是bootstrap compiler.用一個迷你的compiler可以打造runtime libraries和system kernels。但是不能打造應用程式。
首先,確定/usr/local/bin/有在PATH裏設定噢
login as root user,然後按照下面的script:
# export TARGET=sh4-linux //這裏是設定環境變數
# export PREFIX=/usr/local //這樣好處就是不用以後老打那么多字
# export PATH=${PATH}:${PREFIX}/bin //結束
# tar xzf binutils-2.11.2.tar.gz
# patch -p0 < binutils-2.11.2-sh-linux.diff
# mkdir -p build-binutils && cd build-binutils
# ../binutils-2.11.2/configure --target=$TARGET \
--prefix=$PREFIX
# make all install
# cd ..
# tar xzf gcc-3.0.1.tar.gz
# patch -p0 < gcc-3.0.1-sh-linux.diff
# mkdir -p build-gcc && cd build-gcc
# ../gcc-3.0.1/configure \
--target=$TARGET --prefix=$PREFIX \
--without-headers --with-newlib \
--disable-shared --enable-languages=c
# make all-gcc install-gcc
# cd ..
最後的可執行檔案在/usr/local/bin下面,名字是 sh4-linux-as, sh4-linux-ld.
用同樣的方法就可以build bootstrap compiler了。Bootstrap compiler也是在/usr/local/bin下面
執行檔案的名字叫做sh4-linux-gcc.
Configure the Kernel source:
這裏主要是要configure kernel的header file. 非常的簡單,不過請注意,這裏不要對選項做任何的修改。在menuconfig的時候,直接選擇Exit.(按一下鍵盤的箭頭右鍵,然後按enter就好了)
#tar vxf kernel-sh-linux-dreamcast.tar.gz
#path –p0 < kernel-sh-linux-dreamcast.diff
#cd kernel
# make ARCH=sh CROSS_COMPILE=sh4-linux- menuconfig
#cd ..
Building a runtime library 現在我們有了bootstrap compiler和一個設置適當的kernel了。我們現在可以開始build runtime library和header files了。我們使用的run-time library是GNU的glibc.這個library裏面有大家都熟悉的printf()之類的東西。同時還包含動態連接(dynamic linker)和其他的一些東西。
首先解壓縮,然後patch,接下來把 Linux kernel的header files 拷貝過去。實際上,我們需要調用make兩次來build glibc. 第一次的時候,建立library,但是並沒有安裝,第二次才是安裝library. Touch的命令實際上是爲了騙過glibc讓它以爲所有的東西都已經有了(實際上有些東西是我們不需要的)最後echo指令做了一個link libc.so
如果你在built完 binutils, bootstrap, gcc以後重新啓動過你的電腦(或者重新login過)那么你必須重新設定PATH,TARGET,PREFIX這三個變數才可以build gligc.
Glibc在build的時候可能花的時間會比較多。當然,主要也是看你的系統而定。不過到是可以利用現在這個時間休息一下,吃點東西,泡杯茶。
# tar xzf glibc-2.2.4.tar.gz
# patch -p0 < glibc-2.2.4-sh-linux.diff
# mkdir -p build-glibc && cd build-glibc
# mkdir -p ${PREFIX}/${TARGET}/include
# cp -r ../kernel/include/linux \
${PREFIX}/${TARGET}/include
# cp -r ../kernel/include/asm-sh \
${PREFIX}/${TARGET}/include/asm
# CC=sh4-linux-gcc ../glibc-2.2.4/configure \
--host=$TARGET --prefix=$PREFIX \
--disable-debug --disable-profile \
--disable-sanity-checks \
--with-headers=${PREFIX}/${TARGET}/include
# make
# touch iconv/iconv_prog login/pt_chown
# make install_root=${PREFIX}/${TARGET} \
prefix="" install
# echo "GROUP ( libc.so.6 libc_nonshared.a )" \
> ${PREFIX}/${TARGET}/lib/libc.so
# cd ..
Rebuild the cross compiler:
在有了正確完善的header files和runtime library之後。我們現在可以build一個完整的c/c++ cross compiler.
# mkdir -p build-gcc2 && cd build-gcc2
# ../gcc-3.0.1/configure --target=$TARGET \
--prefix=$PREFIX --enable-languages=c,c++
# make all install
# cd ..
Building a Dreamcast Linux kernel
現在我們有了完整的跨平臺的toolchain了。現在到了該用到這些東西的時候了。前面我們已經把我們的linux的kernel爲Saga Dreamcast設置好了。現在只要compile和link kernel就好了。最後compile出來的文件叫做zImage,在kernel/arch/sh/boot/下面。這個文件是以個被壓縮了的kernel image.
以後,當你用這個kernel正常開機以後,你就可以隨意用menuconfig來調整kernel裏面的各種設置了。然後再recompile一下kernel就好了。
# cd kernel
# make ARCH=sh CROSS_COMPILE=sh4-linux- \
clean dep zImage
# cd ..
Building a Saga Dreamcast Bootloader
當你有了一個正確的compiled kernel image.那么下一步我們就該做一個bootloader用來在Saga Dreamcast 開機的時候,把kernel載入到Saga Dreamcast的記憶體裏面去。
但是,現在還不行。還記得嗎,Saga Dreamcast的硬體載入一個單一的可執行的image到它的RAM裏面。這樣,除非應用程式知道如何與Saga Dreamcast的GD-ROM去溝通,不然就沒有辦法從GD-ROM裏面讀去更多的新資料。我們使用的bootloader並不知道如何來跟Saga Dreamcast的GD-ROM來溝通。所以唯一的方法就是,我們在一開始,就把所有需要的東西全部load進去:bootloader, kernel image, ramdisk image.
一旦所有的東西全部load進去,這時候,bootloader就需要分析記憶體,分清楚kernel和ramdisk image.。這就需要bootloader知道kernel和ramdisk的精確的大小。唯一的方法就是,當做好kernel和ramdisk以後,去計算他們的大小,然後在打造 bootloader的時候,把這些準確的資料提供給bootloader。(source code)
所以,我們現在先要去打造一個應用程式(shell),然後再做一個大小合適的ramdisk給它。最後我們再回到Building Saga Dreamcast Bootloader這裏。
打造一個應用程式
對Linux來說,也許最重要的一個應用程式就是Linux的shell了吧。沒有了shell,甚至不可能去載入其他的程式,不能mount設備,不能……
如果你的Saga Dreamcast沒有鍵盤,那么你就沒有辦法享受Saga Dreamcast上的shell的那種感覺啦。因爲沒有鍵盤,你就沒有辦法輸入指令。
打造一個shell的同時,shell也可以運行你在ramdisk裏面的程式或者script.當你能成功的在Saga Dreamcast上面運行一個shell,那么也就意味著你可以隨意的在Saga Dreamcast上面運行任何一個你想要運行的程式。
下面講述如何爲Saga Dreamcast build一個BusyBox . 在基本的Shell的基礎上,Busybox還提供了幾個很有用的工具:mount, ls and modprobe.
第一步先建立一個目錄叫做 initrd,包含了最初ramdisk的東西。PREFIX是爲了把Busybox安裝到正確的位置。DOSTATIC是告訴sh4-linux-gcc Busybox不要用shared libraries.因爲我們沒有安裝動態的linker (dynamic linker).
# mkdir -p initrd
# export INITRD=`pwd`/initrd
# tar xzf busybox-0.60.1.tar.gz
# patch -p0 < busybox-0.60.1-sh-linux.diff
# cd busybox-0.60.1
# make CROSS=sh4-linux- DOSTATIC=true \
CFLAGS_EXTRA="-I ${PREFIX}/${TARGET}/include" \
PREFIX=${INITRD} clean all install
# cd ..
你可以對Busybox做很多的改變,具體請看Config.h和libbb/libbb.h這兩個文件。
現在我們要在ramdisk上面做device nodes:
因爲ramdisk在Saga Dreamcast中,是扮演的root directory的腳色。所以上面必須有所有的kernel在運行中可能需要的東西。除了shell或者其他的應用程式,我們必須提供device nodes.這樣程式才能跟我們的硬體溝通。
在Saga Dreamcast中,只有一個真正的實質性的device node:/dev/console node.如果沒有這個node,那么文字程式將無法跟console device溝通。簡單的說,就是你看不到螢幕上的顯示。用下面的指令做出device node:
# mkdir -p ${INITRD}/dev
# mknod ${INITRD}/dev/console c 5 1
製作ramdisk image:
現在,我們已經製作好了ramdisk的directory了。接下來我們就該把這個目錄製作成一個image file了。
# dd if=/dev/zero of=initrd.img bs=1k count=4096
# mke2fs -F -vm0 initrd.img
# mkdir initrd.dir
# mount -o loop initrd.img initrd.dir
# (cd initrd ; tar cf - .) | (cd initrd.dir ; tar xvf -)
# umount initrd.dir
# gzip -c -9 initrd.img > initrd.bin
製作bootloader:
Saga Dreamcast的bootloader是Hitachi SH的bootloader的一部分,叫做sh-boot。一些Saga Dreamcast的特定的code被放在sh-boot的目錄中。在子目錄tools/dreamcast中,包含Makefile用來製作bootloader的image檔案。另外還有一個script叫做roast.sh,可以用來製作一個包含Saga Dreamcast bootloader的boot CD。下面的指令將建立Saga Dreamcast的bootloader image:
# tar xzf sh-boot-20010831-1455.tar.gz
# patch -p0 < sh-boot-20010831-1455.diff
# cd sh-boot/tools/dreamcast
# cp ../../../kernel/arch/sh/boot/zImage ./zImage.bin
# cp ../../../initrd.bin .
# make scramble kernel-boot.bin
bootloader的image在這裏是文件kernel-boot.bin.這個文件包含了bootloader自己和前面我們做出來的Linux kernel還有ramdisk image.
製作Dreamcast Boot CD
現在只差最後一步了,那就是把kernel-boot.bin燒錄到CD上去。然後把CD放到Saga Dreamcast上。打開Saga Dreamcast的電源,你就可以看到你的kernel boot了。
前面提到過,sh-boot中有一個叫做roast.sh的script.這個script會幫助我們自動完成CD燒錄步驟。這個script首先把kernel-boot.bin改名爲1ST_READ.BIN(啓動檔案名紀錄爲IP.BIN)然後調用mkisofs來建造一個ISO9660的文件系統image,最有用cdrecoder來燒錄CD.
爲了能正確的使用這個script,在這個文件的最開始部分,你必須給cdrecoder設定一些東西,用以識別你的CD-R機器。
利用下面的指令的到你的CD-r driver的ID。然後把roast.sh中的”1,0,0”換成你的CD-R driver的正確的ID.
如果你的CD-R drive不是SCSI的。那么你需要用“ide-scsi”來做SCSI的類比。也就是說把IDE的drive類比成SCSI來用。截入ide-scsi這個module前,如果你進入了X-window,請記得推出X-window.
# modprobe ide-scsi
# cdrecord -scanbus
scsibus1: 1,0,0 100) 'PHILIPS ' 'PCRW804 ' ' 1.5' Removable CD-ROM
當設定好了一切以後,現在放入一片CD-R。並且運行下面的script。當一切完成以後,你就可以把CD-R放到你的Saga Dreamcast裏面,打開電源,幾秒鐘以後,你就可以在你的Saga Dreamcast中運行Busybox shell啦。
# ./roast.sh kernel-boot.bin
後記
這篇文章講解了一些簡單的步驟來製作一個自己的嵌入式系統,包括打造一個cross compiler, GNU C runtime library, linux kernel, Busybox shell, ramdisk image。以及最後把所有的東西方到一起,燒錄出一片可以在Saga Dreamcast運行的CD.
這裏的一切都只是一個開始。嵌入式系統還有很多的東西等待你去發掘、探索。你可以把你的Busybox換掉,換成你自己寫的程式,或者從網上找到其他的程式,也可以把你的Saga Dreamcast做成好象你的桌面型電腦一樣。給你的Saga Dreamcast加上Sega Broadband Adapter (Ethernet)這樣你可以用你的Saga Dreamcast上網遊覽,收郵件。也可以爲你的Saga Dreamcast加上一個RS232的serial port。這樣你就可以利用這個serial port來跟你的桌上型
電腦溝通。還有很多很多的東西可以做……
-------------------------------------------------------------------------------- Copyright
This article is Copyright (c) 2001 by Bill Gatliff. All rights reserved. Reproduction for personal use is encouraged as long as the document is reproduced in its entirety, including this copyright notice. For other uses, contact the author.
About the Author
Bill Gatliff is an independent consultant with almost ten years of embedded development and training experience. He specializes GNU-based embedded development, and in using and adapting GNU tools to meet the needs of difficult development problems. He welcomes the opportunity to participate in projects of all types.
Bill is a Contributing Editor for Embedded Systems Programming Magazine, a member of the Advisory Panel for the Embedded Systems Conference, maintainer of the Crossgcc FAQ, creator of the gdbstubs project, and a noted author and speaker.
Bill welcomes feedback and suggestions. Contact information is on his website, at http://www.billgatliff.com.
中文出處:www.cosoft.org.cn |
|