動手打造Debian root filesystem for ARM

動手打造Debian root filesystem for ARM

一切動力皆來自於 why ?

每次都使用別人做好的image file 來用在自己的ARM 開發板上. 對於別人是如何做出這樣的image file 感到好奇.
於是花了一些時間, 想要動手打造自己開發板上專屬的image file. 上網找了一下, 原本是想從Linux From Scratch著手. 覺得LFS 才是真正從底部打造起, 但是後來想想, 若某個軟體有bug, 想要更新時, 還得從souce code 抓下來, 一個個補上去, 我似乎沒辦法整天都在盯著軟體的漏洞跑. 最後決定採用Debian Distribution, 因為感覺他比較自由. 有漏洞時, 只要用apt 去更新套件就好. 因此動手打造Debian 的Root File System 就成了第一個目標.

事前準備

在動手之前, 先用apt先準備下列套件

# apt-get install binfmt-support qemu qemu-user-static debootstrap kpartx lvm2 dosfstools

然後參考這裡裝上ARM GNU toolchain (Cross compiler). 如果你是用ubuntu 好像直接用apt 就可以裝

# apt-get install crossbuild-essential-armhf

(步驟 1) 建立空白的image file

利用dd 建立一的空白的1.9GB image file, 這個image 是為了以後可以直接燒入到SD Card 或TF Card.

# dd if=/dev/zero of=rootfs.img  bs=1048576 count=1900

(步驟 2) 在image file 中建立partition.

先用losetup 將此image file 做成一個loop device.

# losetup -f --show rootfs.img
/dev/loop0

接下來我們可以把這個/dev/loop0 當作是一個硬碟來, 用fdisk 來創造partition. 我將建立2個partition, 1個是FAT格式的, 為了以後能放uboot 及linux kernel image file.
另一個是ext4格式, 存放Debian root filesystem. 第一個partition 大約只要100MB 就夠了.

# fdisk /dev/loop0
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0xbe3cb21f.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-3891199, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-3891199, default 3891199): +100M

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): c
Changed system type of partition 1 to c (W95 FAT32 (LBA))

Command (m for help): n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): p
Partition number (1-4, default 2): 2
First sector (206848-3891199, default 206848): 
Using default value 206848
Last sector, +sectors or +size{K,M,G} (206848-3891199, default 3891199): 
Using default value 3891199

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 22: 不適用的引數.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.

fdisk 完後記得卸載/dev/loop0

# losetup -d /dev/loop0

(步驟 3) 格式化partition

使用kpartx 將image file 中的兩個partition 都掛成loop device.

# kpartx -va rootfs.img
add map loop0p1 (254:0): 0 204800 linear /dev/loop0 2048
add map loop0p2 (254:1): 0 3684352 linear /dev/loop0 206848
#
# ls -al /dev/mapper/loop0p?
/dev/mapper/loop0p1  /dev/mapper/loop0p2

這兩個partition 分別掛成/dev/mapper/loop0p1, 及/dev/mapper/loop0p2

分別將這兩個partition 格式化成FAT及EXT4 filesystem

# mkfs.vfat /dev/mapper/loop0p1
# mkfs.ext4 /dev/mapper/loop0p2

(步驟 4) 第一階段安裝Debian root filesystem

現在開始準備安裝最基本Debian system 到/dev/mapper/loop0p2 下.

首先建立一個目錄叫rootfs,將/dev/mapper/loop0p2 mount 到此目錄, 然後使用debootstrap 做第一階段安裝.

# mkdir -p /root/tmp/rootfs
# mount /dev/mapper/loop0p2 /root/tmp/rootfs
# debootstrap --foreign --arch armhf wheezy /root/tmp/rootfs http://http.debian.net/debian

將qemu arm 的程式拷貝到rootfs 中的/usr/bin 裡面

# cp /usr/bin/qemu-arm-static /root/tmp/rootfs/usr/bin/

(步驟 5) 第二階段安裝Debian root filesystem

接下來做Debian system 第二階段安裝

# LANG=C chroot /root/tmp/rootfs /debootstrap/debootstrap --second-stage

建立新Debian system 中 /etc目錄下必要的檔案

# cat << EOF > /root/tmp/rootfs/etc/apt/sources.list
> deb http://http.debian.net/debian wheezy main contrib non-free
> EOF

# cat << EOF > /root/tmp/rootfs/etc/fstab
> proc            /proc           proc    defaults        0       0
> /dev/mmcblk0p1  /boot           vfat    defaults        0       0
> EOF

# echo "bsms" > /root/tmp/rootfs/etc/hostname

# cat << EOF > /root/tmp/rootfs/etc/resolv.conf
> nameserver 8.8.8.8
> EOF

