はじめに
MPFS-DISCO-KIT(Microchip PolarFire SoC FPGA Discovery Kit) で動作する Ubuntu 22.04 を構築する方法をいくつかの記事に分けて説明します。
- イントロ編
- HSS(Hart Software Services)編
- U-Boot 標準編
- U-Boot bootmenu 改造編
- Linux Kernel linux4microchip+fpga-2024.09 編
- Linux Kernel mpfs-fpga-first 編
- Ubuntu 22.04 Root File System 編
- SD-Card 作成編 (この記事)
- SD-Card 起動編
上記の記事で構築した MPFS-DISCO-KIT 向け Ubuntu 22.04 Root File System、Linux Kernel、Boot Loader は次の URL にて公開しています。なお、これらはオフシャルなものではなく、筆者の魔改造がはいっています。ご使用の際はこの点にご留意してください。
- https://github.com/ikwzm/MPFS-FPGA-Ubuntu22.04
- https://github.com/ikwzm/MPFS-FPGA-Linux-Kernel-6.6
- https://github.com/ikwzm/MPFS-DISCO-KIT-U-Boot
この記事では、SD-Card に U-Boot、Linux Kernel、Ubuntu 22.04 Root File System を書き込む方法を説明します。
必要な環境
私は次の環境を用意して SD-Card に書き込みました。
- Ubuntu 22.04
- gdisk
- dd
- mkfs.vfat
- mkfs.ext4
SD-Card に書き込むファイルの説明
SD-Card に書き込むファイルとして以下のもの用意します。
- target/mpfs-disco-kit
- u-boot/
- uboot.img : U-Boot Image
- boot/
- uboot.env : U-Boot environment
- uEnv.txt : U-Boot environment variables for linux boot
- boot.scr : U-Boot Script file
- devicetree-6.6.51-mpfs-fpga-first-mpfs-disco-kit.dtb : Linux Device Tree Blob
- devicetree-6.6.51-mpfs-fpga-first-mpfs-disco-kit.dts : Linux Device Tree Blob
- u-boot/
- files/
- vmlinuz-6.6.51-mpfs-fpga-first-1 : Linux Kernel Image
- ubuntu22.04-rootfs.tgz.files/ : Ubuntu22.04 Root File System
- x00 .. x09 : (splited files)
- debian/
- linux-image-6.6.51-mpfs-fpga-first_6.6.51-mpfs-fpga-1_riscv64.deb : Linux Image Package
- linux-headers-6.6.51-mpfs-fpga-first_6.6.51-mpfs-fpga-1_riscv64.deb : Linux Headers Package
上記のファイル群は以下の URL で提供しています。一から作るのが面倒なかたは、こちらからダウンロードしてください。
target/mpfs-disco-kit/u-boot/uboot.img
MPFS-DISCO-KIT 用の u-boot のイメージファイルです。
HSS(Hart Software Services) から起動するため、HSS Payload Generator で生成され、ブート専用のパーティションに書き込まれます。
作りかたは、『U-Boot bootmenu 改造編』 を参照してください。
target/mpfs-disco-kit/boot/uboot.env
MPFS-DISCO-KIT 用の uboot.img が起動時に設定する環境変数のファイルです。
uboot.img から読まれるため、VFAT でフォーマットされたパーティション1 に書き込まれます。
作りかたは、『U-Boot bootmenu 改造編』 を参照してください。
target/mpfs-disco-kit/boot/boot.scr
MPFS-DISCO-KIT 用の uboot.img が boot コマンド実行の際に実行されるスクリプトファイルです。
uEnv.txt が無い場合、または uEnv.txt で uenvcmd 変数が定義されていない場合に実行されます。
uboot.img から読まれるため、VFAT でフォーマットされたパーティション1 に書き込まれます。
作りかたは、『U-Boot bootmenu 改造編』 を参照してください。
target/mpfs-disco-kit/boot/uEnv.txt
MPFS-DISCO-KIT 用の uboot.img が起動時に設定する環境変数のファイルです。
uboot.img から読まれるため、VFAT でフォーマットされたパーティション1 に書き込まれます。
uboot.env と異り修正しやすいテキストファイルになっています。
このファイルに uenvcmd 変数を定義しておくと、boot.scr より優先して uenvcmd 変数で定義されたコマンドを実行します。
ここでは次のような uEnv.txt を用意しています。
########################################################################
# Linux Kernel Files
# * linux_kernel_image : Linux Kernel Image File Name
# * linux_fdt_image : Linux Device Tree Blob File Name
########################################################################
linux_kernel_image=vmlinux-6.6.51-mpfs-fpga-first
linux_fdt_image=devicetree-6.6.51-mpfs-fpga-first-mpfs-disco-kit.dtb
########################################################################
# Linux Boot Argments
# * linux_boot_args_console : ex) console=tty1
# console=ttyPS0,115200
# * linux_boot_args_rootfs : ex) root=/dev/mmcblk0p2 rw rootwait
# * linux_boot_args_systemd : ex) systemd.unit=graphical.target
# systemd.unit=multi-user.target
# * linux_boot_args_cpuidle : ex) cpuidle.off=1
# * linux_boot_args_cma : ex) cma=256M
# * linux_boot_args_uio : ex) uio=uio_pdrv_genirq.of_id=generic-uio
# * linux_boot_args_other :
########################################################################
linux_boot_args_console=
linux_boot_args_rootfs=root=/dev/mmcblk0p3 rw rootwait
linux_boot_args_systemd=
linux_boot_args_cpuidle=
linux_boot_args_cma=
linux_boot_args_uio=uio_pdrv_genirq.of_id=generic-uio
linux_boot_args_other=
########################################################################
# uenvcmd : During sdboot, if uenvcmd is set, uenvcmd will be executed.
########################################################################
linux_img_load_cmd=load mmc 0:1 ${kernel_addr_r} ${linux_kernel_image}
linux_fdt_load_cmd=load mmc 0:1 ${fdt_addr_r} ${linux_fdt_image}
linux_fdt_update_cmd=fdt addr ${fdt_addr_r} ; fdt set /soc/ethernet@20110000 local-mac-address ${discokit_mac_addr0}
linux_load_cmd=env run linux_img_load_cmd && env run linux_fdt_load_cmd && env run linux_fdt_update_cmd
linux_boot_cmd=booti ${kernel_addr_r} - ${fdt_addr_r}
linux_args_cmd=if env exists linux_boot_args; then; setenv bootargs ${linux_boot_args}; else; setenv bootargs ${linux_boot_args_console} ${linux_boot_args_rootfs} ${linux_boot_args_systemd} ${linux_boot_args_cpuidle} ${linux_boot_args_cma} ${linux_boot_args_uio} ${linux_boot_args_other}; fi
uenvcmd=env run linux_args_cmd && env run linux_load_cmd && env run linux_boot_cmd
########################################################################
# external_env_file : external environment file.
# external_env_boot : import external_env_file and boot.
########################################################################
external_env_existence_test=test -e mmc 0:1 ${external_env_file}
external_env_load=load mmc 0:1 ${scriptaddr} ${external_env_file}
external_env_import=env import -t ${scriptaddr} $filesize
external_env_set=env run external_env_existence_test && env run external_env_load && env run external_env_import
external_env_boot=if env run external_env_set; then; boot; else; echo "## Error Read fail " ${external_env_file}; fi
########################################################################
# Boot Menu
########################################################################
bootmenu_0=Boot Default=boot
bootmenu_1=Boot linux-6.6.51-mpfs-fpga-first=env set external_env_file uEnv-linux-6.6.51-mpfs-fpga-first.txt && env run external_env_boot
bootdelay=5
- linux_kernel_image 変数には、Linux Kernel イメージのファイル名を指定します。
ここでは後述の vmlinuz-6.6.51-mpfs-fpga-first-1 を解凍したファイル名を指定しています。 - linux_fdt_image 変数には Linux Kernel Device Tree Blob のファイル名を指定します。
ここでは後述の devicetree-6.6.51-mpfs-fpga-first-mpfs-disco-kit.dtb を指定しています。 - linux_boot_args_ で始まる変数には、Linux Kernel のブート時に Kernel に渡される引数を定義しています。
これらの変数の内容は bootargs 変数にセットされてLinux Kernel のブート時に Kernel に渡されます。 - uenvcmd 変数には 上記で指定したファイルを mmc 0:1(SD-Card のデバイス0 パーティション 1) からロードし、bootargs 変数をセットして booti コマンドを実行するようにしています。
- bootmenu_0 変数には、U-boot 起動後にメニューに表示する内容と実行するコマンドを定義しています。
- bootmenu_1 変数には、U-boot 起動後にメニューに表示する内容と実行するコマンドを定義しています。
- bootdelay 変数には、 U-boot 起動後にメニューを表示した際にキー入力の待ち時間を秒で指定します。
ちなみに、bootdelay 変数に 0 を指定すると、メニューを表示せずに問答無用で bootmenu_0 変数で定義されたコマンドを実行します。
target/mpfs-disco-kit/boot/devicetree-6.6.51-mpfs-fpga-first-mpfs-disco-kit.dtb
MPFS-DISCO-KIT 用の Linux Kernel をブートする際に必要な Device Tree Blob ファイルです。
uEnv.txt で説明したように、mmc 0:1(SD-Card のデバイス0 パーティション 1) に書き込まれます。
作りかたは、『Linux Kernel mpfs-fpga-first 編』 を参照してください。
files/vmlinuz-6.6.51-mpfs-fpga-first-1
MPFS-DISCO-KIT 用の Linux Kernel をブートする際に必要な Linux Kernel Image ファイルを圧縮したものです。
uEnv.txt で説明したように、mmc 0:1(SD-Card のデバイス0 パーティション 1)に、このファイルを解凍して書き込まれます。
作りかたは、『Linux Kernel mpfs-fpga-first 編 を参照してください。
ubuntu22.04-rootfs.tgz.files/
このディレクトリには MPFS-DISCO-KIT 用の Ubuntu22.04 Root File System を tar でまとめて gz で圧縮して 40MB 毎に細切れしたファイルが入っています。
これらのファイル群は、uEnv.txt の linux_boot_args_rootfs 変数で指定したパーティション(/dev/mmcblk0p3) に 連結して解凍して EXT4 で書き込まれます。
作りかたは、『Ubuntu 22.04 Root File System 編』 を参照してください。
debian/linux-image-6.6.51-mpfs-fpga-first_6.6.51-mpfs-fpga-1_riscv64.deb
MPFS-DISCO-KIT 用の Linux Kernel Image の Debian Package です。
作りかたは、『Linux Kernel mpfs-fpga-first 編 を参照してください。
なお、この Debian Package はすでに Ubuntu22.04 Root File System にインストール済みです。詳細は、『Ubuntu 22.04 Root File System 編』 を参照してください。
debian/linux-headers-6.6.51-mpfs-fpga-first_6.6.51-mpfs-fpga-1_riscv64.deb
MPFS-DISCO-KIT 用の Linux Kernel Header の Debian Package です。
作りかたは、『Linux Kernel mpfs-fpga-first 編 を参照してください。
なお、この Debian Package はすでに Ubuntu22.04 Root File System にインストール済みです。詳細は、『Ubuntu 22.04 Root File System 編』 を参照してください。
SD-Card のフォーマット
パーティションの構成
SD-Card を次のようにパーティションを構成します。
Part No | Name | FileSystem | Size | Type | Hex code or GUID |
---|---|---|---|---|---|
1 | boot | VFAT | 256MB | Microsoft basic data | 0700 |
2 | primary | 8MB | BIOS boot partition | 21686148-6449-6E6F-744E-656564454649 | |
3 | rootfs | EXT4 | ANY | Linux filesystem | 8300 |
パーティション1
『U-Boot 標準編』 で説明したように、u-boot は起動後に設定する環境変数を外部ファイル(uboot.env)から読むようにビルドしています。その際、uboot.env をアクセスするファイルシステムを FAT に、デバイスを mmc に、ドライブを 0 に、パーティションを 1 にしたため、このパーティションのファイルシステムは VFAT でなければなりません。
また、パーティション1 に uboot.env だけではもったいないので、uEnv.txt、boot.scr、Linux Kernel Image ファイル、Device Tree Blob ファイルもここに置きます。
このパーティションのサイズは、上記のファイルが格納できる分を確保します。なお、筆者はいろいろと実験する都合上大きめに確保しています。
パーティション2
パーティション2 はファイルシステムを作らずに uboot.img を dd コマンドなどで直接書き込みます。uboot.img が格納できる容量を確保します。
HSS(Hart Software Services) から起動するため、このパーティションの Type は必ず BIOS boot partition(GUID=21686148-6449-6E6F-744E-656564454649) でなければなりません。
パーティション3
uEnv.txt の linux_boot_args_rootfs 変数で指定したパーティションなので、このパーティションは Ubuntu22.04 Root File System を書き込みます。
このパーティションのファイルシステムは Linux Kernel をビルドした時に有効にしておかなければなりません。
『Linux Kernel mpfs-fpga-first 編』 で EXT4 を有効にしていたので、このパーティションのファイルシステムは EXT4 にします。
gdisk & mkfs
ここでは、SD-Card のフォーマットに Ubuntu22.04 の gdisk と mkfs を使った例を示します。
gdisk
次のようなシェルスクリプトを用意します。
#!/bin/sh
if [ -z ${DISKDEV} ]; then
echo "Error: DISKDEV is not defined."
exit 1
fi
if [ -f ${DISKDEV} ]; then
echo "Error: ${DISKDEV} can not write."
exit 1
fi
sed -e 's/\s*\([\+0-9a-zA-Z\-]*\).*/\1/' << EOF | gdisk ${DISKDEV}
#
o # create a new empty GUID partition table (GPT)
y # Proceed? (Y/N)
n # add a new partition
1 # Partition number=1
# First sector=default(2048)
+256M # Size=256M
0700 # Type=Microsoft basic data
n # add a new partition
2 # Partition number=2
# First sector=default
+8M # Size=8M
21686148-6449-6E6F-744E-656564454649 # Type='BIOS boot partition'
n # add a new partition
3 # Partition number=3
# First sector=default
# Last sector=default
8300 # Type=Linux filesystem
c # change a partition's name
1 # Partition number=1
boot # Enter name='boot'
c # change a partition's name
2 # Partition number=2
primary # Enter name='primary'
c # change a partition's name
3 # Partition number=3
rootfs # Enter name='rootfs'
p # print partitions
w # write table to disk and exit
y # Do you want to proceed? (Y/N)
EOF
上記のシェルスクリプトを root 権限で実行します。その際、環境変数 DISKDEV を必ず設定してください。まちがったデバイスを指定したときの責任は持ちません。
shell# export DISKDEV=/dev/sdc
shell# sh scripts/format-disk-mpfs-disco-kit.sh
GPT fdisk (gdisk) version 1.0.8
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Command (? for help):
Command (? for help): This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N):
Command (? for help): Partition number (1-128, default 1): First sector (34-61069278, default = 2048) or {+-}size{KMGTP}: Last sector (2048-61069278, default = 61069278) or {+-}size{KMGTP}: Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): Changed type of partition to 'Microsoft basic data'
Command (? for help): Partition number (2-128, default 2): First sector (34-61069278, default = 526336) or {+-}size{KMGTP}: Last sector (526336-61069278, default = 61069278) or {+-}size{KMGTP}: Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): Changed type of partition to 'BIOS boot partition'
Command (? for help): Partition number (3-128, default 3): First sector (34-61069278, default = 542720) or {+-}size{KMGTP}: Last sector (542720-61069278, default = 61069278) or {+-}size{KMGTP}: Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): Changed type of partition to 'Linux filesystem'
Command (? for help): Partition number (1-3): Enter name:
Command (? for help): Partition number (1-3): Enter name:
Command (? for help): Partition number (1-3): Enter name:
Command (? for help): Disk /dev/sdc: 61069312 sectors, 29.1 GiB
Model: SD/MMC
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): F62CCEAC-1417-4974-9403-305DB94D0239
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 61069278
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)
Number Start (sector) End (sector) Size Code Name
1 2048 526335 256.0 MiB 0700 boot
2 526336 542719 8.0 MiB EF02 primary
3 542720 61069278 28.9 GiB 8300 rootfs
Command (? for help):
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!
Do you want to proceed? (Y/N): OK; writing new GUID partition table (GPT) to /dev/sdc.
The operation has completed successfully.
mkfs
パーティション1 は VFAT で、パーテイョン3 は EXT4 でファイルシステムを作ります。
shell# export DISKDEV=/dev/sdc
shell# mkfs.vfat ${DISKDEV}1
shell# mkfs.ext4 ${DISKDEV}3
SD-Card への書き込み
SD-Card のマウント
ここの例では、パーティション1 を /mnt/usb1 に、パーティション3 を /mnt/usb2 にマウントしています。
shell# export DISKDEV=/dev/sdc
shell# mount ${DISKDEV}1 /mnt/usb1
shell# mount ${DISKDEV}3 /mnt/usb2
パーティション2 の書き込み
パーティション2 には target/mpfs-disco-kit/u-boot/uboot.img を dd コマンドで直接書き込みます。
shell# dd if=target/mpfs-disco-kit/u-boot/uboot.img of=${DISKDEV}2 bs=64k
11+1 records in
11+1 records out
741216 bytes (741 kB, 724 KiB) copied, 0.0678967 s, 10.9 MB/s
パーティション1 の書き込み
パーティション1 には target/mpfs-disco-kit/boot の下にある uboot.env、boot.scr、uEnv.txt、devicetree-6.6.51-mpfs-fpga-first-mpfs-disco-kit.dtb を書き込みます。
また、files/vmlinuz-6.6.51-mpfs-fpga-first-1 を解凍して名前を vmlinux-6.6.51-mpfs-fpga-first に変更して書き込みます。
shell# cp target/mpfs-disco-kit/boot/* /mnt/usb1
shell# gzip -d -c files/vmlinuz-6.6.51-mpfs-fpga-first-1 > /mnt/usb1/vmlinux-6.6.51-mpfs-fpga-first
パーティション3 の書き込み
パーティション3 には ubuntu22.04-rootfs.tgz.files/ の中身を連結して解凍して書き込みます。
shell# cat ubuntu22.04-rootfs.tgz.files/* | tar xfz - -C /mnt/usb2
ユーザーモードで sudo を使う場合は以下のようにしてください。
shell$ sudo sh -c 'cat ubuntu22.04-rootfs.tgz.files/* | tar xfz - -C /mnt/usb2'
パーティション3 の /etc/fstab にパーティション1 のマウントポイントを追加
shell# cat <<EOT >> /mnt/usb2/etc/fstab
/dev/mmcblk0p1 /mnt/boot auto defaults 0 0
EOT
shell# mkdir /mnt/usb2/mnt/boot
SD-Card のマウント解除
shell# umount /mnt/usb1
shell# umount /mnt/usb2