1
0
Fork 0
mirror of https://gitlab.com/bztsrc/bootboot.git synced 2023-02-13 20:54:32 -05:00

Parse symbols to get virtual addresses

This commit is contained in:
bzt 2020-06-15 17:11:59 +02:00
parent 619c2f9135
commit 4aac0746e4
5 changed files with 90 additions and 18 deletions

View file

@ -16,7 +16,7 @@ Előre lefordított binárisok mellékelve, egyből használhatók.
4. *mykernel* egy példa BOOTBOOT [kompatíbilis kernel](https://gitlab.com/bztsrc/bootboot/tree/master/mykernel) C-ben írva, ami vonalakat húz meg színes dobozokat rajzol
Vedd figyelembe, hogy a referencia implementációk nem támogatják a teljes 2-es protokollt,
Vedd figyelembe, hogy a referencia implementációk nem támogatják a teljes 2-es protokollt (kivéve az UEFI változatot),
csak statikus memórialeképezéseket kezelnek, ami az 1-es protokoll szintnek felel meg.
Gyors kipróbáláshoz találsz bootolható képfájlokat az [images](https://gitlab.com/bztsrc/bootboot/tree/master/images) mappában.
@ -24,11 +24,11 @@ Gyors kipróbáláshoz találsz bootolható képfájlokat az [images](https://gi
BOOTBOOT Protokoll
==================
Célközönség
-----------
Lényege
-------
A protokoll definiálja, hogyan kell betölteni ELF64 vagy PE32+ futtathatókat egy induló ramlemezről tisztán
64 bites módban, mindenféle konfiguráció vagy akár a ramlemezkép formátumának ismerete nélkül.
A protokoll definiálja, hogyan kell betölteni ELF64 vagy PE32+ futtathatókat egy induló memórialemezről tisztán
64 bites módban, mindenféle konfiguráció vagy akár a memórialemezkép formátumának ismerete nélkül.
A [BIOS](https://gitlab.com/bztsrc/bootboot/tree/master/x86_64-bios)-t támogató gépeken ugyanaz a betöltő működik
Multiboottal, láncbetöltéssel MBR, VBR (GPT hibrid indítás) és CDROM indító szektorból, vagy BIOS bővítő ROM-ból
@ -40,13 +40,13 @@ A [Raspberry Pi 3+](https://gitlab.com/bztsrc/bootboot/tree/master/aarch64-rpi)
tölti be kernel8.img néven az SD kártya első partíciójáról.
A különbség más betöltő protokollokhoz képest a rugalmasság és a hordozhatóság; a tisztán 64 bit támogatás; és hogy
a BOOTBOOT a kernel-t a ramlemezképből tölti be. Ez ideális hobbi OS-ek és mikrokernelek számára. Ez biztosítja, hogy
a kerneled felbontható több fájlra, mégis megadja azt az előnyt, hogy egyszerre tölti be mind, mintha egy monolitikus
a BOOTBOOT a kernel-t a memórialemezképből tölti be. Ez ideális hobbi OS-ek és mikrokernelek számára. Ez biztosítja, hogy
a kerneled felbontható több fájlra, mégis megadja azt az előnyt, hogy egyszerre tölti be mindet, mintha egy monolitikus
kernel lenne. Ráadásul mindehhez a saját fájl rendszeredet is használhatod.
Megjegyzés: a BOOTBOOT nem egy boot menedzser, hanem egy boot protokoll. Ha interaktív indítómenüt szeretnél, akkor
azt a BOOTBOOT kompatíbilis betöltő *elé* kell integrálnod. Például a GRUB lánctöltheti a boot.bin-t (vagy Multiboot
"kernel"-ként a bootboot.bin-t és modulként a ramlemezt) vagy a bootboot.efi hozzáadható az UEFI Boot menedzser menüjéhez.
"kernel"-ként a bootboot.bin-t és modulként a memórialemezt) vagy a bootboot.efi hozzáadható az UEFI Boot menedzser menüjéhez.
Licensz
-------

View file

@ -16,7 +16,7 @@ I provide pre-compiled images ready for use.
4. *mykernel* an example BOOTBOOT [compatible kernel](https://gitlab.com/bztsrc/bootboot/tree/master/mykernel) in C which draws lines and boxes
Please note that the reference implementations do not support the full protocol at level 2,
Please note that the reference implementations do not support the full protocol at level 2 (except the UEFI version),
they only handle static mappings which makes them level 1 loaders.
For quick test, you can find example bootable disk [images](https://gitlab.com/bztsrc/bootboot/tree/master/images) too.

Binary file not shown.

Binary file not shown.

View file

@ -60,6 +60,8 @@
#define ELFDATA2LSB 1 /* 2's complement, little endian */
#define PT_LOAD 1 /* Loadable program segment */
#define EM_X86_64 62 /* AMD x86-64 architecture */
#define SHT_SYMTAB 2 /* Symbol table */
#define SHT_STRTAB 3 /* String table */
typedef struct
{
@ -91,6 +93,30 @@ typedef struct
UINT64 p_align; /* Segment alignment */
} Elf64_Phdr;
typedef struct
{
UINT32 sh_name; /* Section name (string tbl index) */
UINT32 sh_type; /* Section type */
UINT64 sh_flags; /* Section flags */
UINT64 sh_addr; /* Section virtual addr at execution */
UINT64 sh_offset; /* Section file offset */
UINT64 sh_size; /* Section size in bytes */
UINT32 sh_link; /* Link to another section */
UINT32 sh_info; /* Additional section information */
UINT64 sh_addralign; /* Section alignment */
UINT64 sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
typedef struct
{
UINT32 st_name; /* Symbol name (string tbl index) */
UINT8 st_info; /* Symbol type and binding */
UINT8 st_other; /* Symbol visibility */
UINT16 st_shndx; /* Section index */
UINT64 st_value; /* Symbol value */
UINT64 st_size; /* Symbol size */
} Elf64_Sym;
/*** PE32+ defines and structs ***/
#define MZ_MAGIC 0x5a4d /* "MZ" */
#define PE_MAGIC 0x00004550 /* "PE\0\0" */
@ -109,7 +135,7 @@ typedef struct {
UINT16 sections; /* number of sections */
UINT32 timestamp; /* time_t */
UINT32 sym_table; /* symbol table offset */
UINT32 symbols; /* number of symbols */
INT32 numsym; /* number of symbols */
UINT16 opt_hdr_size; /* size of optional header */
UINT16 flags; /* flags */
UINT16 file_type; /* file type, PE32PLUS magic */
@ -118,10 +144,20 @@ typedef struct {
UINT32 text_size; /* size of text section(s) */
UINT32 data_size; /* size of data section(s) */
UINT32 bss_size; /* size of bss section(s) */
INT32 entry_point; /* file offset of entry point */
INT32 code_base; /* relative code addr in ram */
INT32 entry_point; /* file offset of entry point */
INT32 code_base; /* relative code addr in ram */
} pe_hdr;
typedef struct {
UINT32 iszero; /* if this is not zero, then iszero+nameoffs gives UTF-8 string */
UINT32 nameoffs;
INT32 value; /* value of the symbol */
UINT16 section; /* section it belongs to */
UINT16 type; /* symbol type */
UINT8 storclass; /* storage class */
UINT8 auxsyms; /* number of pe_sym records following */
} pe_sym;
/*** EFI defines and structs ***/
struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
struct EFI_FILE_PROTOCOL;
@ -268,6 +304,9 @@ file_t core; // kernel file descriptor
BOOTBOOT *bootboot; // the BOOTBOOT structure
UINT64 *paging; // paging table for MMU
UINT64 entrypoint; // kernel entry point
UINT64 fb_addr = 0xfffffffffc000000; // frame buffer virtual address
UINT64 bb_addr = 0xffffffffffe00000; // bootboot struct virtual address
UINT64 env_addr= 0xffffffffffe01000; // environment string virtual address
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
EFI_FILE_HANDLE RootDir;
EFI_FILE_PROTOCOL *Root;
@ -1152,7 +1191,7 @@ LoadCore()
DBG(L" * Parsing ELF64 @%lx\n",core.ptr);
Elf64_Phdr *phdr=(Elf64_Phdr *)((UINT8 *)ehdr+ehdr->e_phoff);
for(i=0;i<ehdr->e_phnum;i++){
if(phdr->p_type==PT_LOAD && phdr->p_vaddr>>48==0xffff) {
if(phdr->p_type==PT_LOAD && (phdr->p_vaddr >> 30) == 0x3FFFFFFFF) {
// hack to keep symtab and strtab for shared libraries
core.size = phdr->p_filesz + (ehdr->e_type==3?0x4000:0);
ptr = (UINT8*)ehdr + phdr->p_offset;
@ -1162,18 +1201,48 @@ LoadCore()
}
phdr=(Elf64_Phdr *)((UINT8 *)phdr+ehdr->e_phentsize);
}
if(ehdr->e_shoff > 0) {
Elf64_Shdr *shdr=(Elf64_Shdr *)((UINT8 *)ehdr + ehdr->e_shoff);
Elf64_Sym *sym = NULL, *s;
char *strtable = NULL;
UINT32 strsz = 0, syment = 0;
for(i = 0; i < ehdr->e_shnum; i++){
if(shdr->sh_type == SHT_SYMTAB) { sym=(Elf64_Sym *)((UINT8*)ehdr+shdr->sh_offset); syment=shdr->sh_entsize; }
if(shdr->sh_type == SHT_STRTAB) { strtable = (char *)ehdr + shdr->sh_offset; strsz = shdr->sh_size; }
shdr = (Elf64_Shdr *)((UINT8 *)shdr + ehdr->e_shentsize);
}
if(strtable && strsz > 0 && sym && syment > 0)
for(s = sym, i = 0; i<(strtable-(char*)sym)/syment && s->st_name < strsz; i++, s++) {
if(!CompareMem(strtable + s->st_name, "bootboot", 9)) bb_addr = s->st_value;
if(!CompareMem(strtable + s->st_name, "environment", 12)) env_addr = s->st_value;
if(!CompareMem(strtable + s->st_name, "fb", 3)) fb_addr = s->st_value;
}
}
} else if(((mz_hdr*)(core.ptr))->magic==MZ_MAGIC && ((mz_hdr*)(core.ptr))->peaddr<65536 && pehdr->magic == PE_MAGIC &&
pehdr->machine == IMAGE_FILE_MACHINE_AMD64 && pehdr->file_type == PE_OPT_MAGIC_PE32PLUS &&
(INT64)pehdr->code_base>>48==0xffff) {
//Parse PE32+
(pehdr->code_base & 0xC0000000)) {
// Parse PE32+
DBG(L" * Parsing PE32+ @%lx\n",core.ptr);
core.size = (pehdr->entry_point-pehdr->code_base) + pehdr->text_size + pehdr->data_size;
ptr = core.ptr;
bss = pehdr->bss_size;
entrypoint = (INT64)pehdr->entry_point;
if(pehdr->sym_table > 0 && pehdr->numsym > 0) {
pe_sym *s;
char *strtable = (char *)pehdr + pehdr->sym_table + pehdr->numsym * 18 + 4, *name;
for(i = 0; i < pehdr->numsym; i++) {
s = (pe_sym*)((UINT8 *)pehdr + pehdr->sym_table + i * 18);
name = !s->iszero ? (char*)&s->iszero : strtable + s->nameoffs;
if(!CompareMem(name, "bootboot", 9)) bb_addr = (INT64)s->value;
if(!CompareMem(name, "environment", 12)) env_addr = (INT64)s->value;
if(!CompareMem(name, "fb", 3)) fb_addr = (INT64)s->value;
i += s->auxsyms;
}
}
}
if(ptr==NULL || core.size<2 || entrypoint==0)
return report(EFI_LOAD_ERROR,L"Kernel is not a valid executable");
if(ptr==NULL || core.size<2 || entrypoint==0 || (bb_addr>>30)!=0x3FFFFFFFF || (env_addr>>30)!=0x3FFFFFFFF ||
(fb_addr>>30)!=0x3FFFFFFFF || (fb_addr & ~(1024*1024*2-1)))
return report(EFI_LOAD_ERROR,L"Kernel is not a valid executable");
// create core segment
uefi_call_wrapper(BS->AllocatePages, 4, 0, 2,
(core.size + bss + PAGESIZE-1)/PAGESIZE, (EFI_PHYSICAL_ADDRESS*)&core.ptr);
@ -1183,6 +1252,9 @@ LoadCore()
if(bss>0)
ZeroMem((void*)core.ptr + core.size, bss);
core.size += bss;
DBG(L" * fb @%lx\n", fb_addr);
DBG(L" * bootboot @%lx\n", bb_addr);
DBG(L" * environment @%lx\n", env_addr);
DBG(L" * Entry point @%lx, text @%lx %d bytes\n",entrypoint, core.ptr, core.size);
core.size = ((core.size+PAGESIZE-1)/PAGESIZE)*PAGESIZE;
return EFI_SUCCESS;
@ -1541,7 +1613,7 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
return report(status, L"GOP failed, no framebuffer");
// collect information on system
bootboot->protocol=PROTOCOL_STATIC | LOADER_UEFI;
bootboot->protocol=PROTOCOL_DYNAMIC | LOADER_UEFI;
bootboot->size=128;
bootboot->numcores=1;
CopyMem((void *)&(bootboot->initrd_ptr),&initrd.ptr,8);