ARM Raspbian を PC 上で QEMU usermode emulation する

Facebooktwittergoogle_plustumblrmail

Raspbian のイメージを焼いた SD カードを直接 PC Linux (Ubuntu) 上へマウントし中身の Raspbian 環境をセットアップする方法を紹介する。基本的には Debian Wiki にある記事の内容 (→Raspberry Pi Emulation Using qemu-user-static) の通りだが、途中にいくつかの落とし穴があったので解決方法を補充した。

這篇跟大家分享直接把已有燒入 Raspbian 的 SD 卡掛載到 PC 的 Linux (Ubuntu) 上面,而在 PC Linux 系統上調整 Raspbian 的環境的實際步驟。基本上跟 Debian Wiki 的內容 (-> Raspberry Pi Emulation Using qemu-user-static) 相同,但是我補充中間遇過的有些陷阱與其解決做法。

なおこの文書では以降 /dev/sdd を USB カードリーダーに繋がった SD カードのデバイスエントリとしている。

在此以後 /dev/sdd 用來表示插到讀卡器的 SD 卡片。


Step 1. Install QEMU and sydtemd containers.

$ sudo apt-get install qemu qemu-user-static binfmt-support systemd-container

Step 2. dd

/dev/sdd に含まれるパーティションがどこかへマウントされていないことを確かめてから dd する。

做 dd 之前稍微注意一下都不會被掛載 /dev/sdd 的分區。

$ sudo umount /dev/sdd?
$ sudo dd if=2017-04-10-raspbian-jessie-lite.img of=/dev/sdd bs=512M

Step 3. Resize partition

/dev/sdd2 の領域を SD カードの空き一杯まで広げる。 parted の中で mkpart へ与える引数は各々実際の状況に合わせて変えてほしい。また、この操作により SD カードのそれぞれのパーティションに割り当てられていた PARTUUID の値が変わってしまうので cmdline.txt と fstab を修正する。

分區 /dev/sdd2 放大到 SD 卡後面的整個空間。在 parted 操作中檔使用 mkpart 時指定的參數的部分,請改成跟自己環境適合的數值。另外,因爲這操作會引起各 SD 卡分區的 PARTUID 的改變 (參考後述的「 Step 4-1. Change PARTUUID 」章節 ) ,所以要修改 cmdline.txt 與 fstab 。

$ sudo parted /dev/sdd
GNU Parted 3.2
Using /dev/sdd
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: MXT-USB Storage Device (scsi)
Disk /dev/sdd: 4351MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number Start End Size Type File system Flags
1 4194kB 62.9MB 58.7MB primary fat16 lba
2 62.9MB 3277MB 3214MB primary ext4

(parted) rm 2
(parted) mkpart primary 62.9 4351
(parted) print
Model: MXT-USB Storage Device (scsi)
Disk /dev/sdd: 4351MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number Start End Size Type File system Flags
1 4194kB 62.9MB 58.7MB primary fat16 lba
2 62.9MB 4351MB 4288MB primary lba

(parted) quit

$ sudo e2fsck -f /dev/sdd2
e2fsck 1.42.13 (17-May-2015)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdd2: 86233/261632 files (0.1% non-contiguous), 634636/1046784 blocks

$ sudo resize2fs /dev/sdd2
resize2fs 1.42.12 (29-Aug-2014)
Resizing the filesystem on /dev/sdd2 to 1046784 (4k) blocks.
The filesystem on /dev/sdd2 is now 1046784 (4k) blocks long.

$ sudo blkid
:
/dev/sdd1: LABEL="boot" UUID="70CE-EB76" TYPE="vfat" PARTUUID="4bd62493-01"
/dev/sdd2: UUID="f2100b2f-ed84-4647-b5ae-089280112716" TYPE="ext4" PARTUUID="4bd62493-02"

$ mkdir /tmp/raspbian_mnt
$ sudo mount /dev/sdd2 -o rw /tmp/raspbian_mnt
$ sudo mount /dev/sdd1 -o rw /tmp/raspbian_mnt/boot
$ sudo vi /tmp/raspbian_mnt/etc/fstab
:
: (modify PARTUUID, e.g. 4bd62493-02, 4bd62493-02)
:
$ vi /tmp/raspbian_mnt/boot/cmdline.txt
:
: (modify PARTUUID, e.g. 4bd62493-02)
:
$ sudo umount /dev/sdd?
$ rmdir /tmp/raspbian_mnt

Step 4. Modify files in the Raspbian rootfs

Preparation

SD カードの各パーティションをマウント、 Raspbian の rootfs にある /etc/ld.so.preload の中身を全てコメントアウトし、 PC の qemu-arm-static コマンドを Raspbian の rootfs 内へコピー。最後に QEMU user emulation を起動。

首先掛載 SD 卡的各分區,再來注解掉在 Raspbian rootfs 內 /etc/ld.so.preload 裡面的所有的內容,然後從 PC 把 qemu-arm-static 指令檔複製到 Raspbian 的 rootfs 內。這些做完,就可以啓動 QEMU user emulaiton 。

$ mkdir /tmp/raspbian_mnt
$ sudo mount /dev/sdd2 -o rw /tmp/raspbian_mnt
$ sudo mount /dev/sdd1 -o rw /tmp/raspbian_mnt/boot
$ sudo vi /tmp/raspbian_mnt/etc/ld.so.preload
:
: (comment out everything)
:
$ sudo cp /usr/bin/qemu-arm-static /tmp/raspbian_mnt/usr/bin
$ sudo systemd-nspawn --directory='/tmp/raspbian_mnt' 'bin/bash'
Spawning container mnt on /tmp/raspbian_mnt.
Press ^] three times within 1s to kill container.
Failed to create directory /tmp/raspbian_mnt/sys/fs/selinux: Read-only file system
Failed to create directory /tmp/raspbian_mnt/sys/fs/selinux: Read-only file system
/etc/localtime is not a symlink, not updating container timezone.
root@raspbian_mnt:/#

