birdBuffalo LS-VLにDebian 8.0 jessieをクリーンインストールする

事の発端

ウチではもともと、Buffalo (メルコ) の NAS である LinkStation シリーズの、LS-V1.0TL こと通称 LS-VL の内蔵 HDD を SSD に換装、かつ Debianize (Debian 化) しておうちサーバとして利用していました。

カーネルはファンや LED などの各種デバイスの扱いなどが元から入っているメルコ製のものをそのまま使い、Userland のみ、Debian wheezy に入れ替えて使っていたのですが (その時の顛末はこちらから引き続く何日かの記事を参照のこと)、先日 Debian の新しいバージョン、8.0 jessie がリリースされたので、ちょっと早速バージョンアップをしたい事情もあり1、アップデートしてみることにしました。前回の squeeze→wheezy の時はほとんど苦労らしい苦労をしなかったので、今回も楽勝だろうと考えていた…というのも今思うと一つの理由でした。

が、Debian 公式のリリースノートを熟読し、必要なカーネルモジュール等の確認もシッカリ行って、バックアップも毎日取ってるから大丈夫、と満を持してアップグレードしたところ、アップグレード自体はうまく行ったように見え、apache2.4、postfix といったサーバ群もちゃんと動き出して、よしよし、とマシンをいったんリブートしたところ、二度と起動しなくなってしまいました。

メルコの NAS を改造して使っているおうちサーバの場合、一度起動しなくなってネットワーク経由でアクセス出来なくなってしまうと、もうほとんど打つ手がありません。出来ることと言えば、いったん電源を落として筐体を開け、中の SSD を適当な USB HDD のケースに格納して別の Linux マシンにつなぎ2、直接 SSD の内容を修正するくらいです。

そんなわけで今回もそのようにして中身を確認してみたんですが、今回の場合、そもそも何が悪くて起動しないのかが全く分からない、という問題がありました。おそらくカーネルの機能が足りてなかったりするのだろうと思うんですが3、クロスコンパイルしたメルコカーネルをまともに動かせる自信はありません。

次に考えたのは jessie へのアップグレードを諦めて wheezy に戻ること、だったんですが、バックアップの内容を詳細に確認してみたところ、残念ながら OS 部分についてはバックアップが取られておらず(ユーザデータのみバックアップを取るようにしていた)、その作戦も難しいことが分かりました。

この時点で結構「万策尽きた!」と半ば諦めかけていたんですが、いろいろググッている最中にこちらのページを見つけ、一筋の光明が見えてきました。Debian では今回の jessie から、実は buffalo のまた別の NAS、LS-XHL/LS-CHL に対応しており、それらのための debian-installer がある、というのです。そこで、ダメで元々のつもりで、LS-XHL 用の debian-installer を使って LS-VL に Debian jessie をインストールしてみることにしました。

あ、いろいろやりだす前に忘れないように、と、この時点で SSD 上の全ファイルのバックアップを改めて取りました。たかだか 80GB の SSD なのでバックアップもすぐ取れて便利です。(リストページでは [Comment] から続きが読めます。)

LS-XHL 用 debian-installer を入手、SSD に配置する

上記ページでも紹介されていますが、buffalo LS-XHL 用の debian-installer はこちらから入手出来ます。まずはこちらにある2つのファイルを適当なマシンでダウンロードしておきます。僕はこの後 SSD を USB HDD ケースに入れて繋いで、ファイルを書くのに使った Ubuntu マシンでダウンロードしたので、wget コマンドを使いました。

$ wget http://ftp.jp.debian.org/debian/dists/jessie/main/installer-armel/current/images/kirkwood/network-console/buffalo/lsxhl/uImage
$ wget http://ftp.jp.debian.org/debian/dists/jessie/main/installer-armel/current/images/kirkwood/network-console/buffalo/lsxhl/uInitrd

次に、我が家の場合 SSD のパーティション構成は NAS として出荷時から設定されていた状態のままとしていましたので4、/boot パーティションとなる /dev/sda1 をマウントして、そこにある元のファイルはバックアップを取った上で、以下の名前で置きました。ファイル名を変更しないといけない点に注意です。

(/dev/sda1 を mount したディレクトリで)
# mv initrd.buffalo initrd.buffalo.orig
# mv [ダウンロードしたディレクトリ]/uInitrc ./initrd.buffalo
# mv uImage.buffalo uImage.buffalo.orig
# mv [ダウンロードしたディレクトリ]/uImage ./uImage.buffalo 

