↓最初の環境構築からご覧になる場合はこちらからどうぞ
Windows系SEの日記: 【12ステップで作る組込みOS自作入門】Windows 10+Cygwinで実装中
今回は6thステップで、いよいよRAM上にOSを読み込むためのブートローダーが完成です。
5thステップまででバッファ内のelfファイルの解析処理までは完了してます。
なので、あと必要な処理は
【ブートローダー】
読み込んだelfファイル内のプログラムヘッダ情報をもとに、適切に実行できるようにRAM内の適切なアドレスにセクションをコピーしていく
読み込まれる側のOSもRAMで実行できるようにメモリマップを変更する必要がありますので、
【OS】
全セクションがRAM側のアドレスに読み込まれるようにリンカスクリプトの修正
となります。
■ram領域に余裕が必要な理由
ちょっとわかりにくかったのが、以下のOS部分のリンカスクリプトのMEMORYコマンド部分。
MEMORY { ramall(rwx) : o = 0xffbf20, l = 0x004000 /* 16KB */ ram(rwx) : o = 0xffc020, l = 0x003f00 stack(rw) : o = 0xffff00, l = 0x000000 /* end of RAM */ }
ram部分がRAM上の領域を示しますが、ここはRAM領域の先頭の0xffbf20ではなく、ELFヘッダとプログラムヘッダテーブル分の余裕を見て256バイト空きを作る必要があるという点です。
最初、空きを作る意味がよくわからなかったので試しに
ram(rwx) : o = 0xffbf20, l = 0x003f00
に変更して、readelfで確認してみたところ
セクションヘッダ: [番] 名前 タイプ アドレス Off サイズ ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00ffbf20 000074 000498 00 AX 0 0 2 [ 2] .rodata PROGBITS 00ffc3b8 00050c 000038 01 AMS 0 0 1 [ 3] .data PROGBITS 00ffc3f0 000544 00000c 00 WA 0 0 4 [ 4] .bss NOBITS 00ffc3fc 000550 000020 00 WA 0 0 1 [ 5] .shstrtab STRTAB 00000000 000550 000034 00 0 0 1 [ 6] .symtab SYMTAB 00000000 0006c4 000570 10 7 57 4 [ 7] .strtab STRTAB 00000000 000c34 000232 00 0 0 1 プログラムヘッダ: タイプ オフセット 仮想Addr 物理Addr FileSiz MemSiz Flg Align LOAD 0x000000 0x00ffbeac 0x00ffbeac 0x00544 0x00544 R E 0x1 LOAD 0x000544 0x00ffc3f0 0x00ffc3f0 0x0000c 0x0002c RW 0x1
となり、.textセクションの先頭アドレスが0xffbf20となります。
ただ.textセクションのさらに前方にELFヘッダ部分などもコピーされるようで、プログラムヘッダの物理Addrが0x00ffbeacと、RAMの先頭アドレス0xffbf20より手前になってしまってます。
セクションのコピーはこの物理Addrが示すアドレスを先頭に行うため、このまま実行するとRAM領域外にデータを書き込むことになりNGです。ちなみに試しに実行してみるとリセットされました。
ram(rwx) : o = 0xffc020
に戻すと、こんな感じでファイルを実行できるようになります。
試しにffbfac番地以降をダンプする処理を実行してみましたが、ELFヘッダのマジックナンバーがメモリ上に記録されており、ELFヘッダもメモリに読み込まれていることがわかります。
とりあえずプログラムのブートローダーが完成し、色々なプログラムを手軽に動作確認できるようになりました。