OpenBSD armv7

以前読んだ、ゲノム編集の衝撃に触発されて、福岡伸一さんの『動的平衡』なんて 本を読んだ。各界の著名人との対談集。示唆に富んでいて面白かった。

建築界の有名人、隅研吾さんとの対談で、

生物の細胞内では、蛋白質や遺伝子の粒が常に少しずつ入れ替わっています。
それもカプセルのようなレベルではなく、あくまで目に見えないミクロなレベル
での営みだから、外からは細胞が変化しているようには見えない。
そのじつたえまなく進行しているのが生物の代謝だし、その変化こそ生命そのもの
だといえます。生物は、まさにこの方法によって、何十年もメンテナンスフリーで
生き延びられるわけです。

そうか、そういう事なんだ。おギャーと生れ落ちて、90年、人によっては 100年を超えても、心臓が動いている。考えるまでもなく、とてつもなく素晴らしい 血液循環用ポンプ。現在の工学をもってしても、こうはいくまい。この素晴らしい 働きの裏で、こういう事が行われていたのね。

この発現のきっかけは、建築物は一度作られると、それから変動はしない硬化した ものになってしまうって発言に対してなされたもの。絶えず流動してるってのと 対極になるな。これを打破しようと、建築家は色々考えたけど、なかなかうまく いかない。

だから、国立競技場を壊して、もう一度作り直そうってんで、隅さんが優勝した 訳だ。

玄侑宗久さんと言うお坊さんとの対話

福岡さんが、生命は流れだということをおっしゃっているとき、鴨長明の方丈記を
引かれておられますよね。行く川の流れは絶えずして、しかも、もとの水にあらず
あの冒頭は見事だと思うんです。

人間は、ついつい信念、確信、信条といった無常ならざるもので自分を支えようと
しますが、東日本大震災を経て、そろそろそういう生き方を改めてもいいんじゃ
ないかと思うんです。

とくに最近は、未来に対するシュミレーションが常態化しています。しか、目標や
マニフェストのようなものは、無常の目からみれば根拠のない虚像に過ぎません。
むしろ、そのときどきの状況に合わせて揺らぎ、変わっていける事が本当の強さ
だい、それにはまず無常を受け入れる事が大事だと思うんです。

何事につけ、こうに違いないと思い込む所に間違いが生じるわけですからね。
事実、私達を構成する分岐は無常に入れ替わっていますから、物質レベルでは
自分の一貫性を担保するものは何もありません。

深い話だなあ。

クッキー 喰いねぇ

女房は、ときたま、思い付いたようにクッキーを焼く。先日も、オイラーが寝た 後、思い立ってクッキーを焼いてた。今回のバージョンは、クッキーの上にくるみ を載せてあった。場合によっては、粒チョコが入っていたり、レーズンが入って いたりする。土産で貰った、台湾のドライマンゴーが有るんで、今度はそれで 試してみてね。

オイラーは毎日、各国から送られて来るクッキーを食べているぞ。そう、 ブラウザーが受け止めてくれるやつね。 FirefoxのCookieデータの場所と覗く方法 こんな所に、保存してあるらしい。

クッキーは昔、よくこね回したけど、すっかり忘れているので、 Cookieとセッション管理 を見て復習。 もっと一般的な事なら、 HTTP Header解説 がいいかな。

上の案内で、fedoraのそれを見る。見たら消すんで、あしからず。

[sakae@fedora ynxoh2p8.default]$ pwd
/home/sakae/.mozilla/firefox/ynxoh2p8.default
[sakae@fedora ynxoh2p8.default]$ sqlite3 cookies.sqlite
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite> .schema
CREATE TABLE moz_cookies (
  id INTEGER PRIMARY KEY, 
  baseDomain TEXT,
  originAttributes TEXT NOT NULL DEFAULT '',
  name TEXT,
  value TEXT,
  host TEXT,
  path TEXT,
  expiry INTEGER,
  lastAccessed INTEGER, 
  creationTime INTEGER,
  isSecure INTEGER,
  isHttpOnly INTEGER,
  appId INTEGER DEFAULT 0,
  inBrowserElement INTEGER DEFAULT 0,
  CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes));

CREATE INDEX moz_basedomain ON moz_cookies (baseDomain, originAttributes);

sqlite3が保存庫になってるので、確認。そして、実例に触れてみる。

