SDカードにUbuntuのルートファイルシステムを作成する

zyboでlinuxを動かすときに行った作業ですが、他の場面でも何かの役に立つと思ったメモです。SDカードに２つパーティションを作成して、２つ目のパーティションにルートファイルシステムを作成しています。

# 環境

- ホストPC: lubuntu 18.04
- SDカード 32GB
- SDカードライター

# SDカードの準備

## SDカードの認識

まずSDカードをPCに接続していない状態でlsblkコマンドを実行します。

```SDカード接続前
$ lsblk 
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
nvme0n1     259:0    0   477G  0 disk 
├─nvme0n1p1 259:1    0   512M  0 part 
├─nvme0n1p2 259:2    0     1M  0 part 
└─nvme0n1p3 259:3    0 476.4G  0 part /
```

SDカードを接続してもう一回lsblkコマンドを実行します。するとsdbというデバイスが見えています。これがLinuxが認識しているSDカードのデバイス名になっています。これは環境によって変わってくるので各自の環境に合わせてください。

```SDカード接続後
$ lsblk 
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sdb           8:16   1  28.9G  0 disk 
├─sdb1        8:17   1     1G  0 part /media/yoshi/ZYBO_BOOT
└─sdb2        8:18   1  27.9G  0 part /media/yoshi/ROOT_FS
nvme0n1     259:0    0   477G  0 disk 
├─nvme0n1p1 259:1    0   512M  0 part 
├─nvme0n1p2 259:2    0     1M  0 part 
└─nvme0n1p3 259:3    0 476.4G  0 part /
```

## SDカードデータの消去

この作業は必要な場合のみ行います。一度SDカードのデータは消去し、パーティションもすべて消してしまいます。準備としてumountコマンドでSDカードをアンマウントします。lsblkコマンドで確認してMOUNTPOINTが空になっていればOKです。

```
$ umount /dev/sdb1
$ umount /dev/sdb2
$ lsblk 
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sdb           8:16   1  28.9G  0 disk 
├─sdb1        8:17   1     1G  0 part 
└─sdb2        8:18   1  27.9G  0 part 
nvme0n1     259:0    0   477G  0 disk 
├─nvme0n1p1 259:1    0   512M  0 part 
├─nvme0n1p2 259:2    0     1M  0 part 
└─nvme0n1p3 259:3    0 476.4G  0 part /
```

## SDカードのパーティションの設定

下記のように3ステップで作業を行います。

1. 既存パーティションを削除する
2. 新しいパーティションを作成する
3. 各パーティションにファイルシステムを作成する。

### 既存パーティションを削除する

パーティションを設定するためfdiskコマンドを実行します。/dev/sdbのところは各自の環境に合わせてください。

```
$ sudo fdisk /dev/sdb
```

mコマンドでヘルプが表示されます。このうち、dコマンド、nコマンド、pコマンド、wコマンドを使用していきます。

```
コマンド (m でヘルプ): m

ヘルプ:

  DOS (MBR)
   a   起動可能フラグを切り替えます
   b   入れ子の BSD ディスクラベルを編集します
   c   DOS 互換フラグを切り替えます

  一般
   d   パーティションを削除します
   F   パーティションのない領域を一覧表示します
   l   既知のパーティションタイプを一覧表示します
   n   新しいパーティションを追加します
   p   パーティション情報を表示します
   t   パーティションタイプを変更します
   v   パーティション情報を検証します
   i   パーティションの情報を表示します

  その他
   m   このメニューを表示します
   u   表示項目の単位を変更します
   x   特殊機能に移動します (熟練者向け機能)

  スクリプト
   I   ディスクのレイアウトを sfdisk 互換のスクリプトから読み込みます
   O   ディスクのレイアウトを sfdisk 互換のスクリプトに書き出します

  保存と終了
   w   パーティション情報をディスクに書き込んで終了します
   q   変更点を保存せずに終了します

  新しいラベルを作成します
   g   新しい (何もない) GPT パーティションテーブルを作成します
   G   新しい (何もない) SGI (IRIX) パーティションテーブルを作成します
   o   新しい (何もない) DOS パーティションテーブルを作成します
   s   新しい (何もない) Sun パーティションテーブルを作成します
```

pコマンドで現在のパーティションはsdb1とsdb2の2つのパーティションがあることが確認が出来ます。次からはこの2つのパーティションを削除していきます。

```
コマンド (m でヘルプ): p
ディスク /dev/sdb: 28.9 GiB, 31046238208 バイト, 60637184 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0x001c3a51

デバイス   起動 開始位置 最後から   セクタ サイズ Id タイプ
/dev/sdb1           2048  2099199  2097152     1G 83 Linux
/dev/sdb2        2099200 60637183 58537984  27.9G 83 Linux
```