# cat << EOF > /root/tmp/rootfs/etc/network/interfaces
> auto lo
> iface lo inet loopback
>
> auto eth0
> allow-hotplug eth0
>
> iface eth0 inet dhcp
>
> EOF

# echo T0:2345:respawn:/sbin/getty -L ttyS0 115200 vt100 >> /root/tmp/rootfs/etc/inittab

以上檔案內容可以依據你自己的需求來做修改.

(步驟 6) 第三階段安裝Debian root filesystem

接下來做Debian system 第三階段安裝

# export MALLOC_CHECK_=0
# export LC_ALL=C
# export DEBIAN_FRONTEND=noninteractive

# mount -t proc proc /root/tmp/rootfs/proc
# mount -o bind /dev/ /root/tmp/rootfs/dev/
# mount -o bind /dev/pts /root/tmp/rootfs/dev/pts

# cat << EOF > /root/tmp/rootfs/debconf.set
> console-common console-data/keymap/policy select Select keymap from full list
> console-common console-data/keymap/full select en-latin1-nodeadkeys
> EOF

# cat << EOF > /root/tmp/rootfs/third-stage
> #!/bin/bash
> apt-get update
> apt-get install locales locales-all
> locale-gen en_US.UTF-8
>
> debconf-set-selections /debconf.set
> rm -f /debconf.set
> apt-get update
> apt-get -y install git-core binutils ca-certificates initramfs-tools uboot-mkimage
> apt-get -y install locales console-common ntp less openssh-server nano git vim 
> apt-get -y install wireless-tools wpasupplicant
> echo "root:123456" | chpasswd
> sed -i -e 's/KERNEL\!=\"eth\*|/KERNEL\!=\"/' /lib/udev/rules.d/75-persistent-net-generator.rules
> rm -f /etc/udev/rules.d/70-persistent-net.rules
> rm -f /third-stage
> EOF

# chmod +x /root/tmp/rootfs/third-stage
# LANG=C chroot /root/tmp/rootfs /third-stage

(步驟 7) 最後動作.

其實到了步驟6, 就已經做完Debian root filesystem 了.
首先停止qemu-arm-static 這個process.

# ps -ef | grep qemu-arm-static | awk '{print $2}' | xargs kill -9

接下來要umount 之前掛載的目錄

# umount /root/tmp/rootfs/proc
# umount /root/tmp/rootfs/dev/pts
# umount /root/tmp/rootfs/dev/   
# umount /root/tmp/rootfs

最後卸下loop device 即可.

# kpartx -d rootfs.img

大功告成. 這個rootfs.img 檔已經包含了基本的Debian root filesystem 了.

後續

但是別太興奮的將這個檔燒到SD Card 或TF Card. 因為這樣還不能夠將 ARM 系統正常開機.

他還缺2的東西, uboot 及kernel. 由於這兩的東西跟你的ARM 開發板有絕對的關係, 因此不同家的板子, 其作法都有些不同
下次有機會, 再來討論如何將uboot 及kernel 整合到這個rootfs.img 檔中, 使它能夠真正的在ARM 板子上開機起來.
關於如何建立Cubieboard 的uboot, 及linux kernel 請參考這篇文章

自動化建立root filesystem 的script

做了上面那麼多的動作後, 應該會覺得很累了. 因此我寫了一個自動化的script 讓上面的所有步驟一氣呵成.可以讓省下許多時間去喝杯咖啡吧.

請到這裡抓取這個自動化的script.


參考資料

  1. Ubuntu – 建立 ARM Toolchain (Cross Compiler)
  2. GNU Tools for ARM Embedded Processors
  3. Debootstrap
  4. Preparing a Kali Linux ARM chroot
This entry was posted in embedded system, Linux and tagged , , . Bookmark the permalink.

4 Responses to 動手打造Debian root filesystem for ARM

  1. Ten says:

    你好,”如何將uboot 及kernel 整合到這個rootfs.img 檔”已經出刊了嗎?

    • hao says:

      我在Github 中有建立了一組script 可以自動化產生Cubieboard 的 linux kernel image 及 u-boot image. 並且裡面含有兩個script 可以將u-boot 及 linux kernel 整合到 rootfs.img 中. 細節部分, 可能過完年後我才有空在blog中更新. 你可以先到Github 中查看這些script 的source code.

  2. zing says:

    你好,请问可以分享一下编译好的带有sunxi_mem的镜像吗,非常感谢

  3. box9229 says:

    1 #./update_kernel_to_disk_images.sh img ../DebianRootFS4ARM/rootfs.img output_cb3/kernel/

    2 #./update_uboot_to_disk_images.sh img ../DebianRootFS4ARM/rootfs.img output_cb3/uboot/

    看了一下 兩個script 試燒到SD Card可以開機了

發佈回覆給「hao」的留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *