Posted on

memo

[[2022-03-27]] 11.5-18

OS周辺の学習として, 友人と xv6 を読んでいきます. この記事はその為の備忘録です. 前提知識が何もないので都度フォールバックしています.

Makefile を見る

dd command

単位512byte, countブロックファイル読み書き

dd if=/dev/zero of xv6.img count=10000

電源が入ってから起動するまで

[[UEFI]] or [[BIOS]] -> [[ブートローダー]] -> [[systemd]] 起動, サービス起動

BIOS: bootloaderを探す

xv6.img: [bootloader(1blk) || kernel(..)] ? -> ぽい

MBRの探索は、優先順位の高いブートデバイスから順に、そのデバイスの先頭1セクタの末尾2バイトが0x55 0xaa (Boot Signature) であるか確認することによって行われる。BIOSは、Boot Signatureが存在するセクタを発見すると、そのセクタの内容を0x7c00 番地にロードし、実行を移す。

|500

55 aa あった.

$buf .= "\0" x (510-$n);
$buf .= "\x55\xAA";

bootloader(446B) + partition table(64B) で 510B. つじつまあう.

objcopy

$ objcopy -S -O binary -j .text bootblock.o bootblock
# bootblock.o: ELF
# bootblock: binary

-S: 再配置とシンボルの情報を入力ファイルからコピーしません -O binary: binaryにする -j .text: .text section取り出す.

  • $ readelf bootblock.o のでの .text の Off(000074) を見ると一致
  • #todo kernelld する時 .data に行くのはなぜなのか, kernel.ld にそれらしきことは書いて有りそう

|500

ld $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o
  objdump -S bootblock.o > bootblock.asm

-Ttext でこっちが勝手に0x7C00 して良いのか

Makefile から見るとソースコードの依存関係がわかり読む助けになる

為.

  • Man page of ld

  • #idea [[適当なコマンド列渡すと, man から引っ張って意味を解説してくれるツール]] 欲しい

bootmain.c

void
bootmain(void)
{
  struct elfhdr *elf;
  struct proghdr *ph, *eph;
  void (*entry)(void);
  uchar* pa;

  elf = (struct elfhdr*)0x10000;  // scratch space

  // Read 1st page off disk
  readseg((uchar*)elf, 4096, 0);
 ...
// Read 'count' bytes at 'offset' from kernel into physical address 'pa'.
// Might copy more than asked.
void
readseg(uchar* pa, uint count, uint offset) {
  uchar *epa;
  epa = pa + count;
  pa -= offset % SECTSIZE;

  // 1セクタ目=(kernelの先頭)から
  offset = (offset / SECTSIZE) + 1;
  // セクタごとに読み込み
  for (; pa < epa; pa += SECTSIZE, offset++)
    readsect(pa, offset);
}

xv6.img の先頭4096Bを [[ELF]] header として読んで, Entry point addr(elf->entry) を見つけ, 関数ポインタとして実行する (示す先は entry.S_start, kernel.ldENTRY(_start) と指定しているので) .

  • misc: zellijのトリガ: C-t

  • offset = (offset / SECTSIZE) + 1;

    • 罠: ここで単位がセクタに変換される
    • 0ブロック目はbootloader, それ以降はkernel

outb: I/O portにデータを読み書きする

kernel.ld

SECTOINS {
 // must equal to KERNLINK
 . = 0x80100000;
 .text : AT(0x100000) {
 }
}

[xv6] paging読む へ続く

参考, 関連リンク