このようにしてカーネル、initrd ファイルを置き換えたあと、SSD を NAS に戻して起動すると、LED の光り方が変わって新しいカーネルで起動したらしいことが分かります。LS-XHL 用 debian-installer は dhcp サーバから IP アドレス等を取得しますから、家庭内 LAN 内の dhcp サーバ5のログなどで割り当てられた IP アドレスを調べ、そこへ向けて下記の通り SSH してみます。

$ ssh [email protected][上記で調べた IP アドレス]
(パスワードは「install」)

これで debian のインストール画面が表示されればとりあえず成功です。

インストール時の注意…というか気をつけたこと

先に紹介したページの人やググッて見つかるいろいろな先達の方のページを見ていると、パーティションテーブルを不用意に書き換えてしまうと起動しなくなってしまったり、というリスクがあるようでしたので、今回パーティション設定自体は一切変更しないようにしました。もともとはファイルシステム自体もそのまま使えたら良いなぁと思っていたんですが、LS-XHL 用 debian-installer ではファイルシステムとして XFS が選択出来ないようになっており、僕はもともと / と /home では XFS を利用していたため、残念ながら不可能でした。そんなわけで /boot のみ ext3 で、/ と /home は ext4 でインストールし直して、綺麗さっぱりクリーンインストールされることになりました。

あとは特に注意することもなく、通常通りインストールを完了することが出来、その後無事システムは起動してきました。やった!

ただこの時点では、システムは無事 Debian jessie で起動したとは言っても、LED は点滅しっぱなし、ファンは全開で回りっぱなし、という常用するには難儀な状態でした。そんなわけで、まずはカーネルや LED、FAN 制御周りを LS-VL に対応させていかないといけません。

LS-VL 用カーネルビルド&入れ替え

Debian でカーネルをリビルドする手順自体は公式のインストールガイドの中にありますので、今回もその通りに行いました。ただ、そのまま作成すると今と同じ、/proc/device-tree/model が LS-XHL のままなカーネルとなってしまいますので、まずはソースにパッチを当てます。

Linux カーネルを LS-VL 対応とするパッチは、いつも大変お世話になっている山下さんのHack BBSに投稿されているものを集めて作りました。Debian jessie のカーネルは 3.16.7 というバージョンですが、こちらそのものズバリへの patch、というのは投稿されていないようでしたので、細々調整する必要があったわけです。

最終的な kernel source への patch は以下のようにしました。なお、この patch を当てた状態でとりあえずおうちサーバは何事も無く順調に稼働していますが、起動時に GPIO 周りでまだエラーが出ていたり、本人あまり意味もわからず見よう見まねでやっている部分もあったりしますのでご注意ください。

diff -urN linux-source-3.16.orig/arch/arm/boot/dts/Makefile linux-source-3.16/arch/arm/boot/dts/Makefile
--- linux-source-3.16.orig/arch/arm/boot/dts/Makefile   2015-05-16 22:40:37.800000000 +0900
+++ linux-source-3.16/arch/arm/boot/dts/Makefile    2015-05-17 09:34:21.204000000 +0900
@@ -121,6 +121,7 @@
    kirkwood-laplug.dtb \
    kirkwood-lschlv2.dtb \
    kirkwood-lsxhl.dtb \
+   kirkwood-lsvl.dtb \
    kirkwood-mplcec4.dtb \
    kirkwood-mv88f6281gtw-ge.dtb \
    kirkwood-netgear_readynas_duo_v2.dtb \
diff -urN linux-source-3.16.orig/arch/arm/boot/dts/kirkwood-lsvl.dts linux-source-3.16/arch/arm/boot/dts/kirkwood-lsvl.dts
--- linux-source-3.16.orig/arch/arm/boot/dts/kirkwood-lsvl.dts  1970-01-01 09:00:00.000000000 +0900
+++ linux-source-3.16/arch/arm/boot/dts/kirkwood-lsvl.dts   2015-05-17 09:35:49.740000000 +0900
@@ -0,0 +1,240 @@
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+
+/ {
+   model = "Buffalo Linkstation LS-VL";
+   compatible = "buffalo,lsvl", "marvell,kirkwood-88f6282", "marvell,kirkwood";
+
+   memory {
+   device_type = "memory";
+   reg = <0x00000000 0x10000000>;
+   };
+
+   [email protected] {
+   [email protected] {
+   status = "okay";
+   };
+   };
+
+   chosen {
+   bootargs = "console=ttyS0,115200n8 earlyprintk";
+   stdout-path = &uart0;
+   };
+
+   [email protected] {
+   pinctrl: [email protected] {
+   pmx_power_hdd: pmx-power-hdd {
+   marvell,pins = "mpp8";
+   marvell,function = "gpio";
+   };
+   pmx_usb_vbus: pmx-usb-vbus {
+   marvell,pins = "mpp12";
+   marvell,function = "gpo";
+   };
+   pmx_fan_high: pmx-fan-high {
+   marvell,pins = "mpp16";
+   marvell,function = "gpio";
+   };
+   pmx_fan_low: pmx-fan-low {
+   marvell,pins = "mpp17";
+   marvell,function = "gpio";
+   };
+   pmx_led_function_blue: pmx-led-function-blue {
+   marvell,pins = "mpp39";
+   marvell,function = "gpio";
+   };
+   pmx_led_alarm: pmx-led-alarm {
+   marvell,pins = "mpp36";
+   marvell,function = "gpio";
+   };
+   pmx_led_function_red: pmx-led-function_red {
+   marvell,pins = "mpp37";
+   marvell,function = "gpio";
+   };
+   pmx_led_info: pmx-led-info {
+   marvell,pins = "mpp38";
+   marvell,function = "gpio";
+   };
+   pmx_led_power: pmx-led-power {
+   marvell,pins = "mpp40";
+   marvell,function = "gpio";
+   };
+   pmx_fan_lock: pmx-fan-lock {
+   marvell,pins = "mpp43";
+   marvell,function = "gpio";
+   };
+   pmx_button_function: pmx-button-function {
+   marvell,pins = "mpp45";
+   marvell,function = "gpio";
+   };
+   pmx_power_switch: pmx-power-switch {
+   marvell,pins = "mpp46";
+   marvell,function = "gpio";
+   };
+   pmx_power_auto_switch: pmx-power-auto-switch {
+   marvell,pins = "mpp47";
+   marvell,function = "gpio";
+   };
+
+   };
+   [email protected] {
+   status = "okay";
+   nr-ports = <1>;
+   };
+
+   [email protected] {
+   status = "okay";
+
+   [email protected] {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "m25p40";
+   reg = <0>;
+   spi-max-frequency = <25000000>;
+   mode = <0>;
+
+   [email protected] {
+   reg = <0x0 0x60000>;
+   label = "uboot";
+   read-only;
+   };
+
+   [email protected] {
+   reg = <0x60000 0x10000>;
+   label = "dtb";
+   read-only;
+   };
+
+   [email protected] {
+   reg = <0x70000 0x10000>;
+   label = "uboot_env";
+   };
+   };
+   };
+   };
+
+   gpio_leds {
+   compatible = "gpio-leds";
+   pinctrl-0 = <&pmx_led_function_red &pmx_led_alarm
+   &pmx_led_info &pmx_led_power
+   &pmx_led_function_blue>;
+   pinctrl-names = "default";
+
+   [email protected] {
+   label = "lsvl:red:alarm";
+   gpios = <&gpio0 36 GPIO_ACTIVE_LOW>;
+   };
+
+   [email protected] {
+   label = "lsvl:red:func";
+   gpios = <&gpio0 37 GPIO_ACTIVE_LOW>;
+   };
+
+   [email protected] {
+   label = "lsvl:amber:info";
+   gpios = <&gpio0 38 GPIO_ACTIVE_LOW>;
+   };
+
+   [email protected] {
+   label = "lsvl:blue:func";
+   gpios = <&gpio0 39 GPIO_ACTIVE_LOW>;
+   };
+
+   [email protected] {
+   label = "lsvl:blue:power";
+   gpios = <&gpio0 40 GPIO_ACTIVE_LOW>;
+   default-state = "keep";
+   };
+   };
+
+   gpio_keys {
+   compatible = "gpio-keys";
+   pinctrl-0 = <&pmx_button_function &pmx_power_switch
+   &pmx_power_auto_switch>;
+   pinctrl-names = "default";
+
+   [email protected] {
+   label = "Function Button";
+   linux,code = <KEY_OPTION>;
+   gpios = <&gpio0 45 GPIO_ACTIVE_LOW>;
+   };
+   [email protected] {
+   label = "Power-on Switch";
+   linux,code = <KEY_RESERVED>;
+   linux,input-type = <5>;
+   gpios = <&gpio0 46 GPIO_ACTIVE_LOW>;
+   };
+   [email protected] {
+   label = "Power-auto Switch";
+   linux,code = <KEY_ESC>;
+   linux,input-type = <5>;
+   gpios = <&gpio0 47 GPIO_ACTIVE_LOW>;
+   };
+   };
+
+   gpio_fan {
+   compatible = "gpio-fan";
+   pinctrl-0 = <&pmx_fan_low &pmx_fan_high &pmx_fan_lock>;
+   pinctrl-names = "default";
+   gpios = <&gpio0 17 GPIO_ACTIVE_LOW
+   &gpio0 16 GPIO_ACTIVE_LOW>;
+   gpio-fan,speed-map = <0 3
+   1500 2
+   3250 1
+   5000 0>;
+   alarm-gpios = <&gpio0 43 GPIO_ACTIVE_HIGH>;
+   };
+
+   restart_poweroff {
+   compatible = "restart-poweroff";
+   };
+
+   regulators {
+   compatible = "simple-bus";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   pinctrl-0 = <&pmx_power_hdd &pmx_usb_vbus>;
+   pinctrl-names = "default";
+
+   usb_power: [email protected] {
+   compatible = "regulator-fixed";
+   reg = <1>;
+   regulator-name = "USB Power";
+   regulator-min-microvolt = <5000000>;
+   regulator-max-microvolt = <5000000>;
+   enable-active-high;
+   regulator-always-on;
+   regulator-boot-on;
+   gpio = <&gpio0 12 0>;
+   };
+   hdd_power: [email protected] {
+   compatible = "regulator-fixed";
+   reg = <2>;
+   regulator-name = "HDD Power";
+   regulator-min-microvolt = <5000000>;
+   regulator-max-microvolt = <5000000>;
+   enable-active-high;
+   regulator-always-on;
+   regulator-boot-on;
+   gpio = <&gpio0 8 0>;
+   };
+   };
+};
+
+&mdio {
+   status = "okay";
+
+   ethphy0: [email protected] {
+   reg = <0>;
+   };
+};
+
+&eth0 {
+   status = "okay";
+   [email protected] {
+   phy-handle = <&ethphy0>;
+   };
+};
+
diff -urN linux-source-3.16.orig/arch/arm/mach-kirkwood/Kconfig linux-source-3.16/arch/arm/mach-kirkwood/Kconfig
--- linux-source-3.16.orig/arch/arm/mach-kirkwood/Kconfig   2015-05-16 22:40:36.456000000 +0900
+++ linux-source-3.16/arch/arm/mach-kirkwood/Kconfig    2015-05-17 18:27:00.197045027 +0900
@@ -65,6 +65,13 @@
      Say 'Y' here if you want your kernel to support the
      Marvell RD-88F6281 Reference Board.

