raspberry pi 3 b+ and u-boot and mainline kernel, and meta-fedora

Raspberry Pi(以下rpi)のカーネルではなくて、mainline等のカーネルを使いたい場合のメモです。

TL;DR

基本的に次のwebサイトを見れば事足ります。

elinux.org

概要

rpi向けのカーネルは以下なのですが、mainlineのカーネルを使いたい等の理由がある場合の環境構築方法のメモです。

github.com

uart、wifihdmiを使えるところまでが対象です。archはaarch64を対象とします。使っているのはRaspberry Pi 3 B+です。

f:id:masami256:20190821212408j:plain

必要なもの

これらが必要です。

最初の2つはそりゃそうだなって感じですね。次のrpiで〜というところはstart.elfやfixup.datといったブートに必要なバイナリファイル群です。最後のfirmwarewifiを使うのに必要になります。

u-boot

RPi U-Boot - eLinux.orgを見てビルドしてください。

Linux Kernel

適当なaarch64環境でコンパイルするか、クロスコンパイルします。

Fedoraならgcc-aarch64-linux-gnuあたりのパッケージをインストールします。クロスコンパイル時のmakeコマンドは基本的に次の通りです。これにoldconfigだったりがオプションで付きます。

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 

defconfig

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig

configオプションで設定するものがいくつかあります。defconfigでmakeしたあとに以下のスクリプトを実行し、最後にmake oldconfigを実行します。ここで設定しているのは有線LAN、wifiドライバ、HDMI出力、broadcomのドライバ、フレームバッファです。面倒なのでモジュールではなくてカーネルに組み込んでます。

#!/bin/bash

configs=(USB_LAN78XX
RFKILL
BRCMFMAC
RCMFMAC_PROTO_BCDC
BRCMFMAC_PROTO_MSGBUF
BRCMFMAC_SDIO
BCMFMAC_USB
BRCMFMAC_PCIE
CFG80211
CFG80211_REQUIRE_SIGNED_REGDB
CFG80211_USE_KERNEL_REGDB_KEYS
CFG80211_DEFAULT_PS
CFG80211_DEBUGFS
CFG80211_CRDA_SUPPORT
CFG80211_WEXT
ARCH_BCM2835
SERIAL_8250_BCM2835AUX
HW_RANDOM_BCM2835
I2C_BCM2835
SPI_BCM2835
SPI_BCM2835AUX
PINCTRL_BCM2835
BCM2835_THERMAL
BCM2835_WDT
SND_BCM2835_SOC_I2S
MMC_BCM2835
DMA_BCM2835
BCM2835_VCHIQ
SND_BCM2835
VIDEO_BCM2835
BCM2835_MBOX
BCM2835_POWER
PWM_BCM2835
HW_RANDOM_BCM2835
ROCKCHIP_DW_HDMI
ROCKCHIP_INNO_HDMI
ROCKCHIP_RK3066_HDMI
DRM_SUN4I_HDMI_CEC
DRM_MSM_HDMI_HDCP
DRM_VC4_HDMI_CEC
HDMI
FB_SIMPLE
LOGO
LOGO_LINUX_CLUT224
)

for config in ${configs[@]};
do
    ./scripts/config --enable $config
done

HDMIで画面出力する場合はフレームバッファが必要で、mainlineのカーネルだとsimple-framebuffer(CONFIG_FB_SIMPLE)を有効にする必要があります。

.configが作れたらカーネルとdevicetreeをビルドします。

Imageのビルド

make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-

DeviceTreeのビルド

make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs

カーネルのビルドはこれにて終了です。

Raspberry Pifirmwareダウンロード

ラズパイ用のfirmwareをgitリポジトリからcloneしましょう。

github.com

Linuxfirmwareダウンロード

wifiを動かすのに必要なfirmwareを一式gitリポジトリからcloneしましょう。

git.kernel.org

sdカードの準備

こんな感じで最初のパーティションfat32で作ります。起動はここからです。もう一つのほうはroot filesystemです。

root@qemuarm64:~# fdisk -l
Disk /dev/mmcblk0: 30 GB, 31914983424 bytes, 62333952 sectors
973968 cylinders, 4 heads, 16 sectors/track
Units: cylinders of 64 * 512 = 32768 bytes