dコマンドを打つと削除するパーティション番号を聞かれますが、既定値で2なのでエンターだけを入力します。これでパーティション2が消えます。dコマンドをもう一回打つとパーティション1が削除されます。pコマンドで現在のパーティションは何もないことが確認できます。wコマンドでこれらの変更を反映させます。

```
コマンド (m でヘルプ): d
パーティション番号 (1,2, 既定値 2): 

パーティション 2 を削除しました。

コマンド (m でヘルプ): d
パーティション 1 を選択
パーティション 1 を削除しました。

コマンド (m でヘルプ): p
ディスク /dev/sdb: 28.9 GiB, 31046238208 バイト, 60637184 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0x001c3a51

コマンド (m でヘルプ): w
パーティション情報が変更されました。
ioctl() を呼び出してパーティション情報を再読み込みします。
ディスクを同期しています。
```

### 新しいパーティションを作成する

次はパーティションを2つ作成していきます。パーティションの作成もfdiskコマンドで実行します。

```
$ sudo fdisk /dev/sdb
```

- nコマンドで1つ目の新規パーティションを作成していきます。

   - パーティションタイプを聞かれるので基本パーティションを選ぶ。pと入力してエンターを押す。既定値でpなのでそのままエンターを押してもいいです。
   - パーティション番号を聞かれので1を選ぶ。既定値で1なのでそのままエンターを押す。
   - 最初のセクタを聞かれるので、規定値のままでエンターを押す。
   - サイズを聞かれるので、+1Gと入力してエンターを押す。
   - 署名を削除するかどうか聞かれるので、Yと入力してエンターを押す。

```
コマンド (m でヘルプ): n
パーティションタイプ
   p   基本パーティション (0 プライマリ, 0 拡張, 4 空き)
   e   拡張領域 (論理パーティションが入ります)
選択 (既定値 p): p
パーティション番号 (1-4, 既定値 1):
最初のセクタ (2048-60637183, 既定値 2048): 
最終セクタ, +セクタ番号 または +サイズ{K,M,G,T,P} (2048-60637183, 既定値 60637183): +1G

新しいパーティション 1 をタイプ Linux、サイズ 1 GiB で作成しました。
パーティション #1 には vfat 署名が書き込まれています。

署名を削除しますか？ [Y]es/[N]o: Y

署名は write (書き込み)コマンドを実行すると消えてしまいます。
```

- nコマンドで2つ目の新規パーティションを作成していきます。

   - パーティションタイプを聞かれるので基本パーティションを選ぶ。既定値でpなのでそのままエンターを押す。
   - パーティション番号を聞かれので2を選ぶ。既定値で2なのでそのままエンターを押す。
   - 最初のセクタを聞かれるので規定値のままでエンターを押す。
   - 残り全部の領域をパーティション2にする。規定は残り全部になっているのでそのままエンターを押す。
   - 署名を削除するかどうか聞かれるので、Yと入力してエンターを押す。

```
コマンド (m でヘルプ): n
パーティションタイプ
   p   基本パーティション (1 プライマリ, 0 拡張, 3 空き)
   e   拡張領域 (論理パーティションが入ります)
選択 (既定値 p): 

既定の回答 p であるものとみなします。
パーティション番号 (2-4, 既定値 2): 
最初のセクタ (2099200-60637183, 既定値 2099200): 
最終セクタ, +セクタ番号 または +サイズ{K,M,G,T,P} (2099200-60637183, 既定値 60637183): 

新しいパーティション 2 をタイプ Linux、サイズ 27.9 GiB で作成しました。
パーティション #2 には ext4 署名が書き込まれています。

署名を削除しますか？ [Y]es/[N]o: Y

署名は write (書き込み)コマンドを実行すると消えてしまいます。
```

- 作成したパーティションをSDカードに反映します。

   - pコマンドで作成したパーティションの確認が出来ます。sdb1とsdb2が作成されています。
   - wコマンドでSDカードに反映します。

```
コマンド (m でヘルプ): p
ディスク /dev/sdb: 28.9 GiB, 31046238208 バイト, 60637184 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0x001c3a51

デバイス   起動 開始位置 最後から   セクタ サイズ Id タイプ
/dev/sdb1           2048  2099199  2097152     1G 83 Linux
/dev/sdb2        2099200 60637183 58537984  27.9G 83 Linux

パーティション 1 にあるファイルシステム/RAIDの署名が完全に消去されます。
パーティション 2 にあるファイルシステム/RAIDの署名が完全に消去されます。

コマンド (m でヘルプ): w
パーティション情報が変更されました。
ioctl() を呼び出してパーティション情報を再読み込みします。
ディスクを同期しています。
```

