udos-0.0.2 向け パッチについて 0. 前置き このパッチは、今井が、以下の目的で作成しました: - linux や Mac OS X 等でも udos のビルドを可能に - エミュレータ QEmu (http://fabrice.bellard.free.fr/qemu/)  で動作するように 保証はできませんが、私の環境 (64bit linux や Mac OS X 10.3/10.4) では これで動きました。 1. 使用方法 1-1. パッチを当てる $ tar zxvf udos-0.0.2.tgz $ cd udos-0.0.2 $ patch -p1 < udos-0.0.2_unixbuild.patch 等として、パッチを当てて下さい。 1-2. Makefile の編集 $ vi Makefile で、 Makefile 中の以下の項目を設定してください。 しかし、udos と同じ環境 (x86系のlinux等) でビルドする場合は、 空欄で構いません。 HOSTGCC= TARGETGCC= LIBBFD_LDPATH= LIBBFD_INCLUDEPATH= 1-3. ビルド & 実行 $ make で、問題なくビルドできれば、 $ make bochs や $ qemu -fda floppya.img で udos を動作させることができます。 2. 修正点 2-1. パッチによるソースの修正点について === udos本体のバグ?の修正 === main.c : asm volatile ("movl %0, %%esp"::"r"(KERNEL_STACK_ADDR)); + asm volatile ("movl %esp, %ebp"); esp を新しいスタックフレームに設定しているのに、 対で扱う ebp を設定していないので修正。 paging.c : asm volatile ("movl %cr0, %eax\n" - "orl 0x80000000, %eax\n" + "orl $0x80000000, %eax\n" "movl %eax, %cr0"); or 演算で、CR1 の 最上位ビットを立てる操作の途中の部分ですが、 これでは 0x80000000 番地の中身と eax の or になってしまいます。 即値になるよう $ を付けました。 fd.c : - assert (st0 == (0xC0 | (uint8_t)i)); qemu では、この assertion で失敗する為、外しました。 4度、 SENSE INTERRUPT STATUS を行う場所ですが、 qemu はここで 4回とも 0x20 を 返してきます。 参考として、 FreeBSD や Linux の FDC 部分 http://fxr.watson.org/fxr/source/dev/fdc/fdc.c#L769 を見ると、 FDC リセット時の SENSE INTERRUPT STATUS の戻り値は 無視しています。 === exe2bin.exe の 修正 ==== exe2bin.c : - enum { MAX_SECTION = 5 }; + enum { MAX_SECTION = 6 }; asection *section [MAX_SECTION]; - char *section_name [MAX_SECTION] = {".text", ".data", ".rdata", ".idata", ".bss"}; + char *section_name [MAX_SECTION] = {".text", ".data", ".rodata", ".rdata", ".idata", ".bss"}; elf32-i386 では、読み込み専用セクションの名前は .rdata ではなく .rodata です。 このため、linux 等では、文字列リテラル等の 読み取り専用セクションの抽出に失敗 していました。 (他の修正はエラーメッセージに関するものです。) これを修正しました。 === boot32.S 内の ページエントリ関係 === boot32.S : -.data - .globl _kernel_page_dir - .org 0x1000 -_kernel_page_dir: # used in paging.c - .fill 4096, 1, 0 # 4KB : : このデータセクションが、実際のカーネルに反映されない為、削除しました。 (kernel.dis を読むと、_kernel_page_dir への参照が0x1000ではなく 0x10A80 等に なってしまう) boot32.h : -extern uint32_t kernel_page_dir [1024]; -extern uint32_t kernel_page_tbl_IM [1024]; +#define kernel_page_dir ((uint32_t*)0x1000) +#define kernel_page_tbl_IM ((uint32_t*)0x2000) externの外部参照を、マクロに変更しました。 cpu.c : - kernel_tss.cr3 = (uint32_t) &kernel_page_dir; /* defined in boot32.S */ + kernel_tss.cr3 = (uint32_t) kernel_page_dir; /* defined in boot32.S */ 上の修正に伴い、配列の頭のアドレスのために付いていた & を外しました。 2-2. Makefileの修正点 Makefile : +HOSTGCC= +TARGETGCC= +LIBBFD_LDPATH= +LIBBFD_INCLUDEPATH= 変数を追加しました。 kernel/ や user/ にも伝播し、以下のように使われます: - HOSTGCC ... exe2bin.exe と fat12.exe をビルドするためのgcc - TARGETGCC ... udos本体をビルドする為のgcc  それぞれ、 HOSTGCC=/usr/bin/ , TARGETGCC=/home/sydney/usr/bin/i368-elf-  等を意図しています。 - LIBBFD_LDPATH と LIBBFD_INCLUDEPATH ...  exe2bin.exeをビルドする時に付けるパラメータです。  私が使っている Mac OSX の libbfd では、 kernel.exe 等の elf32-i386 形式を  扱えない為、 このオプションで、別の libbfd を指定します。  例えば、 libbfd を /home/sydney/usr にインストールした場合、  それぞれ -L/home/sydney/usr/lib , -I/home/sydney/usr/include などを  意図しています。 kernel/Makefile, user/Makefile : %.o: %.c - gcc $(WARNING) -DKERNEL -c -nostdinc $< + $(TARGETGCC)gcc -fleading-underscore $(WARNING) -DKERNEL -c -nostdinc $< linux では、エクスポートされるシンボルには、デフォルトでアンダースコアが 付かないため、強制的に付けるようにしました。 3. 既知の問題点と解決策 - exe2bin.exe の ビルド時に -lintl が無いとエラーがでる環境がある ==> -lintl を削除してください。 - exe2bin.exe が Mac OS X では正しく動作しない  ==>  elf32-i386の形式に対応した libbfd をインストールしてください。  また前述した Makefile の修正も行って下さい。  libbfd は、 binutilsパッケージに含まれています。  libbfd の configure に与えるオプション --enable-targets=all で、  elf32-i386 の形式を含めて扱えるようになります。  また、このままでは "File format is ambiguous" とエラーが出ますので、  exe2bin.c の 86行目を - if(!(abfd = bfd_openr (argv [1], "default"))) { + if(!(abfd = bfd_openr (argv [1], "elf32-i386"))) {  のようにして、明示的に フォーマットを指定してください。 以上。 ---- 名古屋大学大学院 情報科学研究科 情報システム学専攻 阿草研究室 D1 今井 敬吾 (IMAI Keigo) mailto:sydney@agusa.i.is.nagoya-u.ac.jp