+config MACH_LSVL
+   bool "Buffalo LS-VL Series"
+   select KIRKWOOD_LEGACY
+   help
+   Say 'Y' here if you want your kernel to support the
+   Buffalo LS-VL Series.
+
 config MACH_T5325
    bool "HP t5325 Thin Client"
    select KIRKWOOD_LEGACY
diff -urN linux-source-3.16.orig/arch/arm/mach-kirkwood/Makefile linux-source-3.16/arch/arm/mach-kirkwood/Makefile
--- linux-source-3.16.orig/arch/arm/mach-kirkwood/Makefile  2015-05-16 22:40:36.464000000 +0900
+++ linux-source-3.16/arch/arm/mach-kirkwood/Makefile   2015-05-17 18:27:34.375019098 +0900
@@ -7,6 +7,7 @@
 obj-$(CONFIG_MACH_OPENRD)      += openrd-setup.o
 obj-$(CONFIG_MACH_RD88F6192_NAS)   += rd88f6192-nas-setup.o
 obj-$(CONFIG_MACH_RD88F6281)       += rd88f6281-setup.o
+obj-$(CONFIG_MACH_LSVL)            += lsvl-setup.o
 obj-$(CONFIG_MACH_T5325)       += t5325-setup.o
 obj-$(CONFIG_MACH_TS219)       += ts219-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_TS41X)       += ts41x-setup.o tsx1x-common.o
