製作ARM9的Bootstrap Root Filesystem
作者/陳俊宏
来自于: http://192.192.6.72/cis/viewthread.php?tid=10422&extra=page%3D1
目的
製作 bootstrap root filesystem(base root filesystem)以提供一個最簡單、陽春且可開機的環境;製作完成的系統可開機到shell模式,並可使用 busybox 提供的指令。
準備工作
首先,您必須準備一台 host 開發環境,並安裝好 cross toolchain;接著,由於本文是做實機測試,因此,如果您沒有 ARM9 開發板,可以考慮使用 Qemu 來做模擬測試。
以下的操作示範,只節錄重點指令片段,您可能必須根據自己的整體實作流程,來微調指令的順序,或是參數等。
Step 1:建立工作目錄
建立一個專用的工作目錄,命名為 arm9.so-busybox/:
# mkdir arm9.so-busybox/
# cd arm9.so-busybox/
接著在 arm9.so-busybox/ 目錄下建立 4 個子目錄:
# mkdir src/ install/ mnt/ pub/ build/
實際進行 root filesystem 實作時,我們應該養成將檔案分類擺放的好習慣。以本專案為例,build/ 目錄用來編譯程式,src/ 目錄用來存放原始程式碼,install/ 目錄則用來擺放我們最後的 root filesystem。
Step 2:建立目錄架構
根據 FHS 的目錄架構標準,在 root filesystem 目錄下(install/)建立目錄階層架構:
# cd install/
# mkdir bin/ dev/ etc/ mnt/ proc/ sbin/ usr/ pub/
另外還有二個必要的目錄:/var 與 /tmp,由於這二個目錄都需要具備寫入權限,所以在這裡我們是以 ramdisk 的做法來 mount 這二個目錄。
Step 3:建立裝置檔
在 root filesystem 的 dev/ 目錄下建立必要的裝置檔:
crw------- 1 root root 5, 1 1月 1 1970 console
crw------- 1 root root 29, 0 1月 1 1970 fb0
crw------- 1 root root 1, 3 1月 1 1970 null
brw------- 1 root root 1, 0 1月 1 1970 ram0
crw------- 1 root root 5, 0 1月 1 1970 tty
crw------- 1 root root 4, 0 1月 1 1970 tty0
此階段使用 mknod 指令來完成。請先切換到 root filesystem 的 dev/ 目錄下,接著執行以下指令:
# mknod console c 5 1
# mknod fb0 c 29 0
# mknod null c 1 3
# mknod ram0 b 1 0
# mknod tty c 5 0
# mknod tty0 c 4 0
對於需要產生大量 device file 的場合來說,可以改用 genext2fs 的 ‘-D’ 參數來製作。詳見 Jollen’s Blog:[使用 genext2fs 的 '-D'(device file table)來建立 root filesystem]。
Step 4:加入Busybox
編譯並安裝 Busybox(動態程式庫方式)。將取得的Busybox原始碼解壓縮至 project 目錄裡的 src/ 子目錄下,以下是幾個注意事項:
本教學文件使用 Busybox 1.3.1
Busybox 1.3.0 開始,使用 Linux Kernel 的 Makefile(因為開始支援 CONFIG_DESKTOP)。Cross compile 時,需要修改 Makefile 如下:
ARCH ?= arm
CROSS_COMPILE ?= /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-
CROSS_COMPILE 的設定是 cross toolchain 的「PREFIX」,視您的 toolchain 而定。您可由 http://www.jollen.org/kit/ 下載本文所使用的 GCC 3.4.1 ARM9 toolchain,以使用與本文完全相同的修改。 Busybox 整合了常用的指令與工具,我們可以設定 Busybox,以勾選我們需要的功能選項。進入 Busybox 的設定選單: # make menuconfig 請注意,init 與 shell 是必選的項目,請檢查是否有勾選這二個功能。同時,也別忘了設定 Busybox 的安裝路徑,將安裝路徑指到我們 root filesystem 目錄下。 接著直接進行編譯(cross compile): # make 編譯完成後,將 Busybox 安裝至我們的 root filesystem 目錄(即 Step 2 的 install/ 目錄): # make install 此時,您應該可以在 root filesystem 目錄下看到 Busybox 所安裝的檔案。 Step 5:加入動態程式庫 編譯完成的 Busybox 已經是給 ARM9 執行的格式了,但我們的編譯設定是將Busybox 編譯成 shared library 架構,因此 Busybox 執行時需要以下的檔案: ˙ libc.so.6:C library標準程式庫。 ˙ ld-linux.so.2:Native dynamic loader。 請由 toolchain 將以上二個檔案複製至 root filesystem 的 lib/ 目錄下: # cd ../../install (切換至root filesystem根目錄) # cp /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/ld-linux.so.2 lib/ (複制native dynamic loader。以上命令請勿斷行) # cp /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/libc.so.6 lib/ (複製C library。以上命令請勿斷行) Busybox 會因版本與功能選項設定的差異,而需要更多的程式庫。請使用 cross toolchain 的 objdump 指令來檢查 Busybox 的程式庫相依問題(無法使用 ldd 指令),並將所需的程式庫由 toolchain 複製到 root filesystem 的 lib/ 目錄下。 Step 6:加入系統檔案 加入2個重要的系統檔案於 etc/ 目錄下: ˙ fstab:mount table。 ˙ inittab:系統初始表(init table)。 etc/fstab內容如下: /dev/ram0 / ext2 defaults 1 1 none /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 tmpfs /var tmpfs defaults 0 0 fstab 第一行設定,目的在將 /dev/ram0 重新附掛成 ‘/’(root),此動作用意在於重新指定 ‘/’ 的檔案系統為 ext2。最後二行的目的是為了以 ramfs 來 mount 重要的二個目錄:/var 與 /tmp;如此一來,就算開機沒做 remount root(詳見後文說明),也能對 /tmp 與 /var 目錄做寫入的動作 etc/inittab內容如下: :0:sysinit:/etc/rc.d/rc.init :0:respawn:/bin/sh 根據這個 inittab 設定,當系統開機後便會進入 run level 0,在 run level 0 模式下,init process會執行2個動作:(1) 執行 /etc/rc.d/rc.init,此即「init script」;(2) 執行 /bin/sh,即進入 shell 模式。 在此我們並沒有參照 LSB 的標準來設定 run level,而且也沒有使用 getty 來讓使用者登入(多使用者模式)。 Step 7:編寫 Initial Script 根據 inittab 的設定,我們 root filesystem 的 init script 位於 /etc/rc.d/rc.init。以下提供一個供 Embedded Linux 使用的 init script 範本: #!/bin/sh # automount (/etc/fstab) mount -a # remount root mount -o remount rw / # mkdir /var/lock mkdir /var/lock/subsys mkdir /var/run # start other applications (Running application automatically during # booting up. # eg. /bin/thttpd –p 80 –d /var/www 當我們執行「mount –a」後,mount 便會去讀取前一步驟所設定的 fstab,並根據此表格的內容來做 mount 的動作。另外,這裡有一個 remount 的動作: # mount -o remount rw / 此動作的目的是將 root(’/’)重新 mount 成可讀寫,此動作是選擇性的,若省略不做,請務必保持 /var 與 /tmp 目錄是能寫入的(建議以 ramdisk 方式實作為佳)。 若 root filesystem 未包含 inittab 設定檔,則 Busybox 會使用以下的內建設定: ::sysinit:/etc/init.d/rcS ::askfirst:/bin/sh ::ctrlaltdel:/sbin/reboot ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -r ::restart:/sbin/init 不過,還是建議編寫自己的 inittab 設定檔。 Step 8: 製作 Root Filesystem 映像檔(Image File) mkcramfs install root.cramfs 直接將建好的 root file system 就是 install 目錄 壓成 root.cramfs 大功告成 *************************************************8 Step 8:製作 Root Filesystem 映像檔(Image File) 截至目前為止,我們的檔案系統已經擁有基本的系統指令與工具。接下來,我們即可將建置完成的 root filesystem 製作成 ext2 格式的映像檔。 以下提供二種 ext2fs image file 的製作方式:(1) 土方法;(2) 使用 genext2fs 工具。 先說明傳統的土方法。首先,先利用dd指令做出一個空白的檔案,大小為 4M(bytes): # dd if=/dev/zero of=ext2fs bs=1k count=4096 我們將檔案命名為 ext2fs,接著再將 ext2fs 製作成 ext2 格式的檔案系統: # mkfs.ext2 ext2fs mke2fs 1.32(09-Nov-2002) ext2fs is not a block special device. Proceed anyway?(y,n)y 選擇y後出現以下畫面: Filesystem label= OS type: Linux Block size=1024(log=0) Fragment size=1024(log=0) 128 inodes, 1024 blocks 51 blocks(4.98%)reserved for the super user First data block=1 1 block group 8192 blocks per group, 8192 fragments per group 128 inodes per group Writing inode tables: done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 26 mounts or 180 days, whichever comes first. Use tune2fs -c or -i to override. 到這裡我們已經做好一個檔案格式為 ext2 的空白映像檔,再來只要將先前做好的 root filesystem 全部複製到 ext2fs 映像檔「裡面」即可。 先將 ext2fs 附掛至任一空目錄,例如 mnt/: # mkdir mnt/ # mount -t ext2 -o loop ext2fs mnt/ (指定檔案系統為 ext2) 複製檔案系統時,我們不使用 cp 指令,而是利用 tar 來完成: # cd install/ # tar cz * > ../install.tar.gz (將檔案系統做成tarball,同時也備份 root filesystem。) # cd .. # cd mnt/ # tar zxvf ../install.tar.gz (再將tarball解至映像檔) 接著將映像檔 umount 並壓縮即可: # cd .. # umount mnt/ # gzip -9c ext2fs > pub/ext2fs.gz 最後得到的 ext2fs.gz 即是完成品。請注意,若不使用 tar 來說,也應該使用 cpio 來複製檔案,避免使用 cp 指令。
来自于: http://192.192.6.72/cis/viewthread.php?tid=10422&extra=page%3D1
目的
製作 bootstrap root filesystem(base root filesystem)以提供一個最簡單、陽春且可開機的環境;製作完成的系統可開機到shell模式,並可使用 busybox 提供的指令。
準備工作
首先,您必須準備一台 host 開發環境,並安裝好 cross toolchain;接著,由於本文是做實機測試,因此,如果您沒有 ARM9 開發板,可以考慮使用 Qemu 來做模擬測試。
以下的操作示範,只節錄重點指令片段,您可能必須根據自己的整體實作流程,來微調指令的順序,或是參數等。
Step 1:建立工作目錄
建立一個專用的工作目錄,命名為 arm9.so-busybox/:
# mkdir arm9.so-busybox/
# cd arm9.so-busybox/
接著在 arm9.so-busybox/ 目錄下建立 4 個子目錄:
# mkdir src/ install/ mnt/ pub/ build/
實際進行 root filesystem 實作時,我們應該養成將檔案分類擺放的好習慣。以本專案為例,build/ 目錄用來編譯程式,src/ 目錄用來存放原始程式碼,install/ 目錄則用來擺放我們最後的 root filesystem。
Step 2:建立目錄架構
根據 FHS 的目錄架構標準,在 root filesystem 目錄下(install/)建立目錄階層架構:
# cd install/
# mkdir bin/ dev/ etc/ mnt/ proc/ sbin/ usr/ pub/
另外還有二個必要的目錄:/var 與 /tmp,由於這二個目錄都需要具備寫入權限,所以在這裡我們是以 ramdisk 的做法來 mount 這二個目錄。
Step 3:建立裝置檔
在 root filesystem 的 dev/ 目錄下建立必要的裝置檔:
crw------- 1 root root 5, 1 1月 1 1970 console
crw------- 1 root root 29, 0 1月 1 1970 fb0
crw------- 1 root root 1, 3 1月 1 1970 null
brw------- 1 root root 1, 0 1月 1 1970 ram0
crw------- 1 root root 5, 0 1月 1 1970 tty
crw------- 1 root root 4, 0 1月 1 1970 tty0
此階段使用 mknod 指令來完成。請先切換到 root filesystem 的 dev/ 目錄下,接著執行以下指令:
# mknod console c 5 1
# mknod fb0 c 29 0
# mknod null c 1 3
# mknod ram0 b 1 0
# mknod tty c 5 0
# mknod tty0 c 4 0
對於需要產生大量 device file 的場合來說,可以改用 genext2fs 的 ‘-D’ 參數來製作。詳見 Jollen’s Blog:[使用 genext2fs 的 '-D'(device file table)來建立 root filesystem]。
Step 4:加入Busybox
編譯並安裝 Busybox(動態程式庫方式)。將取得的Busybox原始碼解壓縮至 project 目錄裡的 src/ 子目錄下,以下是幾個注意事項:
本教學文件使用 Busybox 1.3.1
Busybox 1.3.0 開始,使用 Linux Kernel 的 Makefile(因為開始支援 CONFIG_DESKTOP)。Cross compile 時,需要修改 Makefile 如下:
ARCH ?= arm
CROSS_COMPILE ?= /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-
CROSS_COMPILE 的設定是 cross toolchain 的「PREFIX」,視您的 toolchain 而定。您可由 http://www.jollen.org/kit/ 下載本文所使用的 GCC 3.4.1 ARM9 toolchain,以使用與本文完全相同的修改。 Busybox 整合了常用的指令與工具,我們可以設定 Busybox,以勾選我們需要的功能選項。進入 Busybox 的設定選單: # make menuconfig 請注意,init 與 shell 是必選的項目,請檢查是否有勾選這二個功能。同時,也別忘了設定 Busybox 的安裝路徑,將安裝路徑指到我們 root filesystem 目錄下。 接著直接進行編譯(cross compile): # make 編譯完成後,將 Busybox 安裝至我們的 root filesystem 目錄(即 Step 2 的 install/ 目錄): # make install 此時,您應該可以在 root filesystem 目錄下看到 Busybox 所安裝的檔案。 Step 5:加入動態程式庫 編譯完成的 Busybox 已經是給 ARM9 執行的格式了,但我們的編譯設定是將Busybox 編譯成 shared library 架構,因此 Busybox 執行時需要以下的檔案: ˙ libc.so.6:C library標準程式庫。 ˙ ld-linux.so.2:Native dynamic loader。 請由 toolchain 將以上二個檔案複製至 root filesystem 的 lib/ 目錄下: # cd ../../install (切換至root filesystem根目錄) # cp /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/ld-linux.so.2 lib/ (複制native dynamic loader。以上命令請勿斷行) # cp /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/libc.so.6 lib/ (複製C library。以上命令請勿斷行) Busybox 會因版本與功能選項設定的差異,而需要更多的程式庫。請使用 cross toolchain 的 objdump 指令來檢查 Busybox 的程式庫相依問題(無法使用 ldd 指令),並將所需的程式庫由 toolchain 複製到 root filesystem 的 lib/ 目錄下。 Step 6:加入系統檔案 加入2個重要的系統檔案於 etc/ 目錄下: ˙ fstab:mount table。 ˙ inittab:系統初始表(init table)。 etc/fstab內容如下: /dev/ram0 / ext2 defaults 1 1 none /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 tmpfs /var tmpfs defaults 0 0 fstab 第一行設定,目的在將 /dev/ram0 重新附掛成 ‘/’(root),此動作用意在於重新指定 ‘/’ 的檔案系統為 ext2。最後二行的目的是為了以 ramfs 來 mount 重要的二個目錄:/var 與 /tmp;如此一來,就算開機沒做 remount root(詳見後文說明),也能對 /tmp 與 /var 目錄做寫入的動作 etc/inittab內容如下: :0:sysinit:/etc/rc.d/rc.init :0:respawn:/bin/sh 根據這個 inittab 設定,當系統開機後便會進入 run level 0,在 run level 0 模式下,init process會執行2個動作:(1) 執行 /etc/rc.d/rc.init,此即「init script」;(2) 執行 /bin/sh,即進入 shell 模式。 在此我們並沒有參照 LSB 的標準來設定 run level,而且也沒有使用 getty 來讓使用者登入(多使用者模式)。 Step 7:編寫 Initial Script 根據 inittab 的設定,我們 root filesystem 的 init script 位於 /etc/rc.d/rc.init。以下提供一個供 Embedded Linux 使用的 init script 範本: #!/bin/sh # automount (/etc/fstab) mount -a # remount root mount -o remount rw / # mkdir /var/lock mkdir /var/lock/subsys mkdir /var/run # start other applications (Running application automatically during # booting up. # eg. /bin/thttpd –p 80 –d /var/www 當我們執行「mount –a」後,mount 便會去讀取前一步驟所設定的 fstab,並根據此表格的內容來做 mount 的動作。另外,這裡有一個 remount 的動作: # mount -o remount rw / 此動作的目的是將 root(’/’)重新 mount 成可讀寫,此動作是選擇性的,若省略不做,請務必保持 /var 與 /tmp 目錄是能寫入的(建議以 ramdisk 方式實作為佳)。 若 root filesystem 未包含 inittab 設定檔,則 Busybox 會使用以下的內建設定: ::sysinit:/etc/init.d/rcS ::askfirst:/bin/sh ::ctrlaltdel:/sbin/reboot ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -r ::restart:/sbin/init 不過,還是建議編寫自己的 inittab 設定檔。 Step 8: 製作 Root Filesystem 映像檔(Image File) mkcramfs install root.cramfs 直接將建好的 root file system 就是 install 目錄 壓成 root.cramfs 大功告成 *************************************************8 Step 8:製作 Root Filesystem 映像檔(Image File) 截至目前為止,我們的檔案系統已經擁有基本的系統指令與工具。接下來,我們即可將建置完成的 root filesystem 製作成 ext2 格式的映像檔。 以下提供二種 ext2fs image file 的製作方式:(1) 土方法;(2) 使用 genext2fs 工具。 先說明傳統的土方法。首先,先利用dd指令做出一個空白的檔案,大小為 4M(bytes): # dd if=/dev/zero of=ext2fs bs=1k count=4096 我們將檔案命名為 ext2fs,接著再將 ext2fs 製作成 ext2 格式的檔案系統: # mkfs.ext2 ext2fs mke2fs 1.32(09-Nov-2002) ext2fs is not a block special device. Proceed anyway?(y,n)y 選擇y後出現以下畫面: Filesystem label= OS type: Linux Block size=1024(log=0) Fragment size=1024(log=0) 128 inodes, 1024 blocks 51 blocks(4.98%)reserved for the super user First data block=1 1 block group 8192 blocks per group, 8192 fragments per group 128 inodes per group Writing inode tables: done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 26 mounts or 180 days, whichever comes first. Use tune2fs -c or -i to override. 到這裡我們已經做好一個檔案格式為 ext2 的空白映像檔,再來只要將先前做好的 root filesystem 全部複製到 ext2fs 映像檔「裡面」即可。 先將 ext2fs 附掛至任一空目錄,例如 mnt/: # mkdir mnt/ # mount -t ext2 -o loop ext2fs mnt/ (指定檔案系統為 ext2) 複製檔案系統時,我們不使用 cp 指令,而是利用 tar 來完成: # cd install/ # tar cz * > ../install.tar.gz (將檔案系統做成tarball,同時也備份 root filesystem。) # cd .. # cd mnt/ # tar zxvf ../install.tar.gz (再將tarball解至映像檔) 接著將映像檔 umount 並壓縮即可: # cd .. # umount mnt/ # gzip -9c ext2fs > pub/ext2fs.gz 最後得到的 ext2fs.gz 即是完成品。請注意,若不使用 tar 來說,也應該使用 cpio 來複製檔案,避免使用 cp 指令。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。