sqlite> select * from moz_cookies;
  :
26|adnxs.com||uuid2|11980507060316|.adnxs.com|/|1480799169|1473023169019115|1472242877750213|0|1|0|0
27|criteo.com||zdi|*1pm1hfCfdRKr9M%2f76LQ%3d%3d|.criteo.com|/|1488661570|1473023169195244|1472242881943088|0|0|0|0

もう少し、ましな出力方法が有ったと思って、復讐。 SQLiteコマンド解説の .mode line を指定しておいてからselectすれば、

              id = 198
      baseDomain = im-apps.net
originAttributes =
            name = imid
           value = lrfEOh32ElTWLdDa9nwlFAtx
            host = .im-apps.net
            path = /
          expiry = 1524450979
    lastAccessed = 1461378979679891
    creationTime = 1461378586450121
        isSecure = 0
      isHttpOnly = 0
           appId = 0
inBrowserElement = 0

こんな具合に、見易くなる。他へ持って行くなら、.mode csvしてからが良いだろう。 外部に持ち出す時は、.output hoge-file とかすれば良い。

クッキーなんで、製造会社(baseDomain)、製造工場(host,path)、賞味期限(expiry)、 内容物(name,value)が必須。 lastAccessedは16桁も有る。気を利かせて、firefoxがやけに細かくepocを記録 してるね。

[ob: ~]$ date -r 1524450979
Mon Apr 23 11:36:19 JST 2018
[ob: ~]$ date -r 1461378979
Sat Apr 23 11:36:19 JST 2016

このクッキーを最後にかじったのは、今年の4月23日、賞味期限は、それから2年間 となってた。

Boot失敗、中身拝見

OpenBSD 6.0 になってarmv7のサポートが充実したらしい。ならば、qemuで 何とかならないかと妄想してみる。qemuのmanを見ると、-sdなんて言うオプションも 有るようだし。

       -sd file
           Use file as SecureDigital card image.

sdってのは、こういう意味だって初めて知ったよ。

[ob: arm]$ qemu-system-arm -M cubieboard -nographic  -singlestep  -sd miniroot-cubie-60.fs
WARNING: Image format was not specified for 'miniroot-cubie-60.fs' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
Warning: Orphaned drive without device: id=sd0,file=miniroot-cubie-60.fs,if=sd,bus=0,unit=0
qemu: fatal: Trying to execute code outside RAM or ROM at 0x00000000

R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=400001d3 -Z-- A S svc32
 :
FPSCR: 00000000
Abort trap (コアダンプ)

ひょっとして、sdドライバがBugってる? hdaに変えても、同様なエラーだよ。 苦し紛れに、どんな素材か、確認しておく。

[ob: arm]$ file miniroot-cubie-60.fs
miniroot-cubie-60.fs: x86 boot sector; 
partition 1: ID=0xc, active, starthead 255, startsector 2048, 4096 sectors; 
partition 4: ID=0xa6, starthead 255, startsector 6144, 30720 sectors

もう少し詳しい情報が得られないか、Linuxでも確認してみる。

sakae@ub:/tmp$ fdisk -l miniroot-cubie-60.fs
Disk miniroot-cubie-60.fs: 18 MiB, 18874368 bytes, 36864 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device                Boot Start   End Sectors Size Id Type
miniroot-cubie-60.fs1 *     2048  6143    4096   2M  c W95 FAT32 (LBA)
miniroot-cubie-60.fs4       6144 36863   30720  15M a6 OpenBSD

多少は詳しいか。

OpenBSDのarmv7の所を見ると、色々なボード用のコードが置かれている。その中から 上記を選んだのは、qemu -M? して、それらしいのを決定。

果たしてどんなボードか探ってみれば、 CubieBoard | A series of open source hardware オープンハードウェアらしい。 $50以下で買えるSATA付きARM A8 CPUボード: Cubieboardによると、メモリーを1Gも積んでいる ボードか。ラズパイばかり持て囃されるけど、こういうボードも有るのね。

ちょっと悔しいので、OpenBSDのパーテションを切り出して、確認してみる。 Linuxと違って、mountはブロックデバイスが必要なので、vnconfigで、仮想の デバイスを作っている。

