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 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. 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. 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 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 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 ramlemezkép formátumának ismerete nélkül. 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 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 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. 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 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 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 mind, mintha egy monolitikus 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. 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 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 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 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 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. 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. 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 ELFDATA2LSB 1 /* 2's complement, little endian */
#define PT_LOAD 1 /* Loadable program segment */ #define PT_LOAD 1 /* Loadable program segment */
#define EM_X86_64 62 /* AMD x86-64 architecture */ #define EM_X86_64 62 /* AMD x86-64 architecture */
#define SHT_SYMTAB 2 /* Symbol table */
#define SHT_STRTAB 3 /* String table */
typedef struct typedef struct
{ {
@ -91,6 +93,30 @@ typedef struct
UINT64 p_align; /* Segment alignment */ UINT64 p_align; /* Segment alignment */
} Elf64_Phdr; } 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 ***/ /*** PE32+ defines and structs ***/
#define MZ_MAGIC 0x5a4d /* "MZ" */ #define MZ_MAGIC 0x5a4d /* "MZ" */
#define PE_MAGIC 0x00004550 /* "PE\0\0" */ #define PE_MAGIC 0x00004550 /* "PE\0\0" */
@ -109,7 +135,7 @@ typedef struct {
UINT16 sections; /* number of sections */ UINT16 sections; /* number of sections */
UINT32 timestamp; /* time_t */ UINT32 timestamp; /* time_t */
UINT32 sym_table; /* symbol table offset */ 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 opt_hdr_size; /* size of optional header */
UINT16 flags; /* flags */ UINT16 flags; /* flags */
UINT16 file_type; /* file type, PE32PLUS magic */ UINT16 file_type; /* file type, PE32PLUS magic */
@ -122,6 +148,16 @@ typedef struct {
INT32 code_base; /* relative code addr in ram */ INT32 code_base; /* relative code addr in ram */
} pe_hdr; } 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 ***/ /*** EFI defines and structs ***/
struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
struct EFI_FILE_PROTOCOL; struct EFI_FILE_PROTOCOL;
@ -268,6 +304,9 @@ file_t core; // kernel file descriptor
BOOTBOOT *bootboot; // the BOOTBOOT structure BOOTBOOT *bootboot; // the BOOTBOOT structure
UINT64 *paging; // paging table for MMU UINT64 *paging; // paging table for MMU
UINT64 entrypoint; // kernel entry point 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_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE RootDir;
EFI_FILE_PROTOCOL *Root; EFI_FILE_PROTOCOL *Root;
@ -1152,7 +1191,7 @@ LoadCore()
DBG(L" * Parsing ELF64 @%lx\n",core.ptr); DBG(L" * Parsing ELF64 @%lx\n",core.ptr);
Elf64_Phdr *phdr=(Elf64_Phdr *)((UINT8 *)ehdr+ehdr->e_phoff); Elf64_Phdr *phdr=(Elf64_Phdr *)((UINT8 *)ehdr+ehdr->e_phoff);
for(i=0;i<ehdr->e_phnum;i++){ 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 // hack to keep symtab and strtab for shared libraries
core.size = phdr->p_filesz + (ehdr->e_type==3?0x4000:0); core.size = phdr->p_filesz + (ehdr->e_type==3?0x4000:0);
ptr = (UINT8*)ehdr + phdr->p_offset; ptr = (UINT8*)ehdr + phdr->p_offset;
@ -1162,17 +1201,47 @@ LoadCore()
} }
phdr=(Elf64_Phdr *)((UINT8 *)phdr+ehdr->e_phentsize); 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 && } 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 && pehdr->machine == IMAGE_FILE_MACHINE_AMD64 && pehdr->file_type == PE_OPT_MAGIC_PE32PLUS &&
(INT64)pehdr->code_base>>48==0xffff) { (pehdr->code_base & 0xC0000000)) {
// Parse PE32+ // Parse PE32+
DBG(L" * Parsing PE32+ @%lx\n",core.ptr); DBG(L" * Parsing PE32+ @%lx\n",core.ptr);
core.size = (pehdr->entry_point-pehdr->code_base) + pehdr->text_size + pehdr->data_size; core.size = (pehdr->entry_point-pehdr->code_base) + pehdr->text_size + pehdr->data_size;
ptr = core.ptr; ptr = core.ptr;
bss = pehdr->bss_size; bss = pehdr->bss_size;
entrypoint = (INT64)pehdr->entry_point; 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) }
}
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"); return report(EFI_LOAD_ERROR,L"Kernel is not a valid executable");
// create core segment // create core segment
uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, uefi_call_wrapper(BS->AllocatePages, 4, 0, 2,
@ -1183,6 +1252,9 @@ LoadCore()
if(bss>0) if(bss>0)
ZeroMem((void*)core.ptr + core.size, bss); ZeroMem((void*)core.ptr + core.size, bss);
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); DBG(L" * Entry point @%lx, text @%lx %d bytes\n",entrypoint, core.ptr, core.size);
core.size = ((core.size+PAGESIZE-1)/PAGESIZE)*PAGESIZE; core.size = ((core.size+PAGESIZE-1)/PAGESIZE)*PAGESIZE;
return EFI_SUCCESS; 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"); return report(status, L"GOP failed, no framebuffer");
// collect information on system // collect information on system
bootboot->protocol=PROTOCOL_STATIC | LOADER_UEFI; bootboot->protocol=PROTOCOL_DYNAMIC | LOADER_UEFI;
bootboot->size=128; bootboot->size=128;
bootboot->numcores=1; bootboot->numcores=1;
CopyMem((void *)&(bootboot->initrd_ptr),&initrd.ptr,8); CopyMem((void *)&(bootboot->initrd_ptr),&initrd.ptr,8);