先日,セキュリティミニキャンプ沖縄2015にチューターとして参加させていただきました. そこでお手伝いしながら木藤さんの講義「組込みシステム解体新書(入門編)」を聞いていたところ,組み込み機器をいじりたい欲がむくむくと湧き出してきたので,以前とあるお方から頂いた黒柴(KURO-SHEEVA)に最新のLinuxカーネルとDebian jessieを入れてみることにしました.
本日はKernelをビルドして起動するまでできたので,それまでの方法を記します.
なお,以降の作業はArch Linux(x86_64)環境上で行いました. arm環境用のクロスコンパイル環境は用意されているものとします. ない方はcrosstool-ngなどで作ってください.
黒柴(KURO-SHEEVA)
黒柴は,2010年頃に玄人志向から発売されたSheeva-Plugをベースとしたプラグコンピューターです. 電源プラグにつなぐだけで使える小型省電力サーバーとして,当時プラグコンピューターが(私の観測では)けっこう流行りました. 今でいうところのRaspberry Piのようなものです.
SoCはMarvell社のKirkwood SoCプロセッサ「88F6281」 ARMv5te 1.2GHzとなっています. 周辺機器はGigabitEther,USB2.0ポート,SDカードスロット,eSATAポート,コンソール&JTAG用USB type miniB がひとつずつついています.
Linux Kernelをビルドする
基本は,黒柴の元となったSheeva-Plug用のLinux Kernelビルド方法を参考に進めます. ただし,この記事はLinux 2.6頃の話をしているので,最近のLinuxに合わせてちょこっといじる必要があります.
Building and installing a new kernel for a SheevaPlug
最初にlinux KernelのSourceをとってきます. バージョンは4.3を使いました.
$ cd ~/ $ git clone --depth 1 https://github.com/torvalds/linux $ cd linux $ git checkout -b v4.3 refs/tags/v4.3
次にKirkwood用のconfigをロードします. 昔はkirkwood_defconfigという名前であったようですが,現在はmvebuに統合されたようです.
$ make ARCH=arm mvebu_v5_defconfig
最近のsystemdな環境ではCONFIG_CGROUPSを有効にする必要があるので,menuconfigで設定をいじります.
$ make ARCH=arm menuconfig
General setup ---> Control Group support を選択して設定してください.
後はカーネルをビルドします. CROSS_COMPILEのところは各自環境に合わせて修正してください.
$ make ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabi- zImage dtbs
zImageをuImageにする
正確なバージョンは忘れましたが,現在のLinuxカーネルでは個々の組み込みボードのハードウエア構成等をDevice Treeで設定するようになりました. そのため,Kernelの起動時には,Device Treeを記述したソースをビルドしてできるDevice Tree Blob(以下 dtb)をKernelに渡す必要があります.
U-Bootが対応している場合はKernelとdtbを適当にメモリにおいて起動できるようですが,黒柴に入ってるU-Bootは古いのでできるかわかりません. 以下の資料を参照すると,zImageのケツにdtbをくっつけてuImageに変換し,U-Bootに食わせることもできるようなので,それを試します.
http://tokyodebian.alioth.debian.org/pdf/debianmeetingresume201307-presentation-iwamatsu.pdf
私の黒柴のU-Bootはbootmすると0x02000000からuImageを読みだすようなので,ロードアドレスに0x02000000,エントリポイントにはuImageのヘッダ分ずらした0x02000040を設定します.
$ cd ~/ $ cp linux/arch/arm/boot/zImage linux/arch/arm/boot/dts/kirkwood-sheevaplug-esata.dtb ./ $ cat zImage kirkwood-sheevaplug-esata.dtb > zImage+btb $ mkimage -A arm -O linux -T kernel -C none \ -a 0x02000000 -e 0x02000040 -n 'Linux-sheeva-esata' \ -d zImage+btb uImage+dtb
できたカーネルを起動してみる
できたカーネルを黒柴にくわせてみます. 先ほど作ったuImage+dtbファイルをFATでフォーマットしたSDカードにコピーし,黒柴にさして起動してください. 加えて,ホストマシンと黒柴をUSBでつなぎ,シリアルコンソールを繋いでください.ボーレート等は115200です.
シリアルコンソールを繋いだ状態でEnterを押すと以下のようなプロンプトが出ます.
Marvell>>
これを確認したら,以下のコマンドを実行してカーネルのロードと起動を行います.
mmcinit fatload mmc 0:1 0x02000000 uimage+dtb bootm
うまく起動すれば,以下のようにログがどばっと出て,最後にrootfsが見つからないといってパニックします.
Marvell>> mmcinit SDHC found. Card desciption is: Manufacturer: 0x74, OEM "JE" Product name: "USD ", revision 1.0 Serial number: 1280314594 Manufacturing date: 1/2012 CRC: 0x00, b0 = 0 Marvell>> fatload mmc 0:1 0x02000000 uimage+dtb reading uimage+dtb 4284489 bytes read Marvell>> bootm ## Booting image at 02000000 ... Image Name: Linux-sheeva-esata Created: 2015-12-24 12:22:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 4284425 Bytes = 4.1 MB Load Address: 02000000 Entry Point: 02000040 Verifying Checksum ... OK XIP Kernel Image ... OK Starting kernel ... Booting Linux on physical CPU 0x0 Linux version 4.3.0 (tnishinaga@arch-tx201) (gcc version 5.2.0 (crosstool-NG crosstool-ng-1.22.0) ) #5 PREEMPT Thu Dec 24 18:13:55 JST 2015 CPU: Feroceon 88FR131 [56251311] revision 1 (ARMv5TE), cr=0005397f CPU: VIVT data cache, VIVT instruction cache Machine model: Globalscale Technologies eSATA SheevaPlug Memory policy: Data cache writeback Built 1 zonelists in Zone order, mobility grouping on. Total pages: 130048 Kernel command line: console=ttyS0,115200 root=/dev/mmcblk0p2 rw PID hash table entries: 2048 (order: 1, 8192 bytes) Dentry cache hash table entries: 65536 (order: 6, 262144 bytes) Inode-cache hash table entries: 32768 (order: 5, 131072 bytes) Memory: 510696K/524288K available (6241K kernel code, 212K rwdata, 1680K rodata, 172K init, 661K bss, 13592K reserved, 0K cma-reserved, 0K highmem) Virtual kernel memory layout: vector : 0xffff0000 - 0xffff1000 ( 4 kB) fixmap : 0xffc00000 - 0xfff00000 (3072 kB) vmalloc : 0xe0800000 - 0xff000000 ( 488 MB) lowmem : 0xc0000000 - 0xe0000000 ( 512 MB) pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB) modules : 0xbf000000 - 0xbfe00000 ( 14 MB) .text : 0xc0008000 - 0xc07c4704 (7922 kB) .init : 0xc07c5000 - 0xc07f0000 ( 172 kB) .data : 0xc07f0000 - 0xc0825220 ( 213 kB) .bss : 0xc0825220 - 0xc08ca9a0 ( 662 kB) SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 Preemptible hierarchical RCU implementation. Build-time adjustment of leaf fanout to 32. NR_IRQS:16 nr_irqs:16 16 clocksource: orion_clocksource: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556302233 ns sched_clock: 32 bits at 200MHz, resolution 5ns, wraps every 10737418237ns Console: colour dummy device 80x30 Calibrating delay loop... 1191.11 BogoMIPS (lpj=5955584) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) CPU: Testing write buffer coherency: ok Setting up static identity map for 0x81e0 - 0x8238 mvebu-soc-id: MVEBU SoC ID=0x6281, Rev=0x2 devtmpfs: initialized clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns xor: measuring software checksum speed arm4regs : 1084.400 MB/sec 8regs : 804.400 MB/sec 32regs : 970.800 MB/sec xor: using function: arm4regs (1084.400 MB/sec) pinctrl core: initialized pinctrl subsystem NET: Registered protocol family 16 DMA: preallocated 256 KiB pool for atomic coherent allocations cpuidle: using governor ladder cpuidle: using governor menu Feroceon L2: Enabling L2 Feroceon L2: Cache support initialised. [Firmware Info]: /ocp@f1000000/ethernet-controller@72000/ethernet0-port@0: local-mac-address is not set raid6: int32x1 gen() 111 MB/s raid6: int32x1 xor() 76 MB/s raid6: int32x2 gen() 167 MB/s raid6: int32x2 xor() 103 MB/s raid6: int32x4 gen() 185 MB/s raid6: int32x4 xor() 119 MB/s raid6: int32x8 gen() 187 MB/s raid6: int32x8 xor() 116 MB/s raid6: using algorithm int32x8 gen() 187 MB/s raid6: .... xor() 116 MB/s, rmw enabled raid6: using intx1 recovery algorithm vgaarb: loaded SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb Advanced Linux Sound Architecture Driver Initialized. clocksource: Switched to clocksource orion_clocksource NET: Registered protocol family 2 TCP established hash table entries: 4096 (order: 2, 16384 bytes) TCP bind hash table entries: 4096 (order: 2, 16384 bytes) TCP: Hash tables configured (established 4096 bind 4096) UDP hash table entries: 256 (order: 0, 4096 bytes) UDP-Lite hash table entries: 256 (order: 0, 4096 bytes) NET: Registered protocol family 1 RPC: Registered named UNIX socket transport module. RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. futex hash table entries: 256 (order: -1, 3072 bytes) jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc. io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) kirkwood-pinctrl f1010000.pin-controller: registered pinctrl driver irq: Cannot allocate irq_descs @ IRQ34, assuming pre-allocated irq: Cannot allocate irq_descs @ IRQ66, assuming pre-allocated mv_xor f1060800.xor: Marvell shared XOR driver mv_xor f1060800.xor: Marvell XOR (Registers Mode): ( xor cpy intr ) mv_xor f1060900.xor: Marvell shared XOR driver mv_xor f1060900.xor: Marvell XOR (Registers Mode): ( xor cpy intr ) Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled console [ttyS0] disabled f1012000.serial: ttyS0 at MMIO 0xf1012000 (irq = 26, base_baud = 12500000) is a 16550A console [ttyS0] enabled loop: module loaded sata_mv f1080000.sata: slots 32 ports 2 scsi host0: sata_mv scsi host1: sata_mv ata1: SATA max UDMA/133 irq 32 ata2: SATA max UDMA/133 irq 32 nand: device found, Manufacturer ID: 0xec, Chip ID: 0xdc nand: Samsung NAND 512MiB 3,3V 8-bit nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 Scanning device for bad blocks Bad eraseblock 2909 at 0x000016ba0000 Bad eraseblock 3657 at 0x00001c920000 3 ofpart partitions found on MTD device orion_nand Creating 3 MTD partitions on "orion_nand": 0x000000000000-0x000000100000 : "u-boot" 0x000000100000-0x000000500000 : "uImage" 0x000000500000-0x000020000000 : "root" libphy: orion_mdio_bus: probed mv643xx_eth: MV-643xx 10/100/1000 ethernet driver version 1.4 mv643xx_eth_port mv643xx_eth_port.0 eth0: port 0 with MAC address f0:ad:4e:00:5c:d9 libertas_sdio: Libertas SDIO driver libertas_sdio: Copyright Pierre Ossman ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver ehci-pci: EHCI PCI platform driver ehci-orion: EHCI orion driver orion-ehci f1050000.ehci: EHCI Host Controller orion-ehci f1050000.ehci: new USB bus registered, assigned bus number 1 ata1: SATA link down (SStatus 0 SControl F300) orion-ehci f1050000.ehci: irq 29, io mem 0xf1050000 orion-ehci f1050000.ehci: USB 2.0 started, EHCI 1.00 hub 1-0:1.0: USB hub found hub 1-0:1.0: 1 port detected usbcore: registered new interface driver usb-storage usbcore: registered new interface driver ums-datafab usbcore: registered new interface driver ums-freecom usbcore: registered new interface driver ums-jumpshot usbcore: registered new interface driver ums-sddr09 usbcore: registered new interface driver ums-sddr55 mousedev: PS/2 mouse device common for all mice rtc-mv f1010300.rtc: rtc core: registered f1010300.rtc as rtc0 i2c /dev entries driver orion_wdt: Initial timeout 21 sec mvsdio f1090000.mvsdio: Got CD GPIO mvsdio f1090000.mvsdio: Got WP GPIO MV-CESA:Could not register sha1 driver MV-CESA:Could not register hmac-sha1 driver usbcore: registered new interface driver usbhid usbhid: USB HID core driver oprofile: no performance counters oprofile: using timer interrupt. NET: Registered protocol family 17 lib80211: common routines for IEEE802.11 drivers Btrfs loaded rtc-mv f1010300.rtc: setting system clock to 2013-01-01 11:15:49 UTC (1357038949) ALSA device list: mmc0: new high speed SDHC card at address b368 No soundcards found. mmcblk0: mmc0:b368 USD 3.75 GiB mmcblk0: p1 ata2: SATA link down (SStatus 0 SControl F300) VFS: Cannot open root device "mmcblk0p2" or unknown-block(179,2): error -6 Please append a correct "root=" boot option; here are the available partitions: 1f00 1024 mtdblock0 (driver?) 1f01 4096 mtdblock1 (driver?) 1f02 519168 mtdblock2 (driver?) b300 3941376 mmcblk0 driver: mmcblk b301 3937280 mmcblk0p1 00000000-01 Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2) CPU: 0 PID: 1 Comm: swapper Not tainted 4.3.0 #5 Hardware name: Marvell Kirkwood (Flattened Device Tree) [<c000f848>] (unwind_backtrace) from [<c000d254>] (show_stack+0x10/0x14) [<c000d254>] (show_stack) from [<c008368c>] (panic+0x98/0x1ec) [<c008368c>] (panic) from [<c07c618c>] (mount_block_root+0x170/0x220) [<c07c618c>] (mount_block_root) from [<c07c632c>] (mount_root+0xf0/0x11c) [<c07c632c>] (mount_root) from [<c07c6474>] (prepare_namespace+0x11c/0x17c) [<c07c6474>] (prepare_namespace) from [<c07c5db0>] (kernel_init_freeable+0x184/0x1cc) [<c07c5db0>] (kernel_init_freeable) from [<c05f1e28>] (kernel_init+0x8/0xec) [<c05f1e28>] (kernel_init) from [<c000a470>] (ret_from_fork+0x14/0x24) ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2)
これでとりあえず,Kernelがそこそこ動いていることが確認できました. 次はDebian環境を用意してちゃんと使えるようにしたいと思います.
おやすみなさい.