以降、 PC の上で ARM の環境として Raspbian のユーザーランドの操作が可能。

以後在 PC 上實現虛擬 ARM 環境而可以做任何的 Raspbian 的 user land 的操作。

Step 4-1. Change hostname

root@raspbian_mnt:/# vi /etc/hostname
    :
    : (edit, "raspberry" -> name as you want)
    :
root@raspbian_mnt:/# vi /etc/hosts
    :
    : (edit, "raspberry" -> name as you want)
    :

Step 4-2. Remove calling of init_resize.sh

「 Step 3. Resize partition 」でパーティションの拡張は実施済みなので、 /boot/cmdline.txt から「 init=init_resize.sh 」の部分を削除する。

因爲在「 Step 3. Resize partition 」已經做完放大分區的步驟,所以從 /boot/cmdline.txt  檔刪除掉「 init=init_resize.sh 」的指定。

root@raspbian_mnt:/# vi /boot/cmdline.txt
    :
    : (remove "init=init_resize.sh")
    :

Step 4-3. Setup Wi-Fi (OPTION)

必要ならばこの時点で Wi-Fi のセットアップを実施。

如果需要的話,在這裡預先可以做 Wi-Fi 的設定。

root@raspbian_mnt:/# wpa_passphrase <SSID> <PASSWORD>
network={
    ssid="<SSID>"
    #psk="<PASSWORD>"
    psk=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
}

root@raspbian_mnt:/# vi /etc/wpa_supplicant/wpa_supplicant.conf
    :
    : (change ``country=GB`` -> ``country=TW``)
    : (paste your network information -- as generated above -- at tail)
    :

Step 4-4. Enable SSH daemon (OPTION)

Raspbian ブート後に sshd が走ってたい場合には、空の /boot/ssh ファイルを作っておく。

啓動 Raspbian 後想要開始跑 sshd ,產生 /boot/ssh 檔 (空檔就好) 。

root@raspbian_mnt:/# touch /boot/ssh

Step 4-5. etc..

その他、 apt-get などがしたければどうぞ。

其他想要做,就可以做,例如, apt-get 等等。

root@raspbian_mnt:/# apt-get update
root@raspbian_mnt:/# apt-get dist-upgrade
root@raspbian_mnt:/# apt-get install (...as you want)
    :
root@raspbian_mnt:/# apt-get autoremove
root@raspbian_mnt:/# apt-get autoclean
root@raspbian_mnt:/# apt-get clean

Cleanup

QEMU usermode emulation から抜け、作業開始時にコメントアウトした Raspbian の /etc/ld.so.preload の中身を全て元に戻す。最後に SD カードの各パーティションをアンマウント。

跳出 QEMU usermode emulation ,而要回復剛才注解掉的,在 Raspbian rootfs 內 /etc/ld.so.preload 裡面的所有的內容。最後卸載 Raspbian 的各分區。

root@raspbian_mnt:/# exit
$ sudo vi /tmp/raspbian_mnt/etc/ld.so.preload
    :
    : (restore everything that commented out before)
    :
$ sudo umount /dev/sdd?
$ rmdir /tmp/raspbian_mnt

Step 5. Launch Raspbian!

SD カードを Raspberry Pi へ挿して電源 ON!

把 SD 卡插到 Raspberry Pi 而上電!


Appendix A. QEMU launching script for loopback

イメージファイルを直接ループバックマウントして前述と同様の QEMU usermode emulation 環境を起動するスクリプトの例。

這腳本是個範例,是直接把 Raspbian 的 image 檔用 loopback 的方式掛載起來,而啓動跟上述似的 QEMU usermode emulation 環境。

#!/bin/bash

## apt-get install qemu qemu-user-static binfmt-support systemd-container

set -eu

readonly raspbiandir_="`pwd`/mnt"

readonly uid_="`/usr/bin/id | /bin/sed 's/uid=\([0-9]*\)(.*/\1/'`"
if [ 0 -ne "$uid_" ] ; then
  cat << EOT__ >&2
Need as root.
EOT__
  exit 1
fi

gotdev_="`/sbin/losetup --find --show --partscan 2017-04-10-raspbian-jessie-lite.img`"
ret_="$?"

if [ 0 -ne "$ret_" -o 'x' = x"$gotdev_" ] ; then
  cat << EOT__ >&2
Failure creation loopback device.
EOT__
  exit 1
fi

readonly loopdev_="$gotdev_"

/bin/mkdir -p "$raspbiandir_"

on_exit_() {
  /bin/umount "${raspbiandir_}/boot"
  /bin/umount "${raspbiandir_}"
  /sbin/losetup --detach "$loopdev_"
}

trap 'on_exit_' EXIT

#
# Note that we need to comment out all lines in the
# "${raspbiandir_}/etc/ld.so.preload" before launch
# systemd-nspawn.
#
/bin/mount "${loopdev_}p2" -o rw "$raspbiandir_"
/bin/mount "${loopdev_}p1" -o rw "${raspbiandir_}/boot"
/bin/cp -f /usr/bin/qemu-arm-static "${raspbiandir_}/usr/bin"
/usr/bin/systemd-nspawn --directory="$raspbiandir_" 'bin/bash'

exit 0

参考サイト

Facebooktwittergoogle_plustumblrmail
Yusuke Dada K.
Yusuke Dada K.
台湾の現地企業で主に組み込みソフトウエアの研究開発をしている日本人です。我人是個日本人,負責軟體的研究開發。在臺灣的科技公司工作。

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です