[ob: ~]$ dd if=miniroot-cubie-60.fs of=zzz skip=6144
# vnconfig vnd0 zzz
# mount /dev/vnd0c /mnt
# ls -l /mnt
total 33088
-rwxr-xr-x  2 root  wheel  10470949 Jul 28 12:48 bsd
-rwxr-xr-x  2 root  wheel  10470949 Jul 28 12:48 bsd.rd
# umount /mnt
# vnconfig -u vnd0

ついでに、DOSのパーテションの方も覗いておくか。

[ob: arm]$ dd if=miniroot-cubie-60.fs skip=2048|dd of=w95 count=4096
[ob: arm]$ su
Password:
# vnconfig vnd0 w95
# mount -t msdos /dev/vnd0c /mnt
# tree /mnt
/mnt
|-- efi
|   `-- boot
|       `-- bootarm.efi
`-- sun4i-a10-cubieboard.dtb

bootarm.efiは、MSDOSの実行ファイルだった。このファイルはarmv7が実行するの? 難儀そうだな。

dtbファイルって石の定義と思われるものがあるけど、難じゃらほい。 Device Tree 入門 に説明が載ってた。fdtdumpってコマンドで、逆変換出来るようだから、後でやって 見れ。 第7章 Linuxカーネル仕様も参考になるな。

u-bootについては、 【Raspberry Pi】u-bootを動かすを参考にすれば、どんな物か分かるかな。まあ、深入りはしないけど。

OpenBSD armv7

そこにカーネルが有るなら、起動してみるが鉄則だけど、貧乏人ゆえに失敗。 ゆえに、コードを眺めて、雰囲気に浸ってみる。

[ob: arm]$ arm-none-eabi-objdump -D bsd
c0300000 <bootstrap_start>:
c0300000:       e1a06000        mov     r6, r0
c0300004:       e1a07001        mov     r7, r1
c0300008:       e1a08002        mov     r8, r2
c030000c:       e10f0000        mrs     r0, CPSR
c0300010:       e200001f        and     r0, r0, #31
 :
c0300094:       ee020f10        mcr     15, 0, r0, cr2, cr0, {0}
c0300098:       ee080f17        mcr     15, 0, r0, cr8, cr7, {0}
c030009c:       e3a00105        mov     r0, #1073741825 ; 0x40000001
c03000a0:       ee030f10        mcr     15, 0, r0, cr3, cr0, {0}
c03000a4:       ee110f10        mrc     15, 0, r0, cr1, cr0, {0}
c03000a8:       e3800001        orr     r0, r0, #1
c03000ac:       ee010f10        mcr     15, 0, r0, cr1, cr0, {0}

mcrなんてコードは、mmcの設定に関するものだな。ソースのどのあたりに記述 されているんだろう? 探してみるか。

[ob: arm]$ find /sys/arch | xargs grep bootstrap_start
/sys/arch/armv7/armv7/armv7_start.S:    .global _C_LABEL(bootstrap_start)
/sys/arch/armv7/armv7/armv7_start.S:_C_LABEL(bootstrap_start):

ふむ、そのものずばりの所に有ったわい。

/*
 * Kernel start routine for OMAP
 * this code is excuted at the very first after the kernel is loaded
 * by U-Boot.
 *
 * This code makes a number of assumptions.
 * 1) it is running in RAM.
 * 2) it is run at a fairly well known offset from the beginning of
 *    a ram section.
 * 3) the memory region around the kernel will be at least about 32MB
 * 4) memory just below the kernel can be used by the kernel
 * 5) memory at the start of the ram section may not be useable
 *    it may contain bootloader/u-boot
 * 6) the fdt/kernel parameters in arg r0-r2 may point outside the
 *    32MB of ram (it likely should be copied very early)
 *
 */
        .text

        .global _C_LABEL(bootstrap_start)
_C_LABEL(bootstrap_start):
        /* Save U-Boot arguments */
        mov     r6, r0
        mov     r7, r1
        mov     r8, r2

最初にやる事は、U-Bootからのパラメータを保護する事か。きっと、ここに 上で調べたdtbの情報が載っているんだろうな。

        mcr     CP15_TTBR0(r0)          /* Set TTB */
        mcr     CP15_TLBIALL(r0)        /* Flush TLB */

        /* Set the Domain Access register.  Very important! */
        mov     r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
        mcr     CP15_DACR(r0)

        /* Enable MMU */
        mrc     CP15_SCTLR(r0)
        orr     r0, r0, #CPU_CONTROL_MMU_ENABLE
        mcr     CP15_SCTLR(r0)
        CPWAIT(r0)

このあたりが、MMUの初期設定か、ドメインアクセスとか??なものも出てきて わけわかめだなあ。いわゆるシステムレジスターの定義と超簡単な意味は、 /sys/arch/arm/include/sysreg.hに載ってる。

/*
 * CP15 C1 registers
 */
#define CP15_SCTLR(rr)          p15, 0, rr, c1, c0,  0 /* System Control Register */
/*
 * CP15 C3 registers
 */
#define CP15_DACR(rr)           p15, 0, rr, c3, c0,  0 /* Domain Access Control Register */

そして更に、

/**
 *      omap4_smc_call - issues a secure monitor API call
 *      @r0: contains the monitor API number
 *      @r1: contains the value to set
 *
 *      This function will send a secure monitor call to the internal rom code in
 *      the trust mode. The rom code expects that r0 will contain the value an\

 *      r12 will contain the API number, so internally the function swaps the
 *      register settings around.  The trust mode code may also alter all the cpu
 *      registers so everything (including the lr register) is saved on the stack
 *      before the call.
 *
 *      RETURNS:
 *      nothing
 */
ENTRY(omap4_smc_call)
        stmfd   sp!, {r2-r12, lr}
        mov     r12, r0
        mov     r0, r1

このあたりが、以前、孫さんが自慢してた安全コードの設定か。いきなりこういうのが 出てくるんで、面喰らうな。もう、これぐらいにするかな。

locateコードを追う

BSDの方のやつを追う。gdbから、使われているマクロを確認出来るように フラグを付けてコンパイルしとく。

CFLAGS+= -I${.CURDIR}  -O0 -gdwarf-2 -g3

FreeBSDだとコンパイラーがclangで、このオプションを解釈出来ないので、

CC=gcc make

ってな具合に、コンパイラをgccに切り替えてやれば良い。

使えるgdbのマクロ関係なやつは、info macro XXXX で、定義内容の確認。 macro expand XXXX(e) で、マクロの展開である。これ便利だぞ。

locate.cのmainから実行を辿ってみると、

search_mmap (db=0x76323860 "/var/db/locate.database", s=0xcf7c7748) at locate.:209
209     {
(gdb) p *s
$1 = 0xcf7c77fc "mount_"

こんな所にやって来る。そして、dbをオープンしてそれをメモリーに割り付ける。

          if ((fd = open(path_fcodes, O_RDONLY)) == -1 ||
              fstat(fd, &sb) == -1)
                  err(1, "`%s'", path_fcodes);
          len = sb.st_size;
          if (len < (2*NBG))
                  errx(1, "database too small: %s", db);

  =>      if ((p = mmap((caddr_t)0, (size_t)len, PROT_READ, MAP_SHARED,
              fd, (off_t)0)) == MAP_FAILED)
                  err(1, "mmap ``%s''", path_fcodes);