diff -urN linux-source-3.16.orig/arch/arm/mach-kirkwood/lsvl-setup.c linux-source-3.16/arch/arm/mach-kirkwood/lsvl-setup.c
--- linux-source-3.16.orig/arch/arm/mach-kirkwood/lsvl-setup.c  1970-01-01 09:00:00.000000000 +0900
+++ linux-source-3.16/arch/arm/mach-kirkwood/lsvl-setup.c   2015-05-17 18:35:56.340418546 +0900
@@ -0,0 +1,263 @@
+/*
+ * arch/arm/mach-kirkwood/lsvl-setup.c
+ *
+ * Buffalo LS-VL Series Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/gpio-fan.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <linux/platform_data/mmc-mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data lsvl_ge00_data = {
+   .phy_addr   = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv_sata_platform_data lsvl_sata_data = {
+   .n_ports    = 1,
+};
+
+#define LSVL_GPIO_KEY_FUNC 45
+#define LSVL_GPIO_KEY_POWER    46
+#define LSVL_GPIO_KEY_AUTOPOWER 47
+
+static struct gpio_keys_button lsvl_buttons[] = {
+   {
+   .type = EV_SW,
+   .code = KEY_RESERVED,
+   .gpio = LSVL_GPIO_KEY_POWER,
+   .desc = "Power-on Switch",
+   .active_low = 1,
+   }, {
+   .type = EV_SW,
+   .code = KEY_ESC,
+   .gpio = LSVL_GPIO_KEY_AUTOPOWER,
+   .desc = "Power-auto Switch",
+   .active_low = 1,
+   }, {
+   .type = EV_KEY,
+   .code = KEY_OPTION,
+   .gpio = LSVL_GPIO_KEY_FUNC,
+   .desc = "Function Button",
+   .active_low = 1,
+   },
+};
+
+static struct gpio_keys_platform_data lsvl_button_data = {
+   .buttons = lsvl_buttons,
+   .nbuttons = ARRAY_SIZE(lsvl_buttons),
+};
+
+static struct platform_device lsvl_button_device = {
+   .name = "gpio-keys",
+   .id = -1,
+   .num_resources = 0,
+   .dev = {
+   .platform_data = &lsvl_button_data,
+   },
+};
+
+#define LSVL_GPIO_LED_ALARM    36
+#define LSVL_GPIO_LED_FUNC_RED 37
+#define LSVL_GPIO_LED_INFO 38
+#define LSVL_GPIO_LED_FUNC_BLUE    39
+#define LSVL_GPIO_LED_PWR  40
+
+static struct gpio_led lsvl_led_pins[] = {
+   {
+   .name   = "lsvl:red:alarm",
+   .gpio   = LSVL_GPIO_LED_ALARM,
+   },
+   {
+   .name   = "lsvl:red:func",
+   .gpio   = LSVL_GPIO_LED_FUNC_RED,
+   },
+   {
+   .name   = "lsvl:amber:info",
+   .gpio   = LSVL_GPIO_LED_INFO,
+   },
+   {
+   .name   = "lsvl:blue:func",
+   .gpio   = LSVL_GPIO_LED_FUNC_BLUE,
+   },
+
+   {
+   .name   = "lsvl:blue:power",
+   .default_trigger    = "default-on",
+   .gpio   = LSVL_GPIO_LED_PWR,
+   .active_low = 1,
+   },
+};
+
+static struct gpio_led_platform_data lsvl_led_data = {
+   .leds   = lsvl_led_pins,
+   .num_leds   = ARRAY_SIZE(lsvl_led_pins),
+};
+
+static struct platform_device lsvl_leds = {
+   .name   = "leds-gpio",
+   .id = -1,
+   .dev    = {
+   .platform_data  = &lsvl_led_data,
+   }
+};
+
+#define LSVL_GPIO_FAN_HIGH 16
+#define LSVL_GPIO_FAN_LOW  17
+#define LSVL_GPIO_FAN_LOCK 43
+
+static struct gpio_fan_alarm lsvl_alarm = {
+   .gpio = LSVL_GPIO_FAN_LOCK,
+};
+
+static struct gpio_fan_speed lsvl_speeds[] = {
+   {
+   .rpm = 0,
+   .ctrl_val = 3,
+   }, {
+   .rpm = 1500,
+   .ctrl_val = 1,
+   }, {
+   .rpm = 3250,
+   .ctrl_val = 2,
+   }, {
+   .rpm = 5000,
+   .ctrl_val = 0,
+   }
+};
+
+static int lsvl_gpio_list[] = {
+   LSVL_GPIO_FAN_HIGH, LSVL_GPIO_FAN_LOW,
+};
+
+static struct gpio_fan_platform_data lsvl_fan_data = {
+   .num_ctrl = ARRAY_SIZE(lsvl_gpio_list),
+   .ctrl = lsvl_gpio_list,
+   .alarm = &lsvl_alarm,
+   .num_speed = ARRAY_SIZE(lsvl_speeds),
+   .speed = lsvl_speeds,
+};
+
+static struct platform_device lsvl_fan_device = {
+   .name = "gpio-fan",
+   .id = -1,
+   .num_resources = 0,
+   .dev = {
+   .platform_data = &lsvl_fan_data,
+   },
+};
+
+static unsigned int lsvl_mpp_config[] __initdata = {
+   MPP0_NF_IO2,
+   MPP1_NF_IO3,
+   MPP2_NF_IO4,
+   MPP3_NF_IO5,
+   MPP4_NF_IO6,
+   MPP5_NF_IO7,
+   MPP6_SYSRST_OUTn,
+   MPP7_SPI_SCn,
+   MPP8_GPIO, /* HDD Power */
+   MPP9_GPIO,
+   MPP10_UART0_TXD,
+   MPP11_UART0_RXD,
+   MPP12_GPO, /* USB VBUS EN */
+   MPP13_GPIO,
+   MPP14_GPIO,
+   MPP15_GPIO,
+   MPP16_GPIO, /* FAN HIGH: on:0, off:1 */
+   MPP17_GPIO, /* FAN LOW: on:0, off:1 */
+   MPP18_NF_IO0,
+   MPP19_NF_IO1,
+   MPP20_GPIO,
+   MPP21_GPIO,
+   MPP22_GPIO,
+   MPP23_GPIO,
+   MPP24_GPIO,
+   MPP25_GPIO,
+   MPP26_GPIO,
+   MPP27_GPIO,
+   MPP28_GPIO,
+   MPP29_GPIO,
+   MPP30_GPIO,
+   MPP31_GPIO,
+   MPP32_GPIO,
+   MPP33_GPO,
+   MPP34_GPIO,
+   MPP35_GPIO,
+   MPP36_GPIO, /* ALARM LED */ 
+   MPP37_GPIO, /* FUNC RED LED */
+   MPP38_GPIO, /* INFO LED */
+   MPP39_GPIO, /* FUNC LED */
+   MPP40_GPIO, /* POWER LED */
+   MPP41_GPIO,
+   MPP42_GPIO,
+   MPP43_GPIO, /* FAN LOCK */
+   MPP44_GPIO,
+   MPP45_GPIO, /* FUNC SW */
+   MPP46_GPIO, /* POWER SW */
+   MPP47_GPIO, /* POWER AUTO SW */
+   MPP48_GPIO, /* UART EN */
+   MPP49_GPIO,
+   0
+};
+
+static void lsvl_power_off(void)
+{
+   kirkwood_restart('h', NULL);
+}
+
+static void __init lsvl_init(void)
+{
+   /*
+   * Basic setup. Needs to be called early.
+   */
+   kirkwood_init();
+   kirkwood_mpp_conf(lsvl_mpp_config);
+
+   kirkwood_spi_init();
+   kirkwood_uart0_init();
+
+   if (gpio_request(12, "USB Power Enable") != 0 ||
+   gpio_direction_output(12, 1) != 0)
+   pr_err("can't set up GPIO 12 (USB Power Enable)\n");
+   kirkwood_ehci_init();
+
+   kirkwood_ge00_init(&lsvl_ge00_data);
+   kirkwood_sata_init(&lsvl_sata_data);
+
+   platform_device_register(&lsvl_leds);
+   platform_device_register(&lsvl_button_device);
+   platform_device_register(&lsvl_fan_device);
+
+   /* register power-off method */
+   pm_power_off = lsvl_power_off;
+}
+
+MACHINE_START(LSVL, "Buffalo LS-VL Series")
+   .atag_offset    = 0x100,
+   .init_machine   = lsvl_init,
+   .map_io = kirkwood_map_io,
+   .init_early = kirkwood_init_early,
+   .init_irq   = kirkwood_init_irq,
+   .init_time  = kirkwood_timer_init,
+   .restart    = kirkwood_restart,
+MACHINE_END
diff -urN linux-source-3.16.orig/arch/arm/tools/mach-types linux-source-3.16/arch/arm/tools/mach-types
--- linux-source-3.16.orig/arch/arm/tools/mach-types    2015-05-16 22:40:36.580000000 +0900
+++ linux-source-3.16/arch/arm/tools/mach-types 2015-05-17 18:25:23.138450323 +0900
@@ -118,6 +118,7 @@
 omap_osk       MACH_OMAP_OSK       OMAP_OSK        515
 tosa           MACH_TOSA       TOSA            520
 avila          MACH_AVILA      AVILA           526
