disklabel
install in GPT
OpenBSD6.5をuEFI対応PCにインストールする方法
OpenBSD のインストール (7.0 ARM64 on rpi 版)
切り口を変えて検索すると、色々な方の例が出て来るなあ。世の中リナだけで回っていない事がよく分る。
endian
ふと、 エンディアン について調べてみた。
日本はビッグエンディアンが普通だ。年月日って表す。ヨーロッパは、日月年って具合。 日付の国際規格では、2022-11-15 のように表す。この日は、神社、写真館、レンタルな衣装屋が儲かる日だな。
糞石の世界は、ひねくれていて、リトルエンディアンだ。どう格納されるか、小さいコードで確認してみる。 @ FreeBSD(32Bit version)
int lo = 0x12345678; int hi = 0xfedcba98; int main() {}
gdbでmainで止める。
(gdb) p/x lo $2 = 0x12345678 (gdb) p/x hi $3 = 0xfedcba98 (gdb) x/8b &lo 0x40393c <lo>: 0x78 0x56 0x34 0x12 0x98 0xba 0xdc 0xfe
long longな場合はどうか?
(gdb) p/x abc $1 = 0x123456789abcdef (gdb) x/8b &abc 0x403830 <abc>: 0xef 0xcd 0xab 0x89 0x67 0x45 0x23 0x01
hexeditを使って、バイナリーデータを検索する時は、要注意だな。ってか、脳内変換なんて、到底無理と思うので、変換スクリプトを考えてみる。rubyでやるなら、取り敢えず2文字づつの分解が山だな。
vbox$ irb irb(main):001:0> s = "1234567890" => "1234567890" irb(main):002:0> n=2 => 2 irb(main):003:0> s.scan(/.{1,#{n}}/) => ["12", "34", "56", "78", "90"]
でも、rubyはデフォでは入っていない。やはり古典的な方法が無難だ。ああ、pythonなんて論外です。頼みもしないけど、いつの間にか鎮座してるけどね。
#!/bin/sh # big endian to little endian echo $1 | sed -e 's/0x//' | awk '{ if ( length($0) % 2 == 1 ) { $0 = sprintf("0%s", $0) } for (i = length($0) - 1; i > 0; i -= 2) { printf substr($0, i, 2) ; } printf "\n"; } '
使用例。上のC言語のサンプルをコンパイル。そうしておいてバイナリーエディタを起ち上げ。vi宜しく、/ で検索文字を入力。カーソルはvvの所に来た。続く、0xfedcba98も次の位置に見えている。これで、検索が捗るな。
vbox$ b2l 0x12345678 78563412 vbox$ hexedit a.out Hexa string to search: 78563412 vv 000010C0 61 17 00 00 81 17 00 00 A1 17 00 00 78 56 34 12 a...........xV4. 000010D0 98 BA DC FE 01 11 01 25 0E 13 05 03 0E 10 06 1B .......%........ --- a.out --0x10DC/0x1AF0--63%------------------------------------------
こんなに頭を悩ませるのは、そもそも糞石のせい。普通の人はビッグエンディアンなのに、あの石は常軌を逸脱したリトルエンディアンですから。それからラズパイの石ってかOSもリトルエンディアンなんだよな。困ったものだ。
最近、考古学者は名探偵なんて本を読んだんよ。そしたら、本当に糞石ってのが有るそうな。 コプロライトって学術名がついているらしい。ギリシャ語で、コプロってのが糞を意味し、ライトは石の意味だそうだ。
遺跡を発掘すると、昔の人の便所が出てくる事があるとか。条件が良いと糞が石状になってるらしい。これを分析すると、昔の人が何を食べていたか分るとか。寄生虫の卵を分析するとか、人と犬のウンチは似てて区別がつかなかったけど、残留脂肪酸分析で区別がつくようになったとか。
先人の活躍、ウンチに対する知見を広めるため、はじめ – ふんばった時に最初に出てくる先端部分、シボリ – 最後の部分、バナナ – 中間の弧の部分、コロ – 便秘ぎみ。その他、踏まれてひしゃげた物はフミクソ、火にあぶられた跡のある物はヤケクソって言うらしい。落語みたいだな。一度聞いたら忘れられない強烈なネーミングだ。
おさらい
ちょっと32MのDISKを作って、それを8Mと24Mのパーテションに分てみる。
vbox# dd if=/dev/zero of=test.img bs=1M count=32 32+0 records in 32+0 records out 33554432 bytes transferred in 0.335 secs (100110771 bytes/sec) vbox# vnconfig test.img vnd0 vbox# disklabel -E vnd0 Label editor (enter '?' for help at any prompt) vnd0> a d offset: [0] size: [65536] 16384 FS type: [4.2BSD] vnd0*> a e offset: [16384] size: [49152] FS type: [4.2BSD] vnd0*> w vnd0> p OpenBSD area: 0-65536; size: 65536; free: 0 # size offset fstype [fsize bsize cpg] c: 65536 0 unused d: 16384 0 4.2BSD 2048 16384 1 e: 49152 16384 4.2BSD 2048 16384 1
cパーテションはDISK全体を表す決まりになってる。それ以外では、a,bパーテションがデフォの機能を担当する事になってて、後は自由だ。
vbox# newfs vnd0d /dev/rvnd0d: 8.0MB in 16384 sectors of 512 bytes 4 cylinder groups of 2.00MB, 128 blocks, 256 inodes each super-block backups (for fsck -b #) at: 160, 4256, 8352, 12448, vbox# newfs vnd0e /dev/rvnd0e: 24.0MB in 49152 sectors of 512 bytes 4 cylinder groups of 6.00MB, 384 blocks, 768 inodes each super-block backups (for fsck -b #) at: 160, 12448, 24736, 37024,
それぞれをnewfsしてみた。次は、それをマウントして、DISKの容量とinodeの消費状態を確認。
vbox# mkdir /tst vbox# mount /dev/vnd0d /mnt vbox# mount /dev/vnd0e /tst vbox# df -ki Filesystem 1K-blocks Used Avail Capacity iused ifree %iused Mounted on : /dev/vnd0d 7726 2 7338 0% 1 1021 0% /mnt /dev/vnd0e 23598 2 22418 0% 1 3069 0% /tst
4シリンダー有るので、実際に使える容量とinodeは報告された物の4倍になる。また、1つのファイルの最小容量は2048byteだ。これは、fsize すなわちフラグメントサイズになる。bsizeと言うのはブロックサイズを意味し、DMAでの転送単位になるのかな。
シリンダーってのは、DISKを半径方向に分割し、使用エリアが分散するような管理をしてる。また、大事なスーパーブロックもそれぞれのシリンダーに分散させてバックアップを兼ねさせている。
vbox# disklabel -E vnd0 Label editor (enter '?' for help at any prompt) vnd0> p OpenBSD area: 0-65536; size: 65536; free: 0 # size offset fstype [fsize bsize cpg] c: 65536 0 unused d: 16384 0 4.2BSD 2048 16384 128 e: 49152 16384 4.2BSD 2048 16384 384
一度使用すると、cpgが更新されるみたい。これは、個々のシリンダーグループが幾つのシリンダー(トラック)で構成されてるかを表すのかな。
disklabel
DISKの区画を作るのに手動でやった。自動でやる場合は、どんな風に分るか、更にはDISKの諸元が必要だ。それをあらかじめ登録したファイルが有る。OpenBSDではお任せにしちゃう事が多いので、余り登録されていない。下記は、FreeBSDから代表例を引いてきたものだ。
/etc/disktab
# a == root # b == swap # c == d == whole disk # e == /var # f == scratch # h == /usr cp3100new|Connor Peripherals 100MB IDE, with a different configuration:\ :dt=ST506:ty=winchester:se#512:nt#8:ns#33:nc#766: \ :pa#15840:oa#0:ta=4.2BSD:ba#4096:fa#512: \ :pb#24288:ob#15840:tb=swap: \ :pc#202224:oc#0: \ :pd#202224:od#0: \ :pe#15840:oe#40128:te=4.2BSD:be#4096:fe#512: \ :pg#15840:og#55968:tg=4.2BSD:bg#4096:fg#512: \ :ph#130416:oh#71808:th=4.2BSD:bh#4096:fh#512:
それはさておき、本物のDISKで試してみる。今迄は、ファイルをデバイスに見立てるって方法だったからね。
qemu disk
qemuにDISKを用意させ、そいつを有効にして起動。次は、disklabelを使って、オートレイアウトで、パーテショニング。出来栄えを確認。
ob$ qemu-img create -f qcow2 ext.img 4G Formatting 'ext.img', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=4294967296 lazy_refcounts=off refcount_bits=16 ob$ ./boot -E : qm# disklabel -wA wd1 qm# disklabel wd1 # /dev/rwd1c: type: ESDI disk: ESDI/IDE disk label: QEMU HARDDISK duid: 2fd85dfcaa0d1990 flags: bytes/sector: 512 sectors/track: 63 tracks/cylinder: 255 sectors/cylinder: 16065 cylinders: 522 total sectors: 8388608 boundstart: 0 boundend: 8388608 drivedata: 0 16 partitions: # size offset fstype [fsize bsize cpg] a: 1808352 0 4.2BSD 2048 16384 1 b: 503800 1808352 swap c: 8388608 0 unused d: 5314080 2312160 4.2BSD 2048 16384 1 e: 762368 7626240 4.2BSD 2048 16384 1
a,d,eのパーテションは地均しする必要が有る。で、dパーテションだけフォーマット。この時、各パーテション毎に4つのシリンダーグループが作られるんで、12ヶ出来るはずだけど、一つ多い。それって、swap用かな。
qm# newfs wd1d /dev/rwd1d: 2594.8MB in 5314080 sectors of 512 bytes 13 cylinder groups of 202.50MB, 12960 blocks, 25920 inodes each super-block backups (for fsck -b #) at: 160, 414880, 829600, 1244320, 1659040, 2073760, 2488480, 2903200, 3317920, 3732640, 4147360, 4562080, 4976800,
こうしてdパーテションを作成すると、cpg は、12960 にセットされてたよ。
ラベルブロックがどんな風になってるか、確認したい。が、相手は本物?のHDD、そのままではアクセスが面倒。そんな時の為にDISK全体を表すcパーテションを利用する。
DISKの先頭の1ブロックをスキップしてから1セクター分のデータを取出して確認。
qm# dd if=/dev/wd1c of=sb.txt skip=1 count=1 1+0 records in 1+0 records out 512 bytes transferred in 0.005 secs (97312 bytes/sec) qm# hexdump -C sb.txt 00000000 57 45 56 82 05 00 00 00 45 53 44 49 2f 49 44 45 |WEV.....ESDI/IDE| 00000010 20 64 69 73 6b 00 00 00 51 45 4d 55 20 48 41 52 | disk...QEMU HAR| 00000020 44 44 49 53 4b 20 20 20 00 02 00 00 3f 00 00 00 |DDISK ....?...| 00000030 ff 00 00 00 0a 02 00 00 c1 3e 00 00 00 00 80 00 |.........>......| 00000040 2f d8 5d fc aa 0d 19 90 00 00 00 00 00 00 00 00 |/.].............| 00000050 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 |................| 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000070 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 00 00 00 00 57 45 56 82 98 9f 10 00 00 20 00 00 |....WEV...... ..| 00000090 00 00 01 00 e0 97 1b 00 00 00 00 00 00 00 00 00 |................| 000000a0 07 14 01 00 f8 af 07 00 e0 97 1b 00 00 00 00 00 |................| 000000b0 01 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 |................| 000000c0 00 00 00 00 20 16 51 00 e0 47 23 00 00 00 00 00 |.... .Q..G#.....| 000000d0 07 14 a0 32 00 a2 0b 00 00 5e 74 00 00 00 00 00 |...2.....^t.....| 000000e0 07 14 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000200
busy ?
上で出て来た仕様書により区画を作れるか確認。まあ無理筋とは思うけど。
qm# disklabel -w /dev/wd1c cp3100new disklabel: DIOCWDINFO: Device busy qm# disklabel -wA /dev/wd1c
やっぱり無理、理由は忙しいとな。そんなのソース嫁。 disklabel.c
writelabel(int f, struct disklabel *lp) { /* Write new label to disk. */ if (ioctl(f, DIOCWDINFO, lp) == -1) { warn("DIOCWDINFO"); return (1); }
その先は、 dev/ata/wd.c ここみたいって、大変な場所だな。この先を見る気分じゃないよ。
wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p) { case DIOCWDINFO: case DIOCSDINFO: if ((flag & FWRITE) == 0) { error = EBADF; goto exit; } if ((error = disk_lock(&wd->sc_dk)) != 0) goto exit; error = setdisklabel(wd->sc_dk.dk_label, (struct disklabel *)addr, wd->sc_dk.dk_openmask);
これHDDが持ってる特性エリアを直接読み出したものだろう。それを曲げて違うHDDを名乗るって、詐欺になるぞって事なんだな。
qm# atactl wd1 identify Model: QEMU HARDDISK, Rev: 2.5+, Serial #: QM00002 Device type: ATA, fixed Cylinders: 8322, heads: 16, sec/track: 63, total sectors: 8388608 Device capabilities: IORDY operation Device supports the following standards: ATA-4 ATA-5 ATA-6 ATA-7 Device supports the following command sets: NOP command Write cache SMART feature set Flush Cache Ext command Flush Cache command 48bit address feature set Device has enabled the following command sets/features: NOP command Write cache SMART feature set Flush Cache Ext command Flush Cache command 48bit address feature set
smart
本物のDISKだとSMARTが動くらしいので、確認する
qm# atactl /dev/wd1c smartread Off-line data collection: status: completed ok activity completion time: 288 seconds capabilities: execute immediate read scanning self-test routines Self-test execution: status: completed ok or not started recommended polling time: short routine: 2 minutes extended routine: 54 minutes SMART capabilities: saving SMART data enable/disable attribute autosave Error logging: supported
qm# atactl /dev/wd1c smartreadlog selftest Test 1 LBA Low: 0x0 status: completed ok or not started timestamp: 4660 failure checkpoint byte: 0x0 failing LBA: 0x0
portsにsmartmontoolsが有ると言うのにデフォで機能を搭載してるって、安全に留意してますって事かな。変な事をされない為ってのが錦の旗です。
seeing by disklabel
vnd0を作って、-wA vnd0 した時の図。
(gdb) bt #0 writelabel (f=6, lp=0x348b1070) at disklabel.c:311 #1 0x148bdc3b in main (argc=1, argv=0xcf7e198c) at disklabel.c:286 (gdb) p *lp $3 = {d_magic = 2186691927, d_type = 12, d_subtype = 0, d_typename = 0x348b1078 "vnd device", d_packname = 0x348b1088 "fictitious", d_secsize = 512, d_nsectors = 100, d_ntracks = 1, d_ncylinders = 655, d_secpercyl = 100, d_secperunit = 65536, d_uid = 0x348b10b0 "", d_acylinders = 0, d_bstarth = 0, d_bendh = 0, d_bstart = 0, d_bend = 65536, d_flags = 0, d_drivedata = 0x348b10cc, d_secperunith = 0, d_version = 1, d_spare = 0x348b10e4, d_magic2 = 2186691927, d_checksum = 21137, d_npartitions = 16, d_bbsize = 8192, d_sbsize = 65536, d_partitions = 0x348b1104}
詐欺を働こうとすると、
318 if (ioctl(f, DIOCWDINFO, lp) == -1) { (gdb) 0x18fd1080 #define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++)) (gdb) 319 warn("DIOCWDINFO"); (gdb) disklabel: DIOCWDINFO: Device busy 320 return (1);
こんな風に引掛った。
dd
今迄度々登場してるddコマンド。 A dd utility appeared in Version 5 AT&T UNIX. のように由緒あるやつ。dd - convert and copy a file とあるように、cpのついでにconvertするのが主目的。
大型コンピュータのデータをunixとやり取りするのが主目的。その頃の大型コンピュータと言ったら、IBMさんのやつがデファクトスタンダード。こいつの文字コードがebcdicという独自のもの。unixのASCIIコードとは、相容れないやつだ。
だから、コピーのついでに文字コードも変換出来たら楽だねって事で、unix側がすりよった。 小さな工夫と言ったらなんだけど、512バイトのブロック単位にコピー出来れば更に楽出来る。 という事で、コピーの単位を512バイトをデフォとした。そして、それを何回繰り返すって指定も出来るようにした。ifとかofってのは、入出力のファイル名。
sakae@deb:~$ dd if=/dev/zero of=z count=1000000 1000000+0 records in 1000000+0 records out 512000000 bytes (512 MB, 488 MiB) copied, 7.68823 s, 66.6 MB/s sakae@deb:~$ dd if=/dev/zero of=z count=1000 bs=512000 1000+0 records in 1000+0 records out 512000000 bytes (512 MB, 488 MiB) copied, 8.23623 s, 62.2 MB/s
で、上のような例になる。bsでブロックサイズを任意に設定出来る。bsを大目にして、繰返し回数を減らせば、スピードアップが図れる。普通はこの使いかたをする。
それから変換の指定は、conv=ibm,lcase と言うように機能をカンマ区切で並べて指定する。今となっては遺物っぽいな。
R + Tcl/Tk
デフォのRでもサポートされてる様なので、気分転換してみる。
なぜシェルスクリプトで高度なデータ管理にSQLiteを使うべきなのか? ~ UNIX/POSIXコマンドの欠点をSQLで解決する
ちょい使いのGUIにはいいな。