picobsd,nanobsd
周回遅れと言うか、月遅れと言うか、以前に買ったSDの2月号を今頃になって読んでいる。だって、月刊誌ってその時に手に入れておかないと、手に入れるのが面倒になるんだもん。取り合えず、積読状態にしておけば安心。
何が目当てだったかと言うと、systemdの特集。最近じゃFreeBSDにも導入するとか言う不穏な空気が漂ってますから、取り合えずの先行投資。で、読んでみると、未だにBug内在してるようで、Bug除けのおまじないが炸裂してた。
他の特集ではPythonのモジュール。機械学習がらみで、有名処が紹介されてた。まあ、現代風なBasicと思っておけば間違いないな。オイラーも久しぶりに触ってみるかな。解説記事をそのままなぞるのも馬鹿っぽいので、pythonにbase58が有るか探してみる。無い物は無いと言うPythonだから、きっとあるだろう。(Python頼みかよ!!)
debian:~$ pip search base58 base58 (0.2.5) - Base58 and Base58Check implementation base58_encoded (0.1) - Encode an integer using base58. You know, for short urls.
はて、どちらを入れればいいのでしょうか? 取り合えずbase58を選んでみる。きっとビットコインでも使われていて、信頼がおけるだろうから。
debian:~$ ipython Python 3.6.4 |Anaconda, Inc.| (default, Mar 13 2018, 01:15:57) Type 'copyright', 'credits' or 'license' for more information IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: import base58 In [2]: base58. alphabet b58decode_int() b58encode_int() iseq() b58decode() b58encode() bseq main() b58decode_check() b58encode_check() buffer() sha256()
base58. まで入力してTABを叩くと、候補が色々出て来た。まずはエンコードだな。数値用と 文字用が有ると思われる。文字用を試すか。
In [2]: base58.b58encode('hello') --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-2-ed05472b07f4> in <module>() ----> 1 base58.b58encode('hello') ~/miniconda3/lib/python3.6/site-packages/base58.py in b58encode(v) 43 if not isinstance(v, bytes): 44 raise TypeError("a bytes-like object is required, not '%s'" % ---> 45 type(v).__name__) 46 47 origlen = len(v) TypeError: a bytes-like object is required, not 'str'
早速エラーの洗礼。エラーを出して頭を捻って鍛えられるのさ。どうしましょ?
In [3]: base58.b58encode(b'hello') Out[3]: 'Cn8eVZg'
門前の小僧習わぬ経を読む、ってやつかな。次は逆演算だな。
In [4]: base58.b58decode('Cn8eVZg') Out[4]: b'hello'
普通に、元に戻った。
In [7]: base58.b58encode_int(-123) ^C--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) <ipython-input-7-70040f583258> in <module>() ----> 1 base58.b58encode_int(-123) ~/miniconda3/lib/python3.6/site-packages/base58.py in b58encode_int(i, default_one) 35 while i: 36 i, idx = divmod(i, 58) ---> 37 string = alphabet[idx] + string 38 return string 39 KeyboardInterrupt:
さっぱり答えが返ってこないので、止めたよ。intって負数はダメなんですかと作者さんに聞いてみたいぞ、と。まあ、そんな難癖を付けるのは止めとけ。それより、FreeBSDに入ってる2系のやつでも動くかな。(なんたって、頑固物のFreeBSDですから、ちゃらちゃらしないのさ)
[fb11: ~]$ pip install --user base58 [fb11: ~]$ python2 Python 2.7.14 (default, Jan 2 2018, 01:25:01) [GCC 4.2.1 Compatible FreeBSD Clang 4.0.0 (tags/RELEASE_400/final 297347)] on freebsd11 Type "help", "copyright", "credits" or "license" for more information. >>> import base58 >>> base58.b58encode('hello') 'Cn8eVZg' >>> base58.b58decode('Cn8eVZg') 'hello'
どうやら、2系もサポートしてた。(文字列の扱いが2と3では違う。2の扱いは失敗だったとPython作者さんは認めています)モジュールとしてちゃんとした作りになってた。(お前が偉そうに言うな)
[fb11: ~]$ python2 -m base58 -h usage: base58.py [-h] [-d] [-c] [FILE] Base58 encode or decode FILE, or standard input, to standard output. positional arguments: FILE optional arguments: -h, --help show this help message and exit -d, --decode decode data -c, --check append a checksum before encoding
このエンコーディングを3回ぐらい繰り返せば、トリプルDESならぬトリプルBase58となって、簡易な暗号として 利用出来ますよ。(共通鍵暗号には、鍵が必要だろう。どういう風に鍵を使うかが鍵ですけどね)だって、base58なんて使う人は、コインチェックに明け暮れる、金儲け屋さんぐらいしかいませんからね。
ウォズ、ビットコインを詐取された体験を語る あっ、こんな人が居たか。
作って学ぶBitcoin!ゼロから作るSPVウォレット by Haskell
picobsd
ピコって言うぐらいだから、1e-12 なBSDって事で宜しいか。小ささを際立たせる表現。 前回picobsdなんてのを見つけてしまったものだから、寄り道してみる。picobsd(8)が登録されてるんで、正式にサポートしてますって事だな。
マニュアルを斜め読みした限りでは、
[fb11: sakae]# cd /usr/src/release/picobsd/build/ [fb11: build]# ./picobsd -n qemu PicoBSD build -- Current parameters: 1. Type: qemu name qemu 2. MFS size: 18000 kB 3. Site-info: 4. Full-path: /usr/src/release/picobsd/qemu ---> We'll use the sources living in /usr/src cd /usr/src/sys/amd64/conf; config -d /usr/src/release/picobsd/build/build_dir-qemu-amd64/PICOBSD-qemu PICOBSD-qemu PICOBSD-qemu: unknown option "I586_CPU" *** Error code 1 Stop. make: stopped in /usr/src/release/picobsd/qemu ---> fail: Error <1> error code <missing_kernel> in <> Error: you must build PICOBSD kernel first ---> Aborting ./picobsd
amd64な石の元で、I586な石は、理解不能と言う事だな。スクリプトを ちょい見したら、uname -mで石を割り出している。ここを強引にi386と 書き換えても、コンパイラーが今度はそんな石は知らないと言うだろう。 (前回経験済)
はて、どうする? FreeBSD 5.1が有るじゃん。同地を訪れてみたら
f51# cd /usr/src/release/picobsd/ f51# ls README.html build floppy.tree mfs_tree tinyware Version dial help net bridge doc isp router
ダイアルアップ用とかルーター用とかあるけど、肝心のqemu用が無い。これはもう、卵になるqemuの設定をFreeBSD5.1に移して、そこで代理出産させるか。上手く生まれたら、結果だけをqemuが入っているFreeBSD11.1に戻せばいいんだから。
# -mkdir -p /usr/src/sys/i386/conf # XXX not needed yet. cp PICOBSD /usr/src/sys/i386/conf/PICOBSD-qemu if [ -f PICOBSD.hints ] ; then cp PICOBSD.hints /usr/src/sys/i386/conf/PICOBSD.hints ; fi (cd /usr/src/sys/i386/conf; config -d /usr/src/release/picobsd/build/build_dir-qemu/PICOBSD-qemu PICOBSD-qemu; cd /usr/src/release/picobsd/build/build_dir-qemu/PICOBSD-qemu; make KERNEL=kernel -DNO_MODULES depend ) Specify machine type, e.g. ``machine i386'' *** Error code 1 Stop in /usr/src/release/picobsd/qemu. ---> fail: Error <1> error code <missing_kernel> in <> Error: you must build PICOBSD kernel first ---> Aborting ./picobsd
走らせると上記のようなエラーを吐く。どうやらkernelを作る仕様書を手直ししないとだめみたい。picobsdを起動する時の -n オプションを省くと、インタラクティブモードになって、設定を編集してからgo出来る。
ユーザーランドの方は、リナで言うbusyboxのごとく、クランチバイナリーになるのね。関数の名前解決が出来ずにエラーになってたので、あちこち削った。最近問題になってる、デザイナーベビーを編集してる気分になったぞ。
で、最後の最後で、こんなエラーが出た。
Filesystem 1K-blocks Used Avail Capacity iused ifree %iused Mounted on /dev/md0c 17303 827 16476 5% 69 2233 3% /tmp/picobsd.M5zW78AbSI /dev/md0c: FILESYSTEM CLEAN; SKIPPING CHECKS /dev/md0c: clean, 32953 free (17 frags, 4117 blocks, 0.0% fragmentation) usage: bsdlabel disk (to read label) bsdlabel -w [-n] [-m machine] disk [type] (to write label with existing boot program) :
エラーは、bsdlabelの使い方を示唆したもの。エラーになったにも関わらず、 build_dir-qemu/picobsd.binが出来上がっていた。無事に出産出来たんですかね?
取り合えず、FreeBSD11.1へ持って行って、実行してみる。
[fb11: tmp]$ qemu-system-i386 -m 256 picobsd.bin WARNING: Image format was not specified for 'picobsd.bin' 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. gtk initialization failed
badlabelが認識出来ないのかなあ? もう少しpicobsdスクリプトと首っ引きにならないと、だめだろうね。まあ、いきなりデザイナーベビーが誕生する訳は無いわな。もし誕生したら、ノーベル賞ものだぞ。いや、そんな事は無い。世界中から非難轟々だぞ。(神の領域に手を出すなってね)すこしほとぼりが冷めるまで、待とう。
picobsdのmanを見てたら、1000倍大きいbsdが紹介されてた。
nanobsd
FreeBSD 6.0 からサポートされたとか。作成方法は下記。
The necessary commands to build and install a NanoBSD image are: cd /usr/src/tools/tools/nanobsd sh nanobsd.sh cd /usr/obj/nanobsd.full dd if=_.disk.full of=/dev/da0 bs=64k
実験とか組み込み用のたたき台にどうぞって触れ込みだ。picoより1000倍は大きくて、ユーザーランド全部とカーネルを含んだものらしい。
例の所にあるddの使い方から分かるように、diskを全部使っちゃうという(ラズパイでメディアに転送すれば全て完了)仕様だ。これを使って、FreeBSDのラズパイ版が作られているんだな。
とか言っていたら、サンプルとして提供されてる、embededの中に、ずばりrpi.cfgとかrpi2.cfgなんて言う仕様書が置いてあった。ちょいと指を咥えて眺めてみる。
NANO_ARCH=armv6 NANO_KERNEL=RPI2 NANO_DRIVE=mmcsd0 NANO_NAME=rpi2 NANO_BOOT_PKG=u-boot-rpi2 NANO_CPUTYPE=cortex-a7 . common # Pull in common definitions, keep last
ラズパイで使うSDカードは頻繁に書き込むと劣化してエラーを出す。(そういうネガティブな事は、雑誌で取り上げられない)このnanobsdでは、/varと/tmpをRAM上に取って、メディアへの書き込みを抑止してる。これらをセーブするエリアとして、/cfgってのが用意されてるそうな。
この事情は普通の人(SSDに負担をかけないように常に注意してるオイラーみたいな貧乏人)でも同じで、 FreeBSD を read-only で起動なんていう、貴重な取り組みをしてる方に出会ったよ。
興味を持った人にはmanを補う資料として、 Introduction to NanoBSDなんてのが公開されてる。アップデートの事もちゃんと考えられていて、メディアを2つに分けて、片方でシステムが動いている時、もう片方に入れて、ちゃんと動いたら切り替えて使えるそうな。
ざっとnanobsd.shを眺めると、build world と build kernel それとインストールを一気通貫に行ってくれるようだ。昔は、頻繁にbuildをやったものだけど(カスタマイズを兼ねて)、バイナリーでアップデート(主としてセキュリティーの為)出来るようになってからは、止めちゃったな。
今の巨大になったシステムだと、どれぐらい時間がかかるのだろう? 多分、途方もなくパソコンを痛めつける事になるんだろうね。そんなお悩み解消しますって手がある。例えば、zfsなんて使わないから入れなくて(コンパイルしなくて)いいよってんで、機能を削れる。 FreeBSDのsrc.conf が、その役目を果たしてくれる。有り難ーい設定ファイルです。
ちなみに今風のOSをコンパイルするのが、どのぐらい大変かを実感させてくれる記事が出てたぞ。ラズパイで動くスマートテレビOS、Palm由来の「webOS」を試す
物理4コア、メモリーが16Gのマシンで、4時間ですってさ。そしてドライブ容量100Gは必要ってんだから、呆れて物が言えませんよ。
nanobsdをコンパイルする時は、 make -j 3 で、パラレルコンパイルがデフォになってました。ネットを見てると、nanobsdやってみたーって人がいますが、どれぐらいパソコンを酷使したか言及してる人は皆無でした。みんなビットコイン(お馬さんとかお舟でもいいけど)であぶく銭を手にした人なんでしょうな。そう言えば、友達と話していた時、ビットコインをやってるのは、銀座の夜のおねーちゃんが多いと言ってたな。髪結いの亭主(ヒモ)希望!!
再び picobsd
という事で、貧乏人のためのpicobsdに戻ってきました。上で出ていたエラーを追求してみましょ。そんなの、picobsdっていうシェルスクリプトを読めってのが王道ですが、年寄りは短気なので、トレースしちゃえ。
f51# sh -x ./picobsd -n qemu | & tee LOG f51# less LOG : + b2=/usr/src/release/picobsd/build/build_dir-qemu/boot2 + perl -pne s/\/boot\/loader/\/kernel\0\0\0\0\0/ /boot/boot2 + disklabel -Brw -b /boot/boot1 -s /usr/src/release/picobsd/build/build_dir-qemu/boot2 md0 auto usage: bsdlabel disk (to read label) bsdlabel -w [-n] [-m machine] disk [type] (to write label with existing boot program) :
スクリプト中では、disklabelを指定してるのに、実際に応答(して、使い方を開陳)したのは、bsdlabelでしたよ。どうやら、同じ名前で登録されてるようです。多分disklabelが元祖で、bsdlabelはより大容量のメディアにも対応したって事でしょう。
bsdlabelのmanを見ると、-sオプションなんてのはサポートしてない。それで、bsdlabelが怒り心頭になったのでしょう。はて、どうしてくれよう。
boot2の中にある/boot/loader文字列を/kernelに書き換えておき、それも含めてbootの一部にしたいと言う算段でしょう。boot = boot1 + boot2 らしいんで、ここは素直に/boot/bootを使うように指定。/boot/loaderが無ければ、素直にスルーしてくれるはずですから。
こうやって作ったpicobsd.binを持って行ったら、少しは進歩して、カーネルのロードが始まった。けど、ハングですよ。qemuは色々と欲張り過ぎたんかな。
方針を変えて、5.1に元々有ったdialってのに方向転換。でも、あちこち修正しないと作成が途中で止まる。特に最後のカーネルを書き込む所で、メディアの容量不足になったよ。初期はフロッピー1枚サイズだったんだ。dial/config中で、fd_size=8192に変更しといた。
f51# ls -lh build_dir-dial/ total 12388 drwxr-xr-x 2 root wheel 12K Mar 30 00:56 PICOBSD-dial -rw-r--r-- 1 root wheel 7.5K Mar 30 00:56 boot2 drwxr-xr-x 2 root wheel 3.0K Mar 30 00:56 crunch -rw-r--r-- 1 root wheel 34K Mar 30 00:56 crunch.mk -rw-r--r-- 1 root wheel 1.8K Mar 30 00:56 crunch1.conf drwxr-xr-x 3 root wheel 512B Mar 30 00:56 floppy.tree -rwxr-xr-x 1 root wheel 4.0M Mar 30 00:56 kernel drwxr-xr-x 20 root wheel 512B Mar 30 00:56 mfs.tree -rw-r--r-- 1 root wheel 8.0M Mar 30 00:56 picobsd.bin
これで、picobsd.binをqemu-system-i386に食わせたら、カーネルは無事に起動した。 でも、いよいよinitを起動しようとしてパニックたぞ。結局loginは拝めず、残念至極。
new picobsd
って、FreeBSD11.1に付いてたのを、そう呼ぶ事にする。
興味深い記述
# select the right disklabel program case `uname -r` in 4.*) c_label="disklabel" ;; *) c_label="bsdlabel" ;; esac ${c_label} -w -f `pwd`/${c_img} auto # write in a label # copy partition c: into a: with some sed magic ${c_label} -f `pwd`/${c_img} | sed -e '/ c:/{p;s/c:/a:/;}' | \ ${c_label} -R -f `pwd`/${c_img} /dev/stdin ${c_label} -f `pwd`/${c_img}
FreeBSDの4系までは、disklabelで、それ以上はbsdlabelって振り分け。デバイスがファイルでも指定出来るように -f オプションが追加されてると読めるんだけど、5.1のbsdlabelでは サポートされていない。11.1で確認すると
[fb11: tmp]$ bsdlabel -f picobsd.bin # picobsd.bin: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 16384 0 4.2BSD 512 4096 4104 c: 16384 0 unused 0 0 # "raw" part, don't edit
boot系の書き込みはbsdlabelを離れて、ddの技を使ってる。
echo "BUILDDIR ${BUILDDIR}" # dump the primary and secondary boot # XXX primary is 512 bytes dd if=${c_boot1} of=${BUILDDIR}/${c_img} conv=notrunc 2>/dev/null # XXX secondary starts after the 0x114 = dec 276 bytes of the label # so we skip 276 from the source, and 276+512=788 from dst # the old style blocks used 512 and 1024 respectively dd if=${c_boot2} iseek=1 ibs=276 2> /dev/null | \ dd of=${BUILDDIR}/${c_img} oseek=1 obs=788 conv=notrunc 2>/dev/null log "done disk image"
一応、ファイルシステムを確認。
[fb11: tmp]$ sudo mdconfig -a -t vnode -f picobsd.bin md0 [fb11: tmp]$ ls /dev/md* /dev/md0 /dev/md0a /dev/mdctl [fb11: tmp]$ sudo mount /dev/md0a /mnt [fb11: tmp]$ ls -l /mnt total 1496 -rwxr-xr-x 1 root wheel 1527431 Mar 31 02:07 kernel* [fb11: tmp]$ sudo umount /mnt [fb11: tmp]$ sudo mdconfig -du md0
カーネルしか無いけど、それで委員かい? ここは、ユーザーランドと言うか、dir-treeが 存在しないといけないと思うんだけど。先ほどパニックったって書いたけど、/sbin/init等が何処にも見つかりませんでしたって、断末魔の声を上げてたからなあ。 要調査だな。
build_dir-dial/mfs.treeの中は、ちゃんとツリーが出来ていて、チャンクバイナリーも存在してた。で、mfs.treeの中にinitが有るかと探したら、無かったぞ。
dial/crunch.conf に、initを追加したよ。 そしたら、ミニダエモン君のバナーと共に、loginプロンプトが出て来た。いざloginしようとすると、/usr/sbin/loginが無いですってさ。ちゃんと動くものを掲載して欲しいなあ。
多分、loginだけじゃ足らなくてgettyあたりも必要になるだろうね。それより、rootとかuserのパスワードをjoeにしておかねば、login出来ないぞ。
で、ちょいと、唯一のkernelの出来を見ておく。readelfって道具でね。
Elf file type is EXEC (Executable file) Entry point 0x500000 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x001000 0x00500000 0x00500000 0x016dd 0x016dd R E 0x1000 LOAD 0x003000 0x00502000 0x00502000 0x173992 0x183e8c RW 0x1000 Section to Segment mapping: Segment Sections... 00 .text .rodata 01 .data .bss
これしか無いと言う事は、bss領域にでも、ファイルシステムを埋め込んでいるんだろうね。サイズがやけに大きいぞ。以前にやったxv6方式だな。
これ、picobsdなシェルを使わないで、手動でやる時参考になるよ。