Device       Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type
/dev/mmcblk0p1    4,4,1       261,4,2           2048     133119     131072 64.0M  c Win95 FAT32 (LBA)
Partition 1 does not end on cylinder boundary
/dev/mmcblk0p2    261,5,1     1023,254,2      133120    2097151    1964032  959M 83 Linux
Partition 2 does not end on cylinder boundary

bootパーティションの設定

firmwareのコピー

/mnt/rpiにマウントしているとして、cloneしてきたrpiのfirmwareディレクトリに移動しファイルをコピーします。

$ cd firmware
$ cp -a boot/start* /mnt/rpi/.
$ cp -a boot/fixup* /mnt/rpi/.
$ cp -a boot/overlays/ /mnt/rpi/.
$ cp -a boot/bootcode.bin /mnt/rpi/.

カーネルのコピー

arch/arm64/boot/Imageとarch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dtbを/mnt/rpiにコピーします。

u-bootのコピー

ビルドしたu-boot.binを/mnt/rpiにコピーします。

config.txtの作成

つぎに/mnt/rpi/config.txtを以下の内容で作ります。

[all]
boot_delay=1
kernel=u-boot.bin
arm_control=0x200
upstream_kernel=1
audio_pwm_mode=0
enable_uart=1
gpu_mem=16
mask_gpu_interrupt1=0x100

u-bootの設定

以下のようなファイルを(boot.cmd)を作ります。作成する場所は任意です。

fatload mmc 0:1 ${kernel_addr_r} Image
fatload mmc 0:1 ${fdt_addr} bcm2837-rpi-3-b-plus.dtb
setenv bootargs dwc_otg.lpm_enable=0 earlyprintk root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
booti ${kernel_addr_r} - ${fdt_addr}

そして以下のコマンドでboot.scrを/mnt/rpiに作成します。

$ mkimage -C none -A arm64 -T script -d ./boot.cmd /mnt/rpi/boot.scr

上記のmkimageコマンドはfedoraならuboot-toolsパッケージにあります。

uartの設定

u-bootの段階からuartでログを表示したい場合は以下のようにします。

$ sed -i -e "s/BOOT_UART=0/BOOT_UART=1/" /mnt/rpi/bootcode.bin 

と、ここまででブートローダカーネルの準備はOKです。が、これだとルートファイルシステムがないので面白くないですよね。なのでルートファイルシステムも用意しましょう。

ルートファイルシステム

ルートファイルシステムのビルド

まあなんでもいいのですが、せっかくなので自作のyoctoのレイヤーを使いましょう(´ω`)

github.com

MACHINEにはqemuarm64を指定してcore-image-minimalでビルドしてください。build/tmp-glibc/deploy/images/qemuarm64/にルートファイルシステムのtarファイルがあるのでそれをルートファイルシステムパーティションに展開します。

/mnt/rootfsがルートファイルシステムパーティションだとしてこうします。

$ sudo tar xvf build/tmp-glibc/deploy/images/qemuarm64/core-image-minimal-qemuarm64.tar.bz2 -C /mnt/rootfs/

firmwareのコピー

broadcomファームウェアをルートファイルシステムにコピーしましょう。こんな感じです。

$ sudo mkdir /mnt/rootfs/lib/firmware
$ sudo cp -a linux-firmware/brcm/ /mnt/rootfs/lib/firmware/.

起動

ここまででホストでの作業は完了したのであとはsdカードから起動させましょう。

TV側

起動時の🐧

f:id:masami256:20190821211838j:plain

ログイン

f:id:masami256:20190821211912j:plain

uartでもログインしてるのでttyS1もありますね。

uart側

f:id:masami256:20190821212710p:plain

有線LAN、wifiが認識されてます。

wlan0

root@qemuarm64:~# ip link show wlan0
2: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000

eth0

root@qemuarm64:~# ip link show wlan0
2: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000

まとめ

rpiのカーネルでなくてもhdmiを使ったり有線・wifi使えるようになりましたΣ(゚∀゚ノ)ノキャー tftpブートすればrpiでのカーネルハックが捗ると思います😃