+lsvl           MACH_LSVL       LSVL            527
 edb9302            MACH_EDB9302        EDB9302         538
 husky          MACH_HUSKY      HUSKY           543
 shepherd       MACH_SHEPHERD       SHEPHERD        545

上記 patch を当て、.config ファイルは Debian の linux-source-3.16 パッケージに入っている「/usr/src/linux-config-3.16/config.armel_none_kirkwood.xz」を解凍して linux-source-3.16 ディレクトリのトップに .config として置き、そのディレクトリで「make oldconfig」をまず実行、その後「make menuconfig」して CONFIG_MACH_LSVL を y にしました。以上で一通り準備が整ったので公式ページの通り make-kpkg clean、fakeroot make-kpkg –initrd –revision=custom.1.0 kernel_image6 して、コンパイルが終わるまで待ってから7、一つ上のディレクトリに出来た .deb パッケージをインストールしました。

$ sudo dpkg -i linux-image-3.16.7-ckt9lsvl1_2015051702_armel.deb

インストール時、おそらく flash-linux パッケージによるものと思われるエラーメッセージが出ます。いろいろ調べてみたんですが、どうにもよく分からなかったので今のところは無視しています。ただ、実はそのエラーが原因なのか、linux-image パッケージを入れ替えたこの時点で再起動しても、新しいカーネルではブートせず古い方が使われてしまいます。そのため以下のような手順で、ブート時に利用されるカーネル (+ initrd) を入れ替える必要があります。

