Best strategy to load a kernel elf binary to high vmem?
Posted: Fri Jan 08, 2016 2:15 pm
Hi everyone,
I have a question regarding the best way of loading a kernel binary.
Currently I'm using an identity-mapped (base) kernel which sits inside (now over 320!) the reserved sectors of my FAT16 boot partition. This blob is then loaded by the bootsector code to 0x7e00 and above, which was acceptable while the kernel was small, but now I'm running out of "early memory", i.e. memory that I'm using for an "fixed allocator" which returns identity mapped pages from below 1MB. Also I'm not fond of abusing the FAT filesystem's reserved sector feature as a dump for binary data. To show you the mess, here is the linker script for generating the FAT16 image:
Symbols are added by automatically generating a .gdbinit file which contains the needed "add-symbol-file *.o ofs -s .abc sofs1" commands for gdb to understand the binary blob (works suprisingly well for debugging):
Later inside the C code I'm first loading a nm-style symbol table, followed by parsing it and then loading the module files (relocatable ELF output, practically the output of gcc -c), performing the relocations on them and then everything is set up.
The main incentive for staying with this rather arcane system is that I really don't want to duplicate the mmgr code, containing paging, PAE, ... for loading a kernel image into virtual addresses.
What are possible solutions for this? Compiling mmgr.c as position independent code? With this I could use it inside the bootloader and then relocate it into the kernel high-vmem. Other approaches?
I have a question regarding the best way of loading a kernel binary.
Currently I'm using an identity-mapped (base) kernel which sits inside (now over 320!) the reserved sectors of my FAT16 boot partition. This blob is then loaded by the bootsector code to 0x7e00 and above, which was acceptable while the kernel was small, but now I'm running out of "early memory", i.e. memory that I'm using for an "fixed allocator" which returns identity mapped pages from below 1MB. Also I'm not fond of abusing the FAT filesystem's reserved sector feature as a dump for binary data. To show you the mess, here is the linker script for generating the FAT16 image:
Code: Select all
OUTPUT_FORMAT(binary)
/*STARTUP(prog.o)*/
SECTIONS
{
. = 0x7c00 ;
bootsect :
{
prog.o (.bstext)
prog.o (.bsdata)
endbootsect = . ;
FILL(0x00)
/* partition table */
/* . = 0x1be ;
BYTE(0x80) *//* bootable */
/* BYTE(0x00) *//* head 0 */
/* BYTE(0x02) *//* sector 2 LBA 1 */
/* BYTE(0x00) *//* cylinder 0 */
/* BYTE(0x04) *//* type - fat16 */
/* last sector 5760 CHS (18 per side) last is before cyl 160 */
/* BYTE(0x01)
BYTE(0x11)*/ /* 17 */
/* BYTE(0x9f)*/
/* start sector lba */
/* LONG(0x00000001)*/
/* end sector */
/* LONG(5760)*/ /* minus a? */
. = 0x1fe ;
SHORT(0xaa55)
}
. = 0x7e00 ;
rest :
{
rest = . ;
idt.o (.idt)
/*. = 0x1fe ;*/
/*SHORT(0x1111)*/
. = 0x200 ;
idt.o (.trampo)
. = 0x3fe ;
idt.o (.idtext)
FILL(0x00)
. = 0x7fe ;
SHORT(0x1d35)
prog.o (.bsrmio)
vga.o (.vga)
. = 0xdfe ;
SHORT(0xf1f0)
endbase = . ;
*(.text)
*(.rodata*)
. = ALIGN(0x1000) ;
endtext = . ;
*(.data)
*(.bss)
*(COMMON)
FILL(0x00)
. = 0x39dfe ;
SHORT(0x789a)
endrest = . ;
}
basesize = (endbase - rest) / 0x200 + 1;
restsize = (endrest - rest) / 0x200 + 1;
. = 0x47c00 ; /*(0x28000=512*512)*/
fat16 :
{
/* media descriptor & 1 for sector 1 */
SHORT(0xfff0)
SHORT(0xffff) /* mandatory second entry */
/* first test file */
SHORT(0x0003)
SHORT(0x0004)
SHORT(0xffff)
INCLUDE ifats.ld
/* free clusters (2880-2*11-512) */
FILL(0x00)
. = 0x2c00 ; /* 11 sectors per fat */
}
fat16b : /* la meme chose */
{
SHORT(0xfff0)
SHORT(0xffff)
SHORT(0x0003)
SHORT(0x0004)
SHORT(0xffff)
INCLUDE ifats.ld
FILL(0x00)
. = 0x2c00 ;
}
fat16f :
{
prog.o (.fat16dir)
INCLUDE ifdirs.ld
FILL(0x00)
. = 0x1c00 ; /* 224*32 */
/* fat16 files */
prog.o (.fat16files)
FILL(0x00)
. = ALIGN(0x200) ;
INCLUDE ifils.ld
}
}
Code: Select all
add-symbol-file apic.o 0x0000000000011f01 -s .bss 0x000000000002d5ac -s .data 0x000000000002d0a0 -s .rodata 0x0000000000028a68
add-symbol-file early.o 0x0000000000008c00 -s .bss 0x000000000002d3e4 -s .data 0x000000000002d000 -s .rodata 0x0000000000026fc8
add-symbol-file framebuffer.o 0x000000000000abcc -s .bss 0x000000000002d3f0 -s .data 0x000000000002d020 -s .rodata 0x0000000000027648
add-symbol-file i386-stub.o 0x000000000001622b -s .bss 0x000000000002d960 -s .data 0x000000000002d16c -s .rodata 0x000000000002994c
add-symbol-file idt.o 0x0000000000008200 -s .idt 0x0000000000007e00 -s .idtext 0x0000000000008200 -s .trampo 0x0000000000008000
add-symbol-file kbd.o 0x00000000000177b3 -s .bss 0x000000000002dcb8 -s .data 0x000000000002d180 -s .rodata 0x0000000000029b18
add-symbol-file kernel.o 0x000000000000daa1 -s .bss 0x000000000002d400 -s .data 0x000000000002d060 -s .rodata 0x0000000000027880
add-symbol-file kio.o 0x00000000000183db -s .bss 0x000000000002dcc4 -s .data 0x000000000002d2e0 -s .rodata 0x0000000000029bc4
add-symbol-file libc.o 0x000000000001a7e9 -s .bss 0x000000000002dce0 -s .data 0x000000000002d340 -s .rodata 0x0000000000029ca0
add-symbol-file mmgr.o 0x000000000001bdc3 -s .bss 0x000000000002dd80 -s .data 0x000000000002d37c -s .rodata 0x0000000000029d34
add-symbol-file module.o 0x0000000000024416 -s .bss 0x000000000002de00 -s .data 0x000000000002d3c0 -s .rodata 0x000000000002b358
add-symbol-file prog.o 0x0000000000007c00 -s .bsdata 0x0000000000007dc5 -s .bsrmio 0x0000000000008600 -s .bstext 0x0000000000007c00
add-symbol-file smp.o 0x0000000000012a9c -s .bss 0x000000000002d5b0 -s .data 0x000000000002d0b0 -s .rodata 0x0000000000028d7c
add-symbol-file tasks.o 0x0000000000013db4 -s .bss 0x000000000002d5e0 -s .data 0x000000000002d0c0 -s .rodata 0x000000000002944c
add-symbol-file vga.o 0x0000000000008b84 -s .vga 0x0000000000008b84
The main incentive for staying with this rather arcane system is that I really don't want to duplicate the mmgr code, containing paging, PAE, ... for loading a kernel image into virtual addresses.
What are possible solutions for this? Compiling mmgr.c as position independent code? With this I could use it inside the bootloader and then relocate it into the kernel high-vmem. Other approaches?