### 各パーティションにファイルシステムを作成する。

各パーティションにファイルシステムを作成します。sdb1にvfatファイルシステムを作成してラベル名を-nで指定します。ここではZYBO_BOOTにしていますが、好きな名前で大丈夫です。sdb2にext4ファイルシステムを作成してラベル名を-Lで指定します。ここではROOT_FSにしていますが、ここも好きな名前で大丈夫です。

```
$ sudo lsblk -l /dev/sdb
NAME MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdb    8:16   1 28.9G  0 disk 
sdb1   8:17   1    1G  0 part 
sdb2   8:18   1 27.9G  0 part

$ sudo mkfs.vfat -n ZYBO_BOOT /dev/sdb1
mkfs.fat 4.1 (2017-01-24)

$ sudo mkfs.ext4 /dev/sdb2 -L ROOT_FS
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 7317248 4k blocks and 1831424 inodes
Filesystem UUID: cd251c43-bd53-41a5-8789-60e3100988d0
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	4096000

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
```

SDカードを抜き差した後、適当な場所にマウントされていることが確認できます。

```
$ lsblk -l /dev/sdb
NAME MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdb    8:16   1 28.9G  0 disk 
sdb1   8:17   1    1G  0 part /media/yoshi/ZYBO_BOOT
sdb2   8:18   1 27.9G  0 part /media/yoshi/ROOT_FS
$ ls /media/yoshi/
ROOT_FS  ZYBO_BOOT
```

# root file systemの準備

## root file systemのダウンロード

必要なパッケージをインストールします。

```
$ sudo apt install schroot debootstrap qemu-user-static
```

適当なディレクトリ、ここではROOT_FSを作成してUbuntuのルートファイルシステムをダウンロードします。この例では、バージョン18.04をダウンロードしています。16.04をダウンロードしたい場合はbionicのところをxenialに、14.04をダウンロードしたい場合はtrustyに変更してください。

```
$ mkdir ./ROOT_FS
$ sudo qemu-debootstrap --arch=armhf bionic ./ROOT_FS http://ports.ubuntu.com/ubuntu-ports/
```

zyboにシリアル接続時、ログインできるようにするため、設定ファイルを作成します。

```
$ sudo mkdir -p ./ROOT_FS/etc/init/
$ sudo touch ./ROOT_FS/etc/init/ttyPS0.conf
$ sudo vi ./ROOT_FS/etc/init/ttyPS0.conf
# ttyPS0 - getty
#
# This service maintains a getty on ttyPS0 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345] and (
            not-container or
            container CONTAINER=lxc or
            container CONTAINER=lxc-libvirt)

stop on runlevel [!2345]

respawn
exec /sbin/getty -8 -a root 115200 ttyPS0
```

一般ユーザを追加してsudoerに設定する。yoshiの部分は追加したいユーザ名に変更してください。adduserコマンドを実行すると、追加したいユーザのパスワードを設定する必要があるので、2回入力する。その後もフルネームなども聞かれるがここでは何も入力せずエンターを押しています。gpasswdコマンドで追加したユーザをsudoグループに追加します。


```
$ sudo chroot ./ROOT_FS/
# adduser yoshi
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = "ja",
	LC_ALL = (unset),
	LANG = "ja_JP.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
Adding user `yoshi' ...
Adding new group `yoshi' (1000) ...
Adding new user `yoshi' (1000) with group `yoshi' ...
Creating home directory `/home/yoshi' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for yoshi
Enter the new value, or press ENTER for the default
	Full Name []: 
	Room Number []: 
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n]

# gpasswd -a yoshi sudo
Adding user yoshi to group sudo
```

先程ダウンロードしてきた./ROOT_FSディレクトリをSDカードのパーティション2に同期させます。同期が完了するとSDカード側にファイルがコピーされroot file systemの作成は完了です。コピーサイズによっては時間がかかる場合があるためアンマウントしてSDカードを抜くときは注意してください。

```
$ lsblk -l /dev/sdb
NAME MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdb    8:16   1 28.9G  0 disk 
sdb1   8:17   1    1G  0 part /media/yoshi/ZYBO_BOOT
sdb2   8:18   1 27.9G  0 part /media/yoshi/ROOT_FS
$ sudo rsync -av ./ROOT_FS/ /media/yoshi/ROOT_FS/
```