先ほどの Hack BBS で通りすがりさんが説明してくださっている通り、まず uImage を作るために以下の手順をさっきと同じ linux-source-3.16 ディレクトリのトップで実行します。

$ make kirkwood-lsvl.dtb
$ cat arch/arm/boot/zImage arch/arm/boot/dts/kirkwood-lsvl.dtb > arch/arm/boot/zImage_w_dtb
$ mkimage -A arm -O linux -T kernel -C none -a 0x00008000 -e 0x00008000 -n 'Linux-3.0' -d arch/arm/boot/zImage_w_dtb arch/arm/boot/uImage.buffalo

また /boot にある元の uImage.buffalo をバックアップした後、新しい uImage.buffalo を置きます。

(/boot ディレクトリにて root ユーザで)
# mv uImage.buffalo uImage.buffalo.orig_[日付]
# mv ~/src/linux/linux-source-3.16/arch/arm/boot/uImage.buffalo ./uImage.buffalo

次に上記で作った uImage.buffalo と組み合わせる initrd を準備します。新しいカーネルパッケージをインストールした後 /boot ディレクトリに行くと initrd.img-3.16.7-[local version] というファイルが新たに置かれていると思います。こちらは initrd イメージを単に gzip しただけのものなので、これを下記の手順で u-boot 形式に変換します。こちらの手順はやはり山下さんのページを参考にしました。

(/boot ディレクトリにて root ユーザで)
# mv initrd.buffalo initrd.buffalo.orig_[日付]
# mkimage -A ARM -O Linux -T ramdisk -C gzip -a 0x00000000 -e 0x00000000 -n initrd -d initrd.img-3.16.7-ckt9lsvl1 /boot/initrd.buffalo

上記で新しいカーネルと initrd でのブートの準備が出来ました。念のためそれぞれのファイルが下記の通りのフォーマットとなっているか、オーナーやパーミッションが元のファイルと同じになっているかを確認した方が安全かも。

$ file uImage.buffalo
uImage.buffalo: u-boot legacy uImage, Linux-3.0, Linux/ARM, OS Kernel Image (Not compressed), 2082915 bytes, Sun May 17 20:05:46 2015, Load Address: 0x00008000, Entry Point: 0x00008000, Header CRC: 0x89A96D65, Data CRC: 0x81A254FA
$ file initrd.buffalo
initrd.buffalo: u-boot legacy uImage, initrd, Linux/ARM, RAMDisk Image (gzip), 9923928 bytes, Sun May 17 20:08:25 2015, Load Address: 0x00000000, Entry Point: 0x00000000, Header CRC: 0x187FB98D, Data CRC: 0x72205C1F
$ ls -l uImage.buffalo*
-rw-r--r-- 1 root root 2082979  5月 17 20:07 uImage.buffalo
-rw-r--r-- 1 root root 2084811  5月 17 10:32 uImage.buffalo.orig_20150517
$ ls -l initrd.buffalo*
-rw-r--r-- 1 root root 9923992  5月 17 20:08 initrd.buffalo
-rw-r--r-- 1 root root 9952611  5月 17 10:32 initrd.buffalo.orig_20150517

それでは十分お祈りをした後、リブートしてみましょう。おそらく正常に立ち上がってきてくれるのではないかと思います。

GPIO 周りの調整

上記手順により晴れて新カーネルで動くようになりましたが、相変わらず LED の点灯はおかしな状態、ファンも全開で回りっぱなしです。実はこれらを正しく動作させるには、システム起動後に自分で GPIO を叩いて調整してあげる必要がありました8。これまたいろいろ調べてみた結果、以下のような2つの sh script を root ユーザの crontab から起動時に実行するようにしました。

LED を点灯させる (led_poweron)

#!/bin/bash

GPIO_LED_POWER=40

