2012年11月5日 星期一

將檔案系統塞到 elf 執行檔

simple os 的 romfs binary 檔案, 原本是由 kernel loader 載入, 不過這樣需要載入 p_kernel.elf 和 rom.fs 兩個檔案, 不太方便。

聽了 jserv 的進階嵌入式系統開發與實作之後, 知道可以將 rom.fs 合併到 elf 執行檔中。

課程是以 arm 為平台, 我花的功夫則是把 objcopy 的 x86 平台參數找出來。

objcopy -I binary -O elf32-i386 -B i386 --prefix-sections '.romfs' rom.fs test-romfs.o

這是把 rom.fs 放到 .romfs section 產生 obj file, 再 link test-romfs.o 到 elf 執行檔即可。這招程式設計師的自我修養--連結、載入、程式庫就有提過, 其中範例是把一個 jpg 圖檔塞入 elf, 不過我真的忘了。

增加如下的 linker script:

. = ALIGN(32);
__romfs_start__ =.;
.romfs.data :
{
*(.romfs.data)
}
__romfs_end__ = .;

linker script 很難理解的原因在於除了其怪異的語法之外, 還需要對 elf 檔有一定的理解, 而要對 elf 檔有一定的理解, 還需要能理解 elf 在記憶體中的佈局, 有了想像中的畫面, 才能通盤理解 linker script, 也才能體會其強大。若只看 gnu ld manual, 其實很難理解 linker script。我則是透過閱讀幾本書加上實作, 才達到略懂的地步。

在 C 語言裡頭, 這樣的宣告就可以抓到 romfs 在記憶體的開頭位址:

extern int __romfs_start__, __romfs_end__;
int romfs_addr = &__romfs_start__

然後開心的把 p_kernel.elf 載入到 ram, 不用辛苦的載入兩次, 載入兩次雖然不難, 但也是有些小細節要注意, 能避免則避免, 我踩到好幾次地雷了。

參考 dos memory layout 之後, 我思考重新擺放 simple kernel, ramdisk 的位址, 目前在真實模式下使用 bios 0x13 載入檔案到記憶體, 進入保護模式後, 我會把 p_kernel.elf (include ramdisk) copy 到 0x100000 (真實模式達不到的位址), 這是 p_kernel.elf 的程式進入點。

程式設計師的自我修養--連結、載入、程式庫 p68 提到一個簡單的方法:

romfs.fs 為 romfs 的影像檔 (image)
descent@debian-vm:simple_os$ objcopy -I binary -O elf32-i386 -B i386 romfs.fs test-romfs.o 
descent@debian-vm:simple_os$ objdump -ht test-romfs.o 

test-romfs.o:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .romfs.data   00000400  00000000  00000000  00000034  2**0
                  CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
00000000 l    d  .romfs.data 00000000 .romfs.data
00000000 g       .romfs.data 00000000 _binary_rom_fs_start
00000400 g       .romfs.data 00000000 _binary_rom_fs_end
00000400 g       *ABS* 00000000 _binary_rom_fs_size

把 _binary_rom_fs_start, _binary_rom_fs_end, _binary_rom_fs_size 直接拿來用就好, 不用改 linker script。

PC-DOS and MS-DOS memory map

high memory
segment
offset
size
contents
0000h
0000h
1024
interrupt vector table
0400h
172
BIOS communication area
04ACh
68
reserved by IBM
04F0h
16
user communication area
0500h
256
DOS communication area
0600h
varies
operating system:
IBMBIO.COM (DOS interface to the BIOS)
IBMDOS.COM (DOS interrupt handlers and interrupt 21h service routines
DOS buffers, control areas, and device drivers
COMMAND.COM (resident portion), interrupt 22h, 23h, and 24h handlers, routine to reload transient portion of COMMAND.COM
memory-resident utilities
transient applications
transient portion of COMMAND.COM
9000h
FFFFh
highest address of user memory
A000h
0000h
128K
reserved area of ROM
A000h
0000h
beginning of area used by EGA and PS/2 video systems
B000h
0000h
4000
monochrome video memory
0800h
16K
color graphics adaptor (CGA) video memory
C000h
0000h
192K
ROM expansion and control area
8000h
ROM for hard disk
D000h
ROM expansion and control area
E000h
ROM expansion and control area
F000h
0000h
16K
reserved ROM
4000h
40K
base system ROM, ROM BASIC
E000h
8K
ROM BIOS
low memory

ref:
Linux中使用C語言載入data object 檔案資料

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。