そして、いよいよ検索ルーチンへ突入。

(gdb) s
fastfind_mmap (pathpart=0xcf7c77fc "mount_", paddr=0x819c6000 "esnttoriposiry/C
nero4.trpec_d.ndiove.tismp"..., len=1455724, database=0x76323860 "/var/db/locat
e.database") at fastfind.c:121
121     {
        /* find optimal (last) char for searching */
        for (p = pathpart; *p != '\0'; p++)
=>              if (strchr(LOCATE_REG, *p) != NULL)
                        break;

LOCATE_REGって何よ? いちいちマクロをソースに戻って探すのうざい。こういう時は

(gdb) info macro LOCATE_REG
Defined at /usr/src/usr.bin/locate/locate/locate.h:70
  included at /usr/src/usr.bin/locate/locate/locate.c:82
#define LOCATE_REG "*?[]\\"

と、簡単にチェック出来て、嬉しい。

                for (;;) {
                        c = (u_char)*paddr++;
                        len--;
                        /*
                         * == UMLAUT: 8 bit char followed
                         * <= SWITCH: offset
                         * >= PARITY: bigram
                         * rest:      single ascii char
                         *
                         * offset < SWITCH < UMLAUT < ascii < PARITY < bigram
                         */

後は愚直にコードと言うか文字の比較を行う。取り出した文字の範囲は、上のコメント の通りになってる。