gpio_config()
{
    if [ $1 == "enable" ]; then
        [ -d /sys/class/gpio/gpio$2 ] || echo $2 >/sys/class/gpio/export
        if [ $3 == "output" ]; then
            [ -f /sys/class/gpio/gpio$2/direction ] && \
                echo out >/sys/class/gpio/gpio$2/direction
        else
            [ -f /sys/class/gpio/gpio$2/direction ] && \
                echo in >/sys/class/gpio/gpio$2/direction
        fi
    else
        echo $2 >/sys/class/gpio/unexport
    fi
}

gpio_on()
{
    [ -f /sys/class/gpio/gpio$1/value ] && echo 0 >/sys/class/gpio/gpio$1/value
}

gpio_off()
{
    [ -f /sys/class/gpio/gpio$1/value ] && echo 1 >/sys/class/gpio/gpio$1/value
}

gpio_config enable ${GPIO_LED_POWER} output
gpio_off ${GPIO_LED_POWER}
gpio_on ${GPIO_LED_POWER}

負荷により FAN の回転をコントロールする (fancontrol)

#!/bin/bash

GPIO_FAN_HIGH=16
GPIO_FAN_LOW=17

gpio_config()
{
    if [ $1 == "enable" ]; then
        [ -d /sys/class/gpio/gpio$2 ] || echo $2 >/sys/class/gpio/export
        if [ $3 == "output" ]; then
            [ -f /sys/class/gpio/gpio$2/direction ] && \
                echo out >/sys/class/gpio/gpio$2/direction
        else
            [ -f /sys/class/gpio/gpio$2/direction ] && \
                echo in >/sys/class/gpio/gpio$2/direction
        fi
    else
        echo $2 >/sys/class/gpio/unexport
    fi
}

gpio_on()
{
    [ -f /sys/class/gpio/gpio$1/value ] && echo 0 >/sys/class/gpio/gpio$1/value
}

gpio_off()
{
    [ -f /sys/class/gpio/gpio$1/value ] && echo 1 >/sys/class/gpio/gpio$1/value
}

fan_low()
{
    gpio_off ${GPIO_FAN_HIGH}
    gpio_on ${GPIO_FAN_LOW}
}

fan_high()
{
    gpio_on ${GPIO_FAN_HIGH}
    gpio_off ${GPIO_FAN_LOW}
}

fan_full()
{
    gpio_on ${GPIO_FAN_HIGH}
    gpio_on ${GPIO_FAN_LOW}
}

gpio_config enable ${GPIO_FAN_HIGH} output
gpio_config enable ${GPIO_FAN_LOW} output

while true; do
    if [ `echo "scale=2; $(cat /proc/loadavg | cut -f1 -d' ') > 3.00" | bc` == 1 ]; then
        fan_full
    elif [ `echo "scale=2; $(cat /proc/loadavg | cut -f1 -d' ') > 1.00" | bc` == 1 ]; then
        fan_high
    else
        fan_low
    fi
    sleep 60
done

crontab の設定

@reboot /root/bin/led_poweron
@reboot /root/bin/fancontrol

これで一通り動くようになったのではないかと思います。あとは不要な pkg の削除とか各種 service 設定戻しなどを backup から適宜ファイルを取り出したりしつつ進め、なんとか元と同じ環境となりました。よかったよかった。

で、結局 fb_graph は…

元々自作 ruby スクリプトで Facebook wall へつぶやきを投稿するために使っていた fb_graph が (Facebook 側での古い API 停止に伴い) 使えなくなってしまい、後継の fb_graph2 へ移行しようとしたらそれが ruby2.0 以降を要求していたことが今回 jessie への移行を行おうと思った一つのきっかけだったのですが (ちなみに jessie の ruby は 2.1 です)、jessie 移行後 fb_graph2 を rubygem でインストールして移行しようとしたものの、どうにもうまく動かすことが出来ず、結局もう一つの Facebook Graph API 用 ruby ライブラリであるところの koala に移行してしまいました。ちゃんちゃん。


  1. Twitter のつぶやきを Facebook wall に自動的に投稿する自作の ruby スクリプト内で使っているライブラリ fb_graph が古くなって使えなくなってしまったので。
  2. 幸いなことに我が家にはもう一台 Linux (Ubuntu) マシンがあります。
  3. Debian jessie ではこれまでの init から systemd への移行が大きな話題となっていました。
  4. メルコカーネルを使っていたためその方が安全だと思った。
  5. 我が家の場合は wifi ルータの Aterm WR8300N が dhcp サーバも兼ねています。
  6. revision は適当に調整しました。
  7. 我が家のマシンでは10時間くらいかかりました(汗。
  8. もっとスマートな方法があるのかもしれませんが、とりあえず今はこれしかわからないのでこのような形にしています。