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

Added protocol level 2 to reference implementations

This commit is contained in:
bzt 2020-06-16 03:35:19 +02:00
parent 69ae4d7f22
commit 3fa776a803
24 changed files with 386 additions and 215 deletions

View file

@ -5,19 +5,19 @@ Előre lefordított binárisok mellékelve, egyből használhatók.
1. *x86_64-efi* a preferált indítási mód x86_64-en.
Szabvány GNU eszköztár plusz néhány fájl a gnuefi-ből (mellékelve).
[bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.efi) (94k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.rom) (94k)
[bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.efi) (95k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.rom) (96k)
2. *x86_64-bios* BIOS, Multiboot (GRUB), El Torito (CDROM), bővítő ROM és Linux boot kompatíbilis, RÉGI betöltő.
Ha újra akarod fordítani, szükséged lesz a fasm-ra (nincs mellékelve).
[boot.bin](https://gitlab.com/bztsrc/bootboot/raw/master/boot.bin) (512 bájt, egyszerre MBR, VBR és CDROM indító szektor), [bootboot.bin](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.bin) (11k, a boot.bin tölti be, valamint BBS bővítő ROM és Multiboot kompatíbilis is)
3. *aarch64-rpi* ARMv8 betöltő Raspberry Pi 3-hoz, 4-hez
[bootboot.img](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.img) (32k)
[bootboot.img](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.img) (34k)
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 (kivéve az UEFI változatot),
csak statikus memórialeképezéseket kezelnek, ami az 1-es protokoll szintnek felel meg.
Vedd figyelembe, hogy nem minden referencia implementáció támogatja a teljes 2-es protokollt, az x86_64-bios csak statikus
memórialeképezéseket kezel, 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.
@ -48,6 +48,12 @@ Megjegyzés: a BOOTBOOT nem egy boot menedzser, hanem egy boot protokoll. Ha int
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 memórialemezt) vagy a bootboot.efi hozzáadható az UEFI Boot menedzser menüjéhez.
Támogasd a fejlesztést adománnyal
---------------------------------
Ha tetszik, vagy hasznosnak találod, szívesen fogadok akármekkora adományt:<br>
<a href="bitcoin:3G9vcV91S19fHMoBcmSksUpaxGPR5MUGCk"><img src="https://gitlab.com/bztsrc/bootboot/raw/master/donate.png"><br>BTC 3G9vcV91S19fHMoBcmSksUpaxGPR5MUGCk</a>
Licensz
-------
@ -123,7 +129,7 @@ Betöltés menete
---------------
1. a förmver megkeresi a betöltőt, betölti és elindítja.
2. a betöltő inicializálja a hardvert (64 bites mód, képernyőfelbontás, memória térkép stb.)
2. a betöltő inicializálja a hardvert (64 bites többmagos mód, képernyőfelbontás, memória térkép stb.)
3. aztán betölti a környezeti fájlt és az initrd-t (valószínűleg a boot partícióról vagy ROM-ból).
4. sorra meghívja a fájl rendszer meghajtókat, hogy betöltse a kernelt az initrd-ről.
5. ha egyik meghajtó sem járt szerencsével, akkor megkeresi az első futtathatót az initrd-ben.
@ -152,12 +158,12 @@ a 2-es szintű betöltők a futtatható által definiált szimbólumokat haszná
A RAM (egészen 16G-ig) egy-az-egyben le van képezve a pozitív címtartományban. A soros vonali konzol 115200 baudra,
8 adatbittel, paritás nélkül és 1 stopbitre van felkonfigurálva. Megszakítások le vannak tiltva, a kód pedig felügyeleti
szinten (0-ás gyűrű / EL1) fut.
szinten (0-ás gyűrűn / EL1-n) fut.
A képernyű megfelelő felbontásra van állítva 32 bites picelekkel, az `fb` szimbólum által jelölt, negatív címre leképezve.
A képernyű megfelelő felbontásra van állítva 32 bites pixelekkel, az `fb` szimbólum által jelölt, negatív címre leképezve.
Az 1-es szintű betöltők korlátozzák a képernyő méretét valahol 4096 x 4096 pixelnél (függ a szkensortól és a képaránytól is).
Ez több, mint elég az [Ultra HD 4K](https://en.wikipedia.org/wiki/4K_resolution) (3840 x 2160) felbontáshoz. A 2-es szintű
betöltők akárhoz képesek kezelni az fb szimbólumot, ezért rájuk nem vonatkozik ez a megszorítás.
betöltők akárhova képesek leképezni az fb szimbólumot -1G és -2M között, ezért rájuk nem vonatkozik ez a megszorítás.
A fő információs [bootboot struktúra](https://gitlab.com/bztsrc/bootboot/blob/master/bootboot.h) a `bootboot` szimbólumra
van leképezve. Ez áll egy fix 128 bájtos fejlécből, amit egy változó hosszúságú, de fix méretű rekordok követnek. Az initrd
@ -165,12 +171,13 @@ van leképezve. Ez áll egy fix 128 bájtos fejlécből, amit egy változó hoss
*initrd_size* mezői mutatnak rá. A framebuffer fizikai címe az *fb_ptr* mezőben található. Az *indulási rendszer idő* és
a platform független *memóriatérkép* szintén itt található.
A konfigurációs sztring (vagy parancssor, ha úgy tetszik) az `environment` szimbólumra van leképezve.
A konfigurációs sztring (vagy parancssor, "command line" ha úgy tetszik) az `environment` szimbólumra van leképezve.
A kernel kód szegmense az ELF fejléc `p_vaddr` vagy a PE fejléc `code_base` mezői alapján kerülnek leképezésre (csak 2-es
szint). Az 1-es szintű betöltők mindig -2M-re töltik a kernelt, ezzel limitálva a teljes méretét 2M-re, beleértve a
konfigurációt, adatot, inicializálatlan adatterületet és a vermet. Ennek több, mint elégnek kell lennie bármilyen mikrokernel
számára. Az inicialiyálatlan adatterület a text szegmens után jön, felfelé növekszik, és a betöltő kinullázza.
konfigurációt, adatot, inicializálatlan adatterületet és a vermet. A 2. szint limitje 16M az adat, kód és bss szegmensre.
Ennek több, mint elégnek kell lennie bármilyen mikrokernel számára. Az inicializálatlan adatterület a text szegmens után jön,
felfelé növekszik, és a betöltő kinullázza.
A társprocesszor (lebegőpontos számtás) be van kapcsolva, és ha a Szimmetrikus Többmagos Feldolgozás (SMP) támogatott, akkor
minden CPU mag ugyanazt a kernel kódot hajtja végre egyszerre.
@ -411,7 +418,14 @@ BOOTBOOT-PANIC: Kernel is not a valid executable
A megadott kernel fájlt megtalálta ugyan az initrd-n valamelyik fájl rendszer meghajtó, de az nem ELF64 se PE32+ formátumú,
vagy nem az adott architáktúrára van fordítva, vagy nincs benne betölthető szegmens definíció a negatív címtartományban
megadva (lásd linker szkript). Ezt a hibát a 2-es szintű betöltők is kiírhatják, ha az `mmio`, `fb`, `bootboot` vagy
`environment` szimbólumok címei nincsenek a negatív címtartományban.
`environment` szimbólumok címei nincsenek a negatív címtartományban (-1G és 0 között), vagy nincsenek lapcímhatárra igazítva.
Az x86_64-en az fb szimbólumnak, míg AArch64-on az mmio szimbólumnak 2M igazítottnak is kell lennie.
```
BOOTBOOT-PANIC: Kernel is too big
```
A kernel nagyobb, 16 megabájt.
```
BOOTBOOT-PANIC: GOP failed, no framebuffer
@ -428,14 +442,16 @@ BOOTBOOT-PANIC: Unsupported cipher
```
Ezt akkor írja ki, ha az initrd olyan titkosítást használ, amit a betöltő nem ismer. Megoldás: újra kell generálni az
initrd-t SHA-XOR-CBC-vel, amit minden betöltő implementációnak támogatnia kell (megjegyzés: a titikosítás csak FS/Z
esetén támogatott).
initrd-t SHA-XOR-CBC-vel, amit minden betöltő implementációnak támogatnia kell (megjegyzés: a titkosítás csak FS/Z
lemezkép esetén támogatott).
Ez minden, remélem hasznososnak találod!
Hozzájárulások
--------------
Szeretnék külön köszönetet mondani [Valentin Anger](https://gitlab.com/SyrupThinker)-nek, amiért alaposan letesztelte a
kódot számtalan igazi vason is.
Szeretnék külön köszönetet mondani [Valentin Anger](https://gitlab.com/SyrupThinker)nek, amiért alaposan letesztelte a
kódot számtalan igazi vason is. Továbbá [Vinay Chandrá](https://gitlab.com/vinaychandra)nak, amiért addig nem hagyott
békén, míg a 2. szintű protokoll be nem került a refenrencia implementációkba, és amiért tesztelte és kiegészítette
Rust minta kernellel a projektet.

View file

@ -5,19 +5,19 @@ I provide pre-compiled images ready for use.
1. *x86_64-efi* the preferred way of booting on x86_64 architecture.
Standard GNU toolchain and a few files from gnuefi (included).
[bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.efi) (94k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.rom) (94k)
[bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.efi) (95k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.rom) (96k)
2. *x86_64-bios* BIOS, Multiboot (GRUB), El Torito (CDROM), Expansion ROM and Linux boot compatible, OBSOLETE loader.
If you want to recompile this, you'll need fasm (not included).
[boot.bin](https://gitlab.com/bztsrc/bootboot/raw/master/boot.bin) (512 bytes, works as MBR, VBR and CDROM boot record too), [bootboot.bin](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.bin) (11k, loaded by boot.bin, also BBS Expansion ROM and Multiboot compliant)
3. *aarch64-rpi* ARMv8 boot loader for Raspberry Pi 3, 4
[bootboot.img](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.img) (32k)
[bootboot.img](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.img) (34k)
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 (except the UEFI version),
they only handle static mappings which makes them level 1 loaders.
Please note that not all the reference implementations do support the full protocol at level 2, x86_64-bios only handles
static mappings which makes it a level 1 loader.
For quick test, you can find example bootable disk [images](https://gitlab.com/bztsrc/bootboot/tree/master/images) too.
@ -49,6 +49,12 @@ Note: BOOTBOOT is not a boot manager, it's a boot loader protocol. If you want a
integrate that *before* a BOOTBOOT compatible loader is called. Like GRUB chainloading boot.bin (or loading bootboot.bin as a
multiboot "kernel" and initrd as a module) or adding bootboot.efi to UEFI Boot Manager's menu for example.
Support the Development by Donation
-----------------------------------
If you like it or find it useful, your donation of any amount will be very much appreciated:<br>
<a href="bitcoin:3G9vcV91S19fHMoBcmSksUpaxGPR5MUGCk"><img src="https://gitlab.com/bztsrc/bootboot/raw/master/donate.png"><br>BTC 3G9vcV91S19fHMoBcmSksUpaxGPR5MUGCk</a>
Licence
-------
@ -124,7 +130,7 @@ Boot process
------------
1. the firmware locates the loader, loads it and passes control to it.
2. the loader initializes hardware (64 bit mode, screen resolution, memory map etc.)
2. the loader initializes hardware (64 bit multicore mode, screen resolution, memory map etc.)
3. then loads environment file and initrd file (probably from the boot partition or from ROM).
4. iterates on file system drivers, and loads kernel file from initrd.
5. if file system is not recognized, scans for the first executable in the initrd.
@ -156,8 +162,8 @@ The RAM (up to 16G) is identity mapped in the positive address range. Serial con
The screen is properly set up with a 32 bit packed pixel linear framebuffer, mapped at the negative address defined by
the `fb` symbol. Level 1 loaders limit the framebuffer size somewhere around 4096 x 4096 pixels (depends on scanline size
and aspect ratio too). That's more than enough for [Ultra HD 4K](https://en.wikipedia.org/wiki/4K_resolution)
(3840 x 2160). Level 2 loaders can place the fb anywhere in memory therefore they do not have such a limitation.
and aspect ratio too). That's more than enough for [Ultra HD 4K](https://en.wikipedia.org/wiki/4K_resolution) (3840 x 2160).
Level 2 loaders can place the fb anywhere in memory from -1G to -2M, therefore they do not have such a limitation.
The main information [bootboot structure](https://gitlab.com/bztsrc/bootboot/blob/master/bootboot.h) is mapped
at `bootboot` symbol. It consist of a fixed 128 bytes long header followed by various number of fixed
@ -168,9 +174,9 @@ the *fb_ptr* field. The *boot time* and a platform independent *memory map* are
The configuration string (or command line if you like) is mapped at `environment` symbol.
Kernel's code segment is mapped at ELF header's `p_vaddr` or PE header's `code_base` (level 2 only). Level 1 loaders
load kernels at -2M, therefore limiting the kernel's size in 2M, including configuration, data, bss and stack. That
must be more than enough for all micro-kernels. Bss segment is after the text segment, growing upwards, and it's zerod-out
by the loader.
load kernels at -2M, therefore limiting the kernel's size in 2M, including configuration, data, bss and stack. Level 2
loaders has a limit of 16M for code, data and bss segment. That must be more than enough for all micro-kernels. Bss
segment is after the text segment, growing upwards, and it's zerod-out by the loader.
Co-processor enabled, and if Symmetric Multi Processing supported, all cores are running the same kernel code at once.
@ -413,7 +419,14 @@ BOOTBOOT-PANIC: Kernel is not a valid executable
The file that was specified as kernel could be loaded by fs drivers, but it's not an ELF64 or PE32+,
does not match the architecture, or does not have any program header with a loadable segment (p_vaddr or core_base)
in the negative range (see linker script). This error is also shown by level 2 loaders if the address of `mmio`, `fb`,
`bootboot` and `environment` symbols are not in the negative range.
`bootboot` and `environment` symbols are not in the negative range (-1G to 0) or if they are not page aligned.
On x86_64 the fb symbol, and for AArch64 the mmio symbol must be 2M aligned too.
```
BOOTBOOT-PANIC: Kernel is too big
```
The kernel is bigger than 16 megabytes.
```
BOOTBOOT-PANIC: GOP failed, no framebuffer
@ -439,5 +452,5 @@ Contributors
------------
I'd like to say special thanks to [Valentin Anger](https://gitlab.com/SyrupThinker) for throughfully testing this
code on many different real hardware.
code on many different real hardware. Also to [Vinay Chandra](https://gitlab.com/vinaychandra) for pushing me to add
level 2 protocol to the reference implementations and for testing and providing a Rust kernel example for the project.

View file

@ -28,11 +28,11 @@
*
*/
#define DEBUG 1
//#define SD_DEBUG DEBUG
//#define INITRD_DEBUG DEBUG
//#define EXEC_DEBUG DEBUG
//#define MEM_DEBUG DEBUG
#define BBDEBUG 1
//#define SD_DEBUG BBDEBUG
//#define INITRD_DEBUG BBDEBUG
//#define EXEC_DEBUG BBDEBUG
//#define MEM_DEBUG BBDEBUG
#define CONSOLE UART0
@ -43,16 +43,13 @@
/* get BOOTBOOT structure */
#include "../bootboot.h"
// comment out this include if you don't want FS/Z support
//#include "../../osZ/include/osZ/fsZ.h"
/* aligned buffers */
volatile uint32_t __attribute__((aligned(16))) mbox[36];
/* we place these manually in linker script, gcc would otherwise waste lots of memory */
volatile uint8_t __attribute__((aligned(PAGESIZE))) __bootboot[PAGESIZE];
volatile uint8_t __attribute__((aligned(PAGESIZE))) __environment[PAGESIZE];
volatile uint8_t __attribute__((aligned(PAGESIZE))) __paging[23*PAGESIZE];
volatile uint8_t __attribute__((aligned(PAGESIZE))) __paging[50*PAGESIZE];
volatile uint8_t __attribute__((aligned(PAGESIZE))) __corestack[PAGESIZE];
#define __diskbuf __paging
extern volatile uint8_t _data;
@ -103,6 +100,30 @@ typedef struct
uint64_t p_align; /* Segment alignment */
} Elf64_Phdr;
typedef struct
{
uint32_t sh_name; /* Section name (string tbl index) */
uint32_t sh_type; /* Section type */
uint64_t sh_flags; /* Section flags */
uint64_t sh_addr; /* Section virtual addr at execution */
uint64_t sh_offset; /* Section file offset */
uint64_t sh_size; /* Section size in bytes */
uint32_t sh_link; /* Link to another section */
uint32_t sh_info; /* Additional section information */
uint64_t sh_addralign; /* Section alignment */
uint64_t sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
typedef struct
{
uint32_t st_name; /* Symbol name (string tbl index) */
uint8_t st_info; /* Symbol type and binding */
uint8_t st_other; /* Symbol visibility */
uint16_t st_shndx; /* Section index */
uint64_t st_value; /* Symbol value */
uint64_t st_size; /* Symbol size */
} Elf64_Sym;
/*** PE32+ defines and structs ***/
#define MZ_MAGIC 0x5a4d /* "MZ" */
#define PE_MAGIC 0x00004550 /* "PE\0\0" */
@ -121,7 +142,7 @@ typedef struct {
uint16_t sections; /* number of sections */
uint32_t timestamp; /* time_t */
uint32_t sym_table; /* symbol table offset */
uint32_t symbols; /* number of symbols */
uint32_t numsym; /* number of symbols */
uint16_t opt_hdr_size; /* size of optional header */
uint16_t flags; /* flags */
uint16_t file_type; /* file type, PE32PLUS magic */
@ -134,6 +155,15 @@ typedef struct {
int32_t code_base; /* relative code addr in ram */
} pe_hdr;
typedef struct {
uint32_t iszero; /* if this is not zero, then iszero+nameoffs gives UTF-8 string */
uint32_t nameoffs;
int32_t value; /* value of the symbol */
uint16_t section; /* section it belongs to */
uint16_t type; /* symbol type */
uint8_t storclass; /* storage class */
uint8_t auxsyms; /* number of pe_sym records following */
} pe_sym;
/*** Raspberry Pi specific defines ***/
static uint64_t mmio_base;
@ -316,7 +346,7 @@ int oct2bin(unsigned char *s, int n){ int r=0;while(n-->0){r<<=3;r+=*s++-'0';} r
int hex2bin(unsigned char *s, int n){ int r=0;while(n-->0){r<<=4;
if(*s>='0' && *s<='9')r+=*s-'0';else if(*s>='A'&&*s<='F')r+=*s-'A'+10;s++;} return r; }
#if DEBUG
#if BBDEBUG
#define DBG(s) puts(s)
#else
#define DBG(s)
@ -744,6 +774,11 @@ file_t env; // environment file descriptor
file_t initrd; // initrd file descriptor
file_t core; // kernel file descriptor
BOOTBOOT *bootboot; // the BOOTBOOT structure
uint64_t mm_addr = BOOTBOOT_MMIO; // virtual addresses
uint64_t fb_addr = BOOTBOOT_FB;
uint64_t bb_addr = BOOTBOOT_INFO;
uint64_t env_addr= BOOTBOOT_ENV;
uint64_t core_addr=BOOTBOOT_CORE;
// default environment variables. M$ states that 1024x768 must be supported
int reqwidth = 1024, reqheight = 768;
@ -756,7 +791,6 @@ char *cfgname="sys/config";
uint64_t entrypoint=0, bss=0, *paging, reg, pa;
uint8_t bsp_done=0;
#ifdef _FS_Z_H_
/**
* SHA-256
*/
@ -903,7 +937,6 @@ int ReadLine(unsigned char *buf, int l)
}
return i;
}
#endif
// get filesystem drivers for initrd
#include "fs.h"
@ -1054,6 +1087,27 @@ void putc(char c)
*/
void puts(char *s) { while(*s) putc(*s++); }
/**
* Add a mapping to paging tables
*/
int freep = 37;
void MapPage(uint64_t virt, uint64_t phys)
{
int i,j;
j = (virt>>(9+12)) & 0x1FF;
if(!paging[4*512 + j] || (paging[4*512 + j] & (2<<2))) {
if(freep == 50) return;
paging[4*512 + j]=(uint64_t)((uint8_t *)paging+freep*PAGESIZE)|0b11|(3<<8)|(1<<10);
freep++;
}
i = (paging[4*512 + j] - (uint64_t)((uint8_t *)paging)) >> 12;
j = (virt>>(12)) & 0x1FF;
paging[i*512 + j] = phys;
}
/**
* Parse FS0:\BOOTBOOT\CONFIG or /sys/config
*/
void ParseEnvironment(uint8_t *env)
{
uint8_t *end=env+PAGESIZE;
@ -1107,7 +1161,7 @@ void ParseEnvironment(uint8_t *env)
int bootboot_main(uint64_t hcl)
{
uint8_t *pe,bkp=0;
uint32_t np,sp,r,mp;
uint32_t np,sp,r,mp,j;
efipart_t *part;
volatile bpb_t *bpb;
MMapEnt *mmap;
@ -1172,7 +1226,7 @@ int bootboot_main(uint64_t hcl)
bootboot = (BOOTBOOT*)&__bootboot;
memset(bootboot,0,PAGESIZE);
memcpy((void*)&bootboot->magic,BOOTBOOT_MAGIC,4);
bootboot->protocol = PROTOCOL_STATIC | LOADER_RPI;
bootboot->protocol = PROTOCOL_DYNAMIC | LOADER_RPI;
bootboot->size = 128;
bootboot->numcores = 4;
bootboot->arch.aarch64.mmio_ptr = mmio_base;
@ -1490,14 +1544,52 @@ gzerr: puts("BOOTBOOT-PANIC: Unable to uncompress\n");
}
phdr=(Elf64_Phdr *)((uint8_t *)phdr+ehdr->e_phentsize);
}
if(ehdr->e_shoff > 0) {
Elf64_Shdr *shdr=(Elf64_Shdr *)((uint8_t *)ehdr + ehdr->e_shoff), *sym_sh = NULL, *str_sh = NULL;
Elf64_Shdr *strt=(Elf64_Shdr *)((uint8_t *)shdr+(uint64_t)ehdr->e_shstrndx*(uint64_t)ehdr->e_shentsize);
Elf64_Sym *sym = NULL, *s;
char *strtable = (char *)ehdr + strt->sh_offset;
uint32_t strsz = 0, syment = 0, i;
for(i = 0; i < ehdr->e_shnum; i++){
/* checking shdr->sh_type is not enough, there can be multiple SHT_STRTAB records... */
if(!memcmp(strtable + shdr->sh_name, ".symtab", 8)) sym_sh = shdr;
if(!memcmp(strtable + shdr->sh_name, ".strtab", 8)) str_sh = shdr;
shdr = (Elf64_Shdr *)((uint8_t *)shdr + ehdr->e_shentsize);
}
if(str_sh && sym_sh) {
strtable = (char *)ehdr + str_sh->sh_offset; strsz = str_sh->sh_size;
sym = (Elf64_Sym *)((uint8_t*)ehdr + sym_sh->sh_offset); syment = sym_sh->sh_entsize;
if(str_sh->sh_offset && strsz > 0 && sym_sh->sh_offset && syment > 0)
for(s = sym, i = 0; i<(strtable-(char*)sym)/syment && s->st_name < strsz; i++, s++) {
if(!memcmp(strtable + s->st_name, "bootboot", 9)) bb_addr = s->st_value;
if(!memcmp(strtable + s->st_name, "environment", 12)) env_addr = s->st_value;
if(!memcmp(strtable + s->st_name, "mmio", 4)) mm_addr = s->st_value;
if(!memcmp(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_ARM64 && pehdr->file_type == PE_OPT_MAGIC_PE32PLUS &&
(int64_t)pehdr->code_base>>48==0xffff) {
(pehdr->code_base & 0xC0000000)) {
DBG(" * Parsing PE32+\n");
core.size = (pehdr->entry_point-pehdr->code_base) + pehdr->text_size + pehdr->data_size;
bss = pehdr->bss_size;
entrypoint = (int64_t)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;
uint32_t i;
for(i = 0; i < pehdr->numsym; i++) {
s = (pe_sym*)((uint8_t *)pehdr + pehdr->sym_table + i * 18);
name = !s->iszero ? (char*)&s->iszero : strtable + s->nameoffs;
if(!memcmp(name, "bootboot", 9)) bb_addr = (int64_t)s->value;
if(!memcmp(name, "environment", 12)) env_addr = (int64_t)s->value;
if(!memcmp(name, "mmio", 4)) mm_addr = (int64_t)s->value;
if(!memcmp(name, "fb", 3)) fb_addr = (int64_t)s->value;
i += s->auxsyms;
}
}
}
}
#if EXEC_DEBUG
@ -1508,8 +1600,14 @@ gzerr: puts("BOOTBOOT-PANIC: Unable to uncompress\n");
uart_putc('\n');
uart_dump((void*)core.ptr,4);
#endif
if(core.size<2 || entrypoint==0) {
puts("BOOTBOOT-PANIC: Kernel is not a valid executable\n");
if(core.ptr==NULL || core.size<2 || entrypoint==0 || (core_addr&(PAGESIZE-1)) || (bb_addr>>30)!=0x3FFFFFFFF ||
(bb_addr & (PAGESIZE-1)) || (env_addr>>30)!=0x3FFFFFFFF || (env_addr&(PAGESIZE-1)) || (fb_addr>>30)!=0x3FFFFFFFF ||
(fb_addr&(1024*1024*2-1))) {
puts("BOOTBOOT-PANIC: Kernel is not a valid executable\n");
goto error;
}
if(core.size+bss > 16*1024*1024) {
puts("BOOTBOOT-PANIC: Kernel is too big");
goto error;
}
// create core segment
@ -1606,19 +1704,19 @@ viderr:
puts("BOOTBOOT-PANIC: VideoCore error, no framebuffer\n");
goto error;
}
/* clear the screen */
int offs = 0, line;
for(ky=0;ky<bootboot->fb_height;ky++) {
line=offs;
for(kx=0;kx<bootboot->fb_width;kx+=2,line+=8)
*((uint64_t*)((uint64_t)bootboot->fb_ptr + line))=0;
offs+=bootboot->fb_scanline;
}
}
/* clear the screen */
for(j=ky=0;ky<bootboot->fb_height;ky++) {
r=j;
for(kx=0;kx<bootboot->fb_width;kx+=2,r+=8)
*((uint64_t*)((uint64_t)bootboot->fb_ptr + r))=0;
j+=bootboot->fb_scanline;
}
kx=ky=0; color=0xFFDD33;
/* create MMU translation tables in __paging */
paging=(uint64_t*)&__paging;
memset(paging, 0, 50*PAGESIZE);
// TTBR0, identity L1
paging[0]=(uint64_t)((uint8_t*)&__paging+2*PAGESIZE)|0b11|(3<<8)|(1<<10); //AF=1,Block=1,Present=1, SH=3 ISH, RO
// identity L2
@ -1635,24 +1733,28 @@ viderr:
paging[512+511]=(uint64_t)((uint8_t*)&__paging+4*PAGESIZE)|0b11|(3<<8)|(1<<10); //AF=1,Block=1,Present=1
// core L2
// map MMIO in kernel space
for(r=0;r<32;r++)
paging[4*512+448+r]=(uint64_t)(mmio_base+((uint64_t)r<<21))|0b01|(2<<8)|(1<<10)|(1<<2)|(1L<<54); //OSH, Attr=1, NX
j = (mm_addr>>(9+12)) & 0x1FF;
for(r=0;j+r < 511 && r<32;r++)
paging[4*512+j+r]=(uint64_t)(mmio_base+((uint64_t)r<<21))|0b01|(2<<8)|(1<<10)|(1<<2)|(1L<<54); //OSH, Attr=1, NX
// map framebuffer
for(r=0;r<16;r++)
paging[4*512+480+r]=(uint64_t)((uint8_t*)&__paging+(6+r)*PAGESIZE)|0b11|(2<<8)|(1<<10)|(2<<2)|(1L<<54); //OSH, Attr=2
paging[4*512+511]=(uint64_t)((uint8_t*)&__paging+5*PAGESIZE)|0b11|(3<<8)|(1<<10);// pointer to core L3
j = (fb_addr>>(9+12)) & 0x1FF;
for(r=0;j+r < 511 && r<31;r++)
paging[4*512+j+r]=(uint64_t)((uint8_t*)&__paging+(5+r)*PAGESIZE)|0b11|(2<<8)|(1<<10)|(2<<2)|(1L<<54); //OSH, Attr=2
paging[4*512+511]=(uint64_t)((uint8_t*)&__paging+36*PAGESIZE)|0b11|(3<<8)|(1<<10);// pointer to core L3
j = (fb_addr>>(12)) & 0x1FF;
for(r=0;r<31*512;r++)
paging[5*512+j+r]=(uint64_t)((uint8_t*)bootboot->fb_ptr+r*PAGESIZE)|0b11|(2<<8)|(1<<10)|(2<<2)|(1L<<54); //map framebuffer
// core L3
paging[5*512+0]=(uint64_t)((uint8_t*)&__bootboot)|0b11|(3<<8)|(1<<10)|(1L<<54); // p, b, AF, ISH
paging[5*512+1]=(uint64_t)((uint8_t*)&__environment)|0b11|(3<<8)|(1<<10)|(1L<<54);
// dynamically map these. Main struct, environment string and code segment
for(r=0;r<(core.size/PAGESIZE);r++)
paging[5*512+2+r]=(uint64_t)((uint8_t *)core.ptr+(uint64_t)r*PAGESIZE)|0b11|(3<<8)|(1<<10);
MapPage(core_addr+r*PAGESIZE,(uint64_t)((uint8_t *)core.ptr+(uint64_t)r*PAGESIZE)|0b11|(3<<8)|(1<<10));
MapPage(bb_addr,(uint64_t)((uint8_t*)&__bootboot)|0b11|(3<<8)|(1<<10)|(1L<<54)); // p, b, AF, ISH
MapPage(env_addr,(uint64_t)((uint8_t*)&__environment)|0b11|(3<<8)|(1<<10)|(1L<<54));
// stack at the top of the memory
paging[36*512+511]=(uint64_t)((uint8_t*)&__corestack)|0b11|(3<<8)|(1<<10)|(1L<<54); // core stacks (1k each)
#if MEM_DEBUG
reg=r;
#endif
paging[5*512+511]=(uint64_t)((uint8_t*)&__corestack)|0b11|(3<<8)|(1<<10)|(1L<<54); // core stacks (1k each)
// core L3 (lfb)
for(r=0;r<16*512;r++)
paging[6*512+r]=(uint64_t)((uint8_t*)bootboot->fb_ptr+r*PAGESIZE)|0b11|(2<<8)|(1<<10)|(2<<2)|(1L<<54); // map framebuffer
#if MEM_DEBUG
/* dump page translation tables */
@ -1697,7 +1799,19 @@ viderr:
for(r=508;r<512;r++) { uart_hex(paging[5*512+r],8); uart_putc(' '); }
uart_puts("\n\n");
#endif
#if DEBUG
#if BBDEBUG
uart_puts(" * mmio ");
uart_hex(mm_addr,8);
uart_putc('\n');
uart_puts(" * fb ");
uart_hex(fb_addr,8);
uart_putc('\n');
uart_puts(" * bootboot ");
uart_hex(bb_addr,8);
uart_putc('\n');
uart_puts(" * environment ");
uart_hex(env_addr,8);
uart_putc('\n');
uart_puts(" * Entry point ");
uart_hex(entrypoint,8);
uart_putc('\n');

View file

@ -28,51 +28,48 @@
*
*/
#ifdef _FS_Z_H_
/**
* FS/Z initrd (OS/Z's native file system)
*/
file_t fsz_initrd(unsigned char *initrd_p, char *kernel)
{
FSZ_SuperBlock *sb = (FSZ_SuperBlock *)initrd_p;
file_t ret = { NULL, 0 };
if(initrd_p==NULL || memcmp(sb->magic,FSZ_MAGIC,4) || kernel==NULL){
if(initrd_p==NULL || memcmp(initrd_p + 512,"FS/Z",4) || kernel==NULL){
return ret;
}
unsigned char passphrase[256],chk[32],iv[32];
int i,j,k,l,ss=1<<(sb->logsec+11);
FSZ_DirEnt *ent;
FSZ_Inode *in=(FSZ_Inode *)(initrd_p+sb->rootdirfid*ss);
unsigned int i,j,k,l,ss=1<<(*((uint16_t*)(initrd_p+520))+11);
unsigned char *ent, *in=(initrd_p+*((uint64_t*)(initrd_p+560))*ss);
SHA256_CTX ctx;
DBG(" * FS/Z ");
DBG(kernel);
DBG("\n");
//decrypt initrd
if(sb->enchash!=0 && FSZ_SB_EALG(sb->flags)!=0) {
if(*((uint32_t*)(initrd_p+708))!=0 && ((initrd_p[518]>>2)&7)!=0) {
puts("BOOTBOOT-PANIC: Unsupported cipher\n");
return ret;
}
while(sb->enchash!=0) {
while(*((uint32_t*)(initrd_p+708))!=0) {
puts(" * Passphrase? ");
l=ReadLine(passphrase,sizeof(passphrase));
if(!l) {
puts("\n");
return ret;
}
if(sb->enchash!=crc32_calc((char*)passphrase,l)) {
if(*((uint32_t*)(initrd_p+708))!=crc32_calc((char*)passphrase,l)) {
puts("\rBOOTBOOT-ERROR: Bad passphrase\n");
continue;
}
puts("\r * Decrypting...\r");
SHA256_Init(&ctx);
SHA256_Update(&ctx,passphrase,l);
SHA256_Update(&ctx,&sb->magic,6);
SHA256_Update(&ctx,initrd_p+512,6);
SHA256_Final(chk,&ctx);
for(i=0;i<sizeof(sb->encrypt);i++) sb->encrypt[i]^=chk[i];
for(i=0;i<28;i++) initrd_p[i+680]^=chk[i];
SHA256_Init(&ctx);
SHA256_Update(&ctx,&sb->encrypt,sizeof(sb->encrypt));
SHA256_Update(&ctx,initrd_p+680,28);
SHA256_Final(iv,&ctx);
for(k=ss,j=1;j<sb->numsec;j++) {
for(k=ss,j=1;j<*((uint32_t*)(initrd_p+528));j++) {
memcpy(chk,iv,32);
for(i=0;i<ss;i++) {
if(i%32==0) {
@ -84,8 +81,8 @@ file_t fsz_initrd(unsigned char *initrd_p, char *kernel)
initrd_p[k++]^=chk[i%32]^iv[i%32];
}
}
memset(sb->encrypt,0,sizeof(sb->encrypt)+4);
sb->checksum=crc32_calc((char *)sb->magic,508);
memset(initrd_p+680,0,28+4);
*((uint32_t*)(initrd_p+1020))=crc32_calc((char *)initrd_p+512,508);
puts(" \r");
}
// Get the inode
@ -95,60 +92,59 @@ file_t fsz_initrd(unsigned char *initrd_p, char *kernel)
again:
while(*e!='/'&&*e!=0){e++;}
if(*e=='/'){e++;}
if(!memcmp(in->magic,FSZ_IN_MAGIC,4)){
if(!memcmp(in,"FSIN",4)){
//is it inlined?
if(!memcmp(sb->flags&FSZ_SB_FLAG_BIGINODE? in->data.big.inlinedata : in->data.small.inlinedata,FSZ_DIR_MAGIC,4)){
ent=(FSZ_DirEnt *)(sb->flags&FSZ_SB_FLAG_BIGINODE? in->data.big.inlinedata : in->data.small.inlinedata);
} else if(!memcmp(initrd_p+in->sec*ss,FSZ_DIR_MAGIC,4)){
if(!memcmp(initrd_p[518]&1? in + 2048 : in + 1024,"FSDR",4)){
ent=(initrd_p[518]&1? in + 2048 : in + 1024);
} else if(!memcmp(initrd_p+*((uint64_t*)(in+448))*ss,"FSDR",4)){
// go, get the sector pointed
ent=(FSZ_DirEnt *)(initrd_p+in->sec*ss);
ent=(initrd_p+*((uint64_t*)(in+448))*ss);
} else {
return ret;
}
//skip header
FSZ_DirEntHeader *hdr=(FSZ_DirEntHeader *)ent; ent++;
unsigned char *hdr=ent; ent+=128;
//iterate on directory entries
int j=hdr->numentries;
int j=*((uint64_t*)(hdr+16));
while(j-->0){
if(!memcmp(ent->name,s,e-s)) {
if(!memcmp(ent + 17,s,e-s)) {
if(*e==0) {
i=ent->fid;
i=*((uint64_t*)(ent+0));
break;
} else {
s=e;
in=(FSZ_Inode *)(initrd_p+ent->fid*ss);
in=(initrd_p+*((uint64_t*)(ent+0))*ss);
goto again;
}
}
ent++;
ent+=128;
}
} else {
i=0;
}
if(i!=0) {
// fid -> inode ptr -> data ptr
FSZ_Inode *in=(FSZ_Inode *)(initrd_p+i*ss);
if(!memcmp(in->magic,FSZ_IN_MAGIC,4)){
ret.size=in->size;
switch(FSZ_FLAG_TRANSLATION(in->flags)) {
case FSZ_IN_FLAG_INLINE:
unsigned char *in=(initrd_p+i*ss);
if(!memcmp(in,"FSIN",4)){
ret.size=*((uint64_t*)(in+464));
switch(in[488]) {
case 0xFF:
// inline data
ret.ptr=(uint8_t*)(initrd_p+i*ss+1024);
ret.ptr=(uint8_t*)(initrd_p+i*ss+(initrd_p[518]&1? 2048 : 1024));
break;
case FSZ_IN_FLAG_SECLIST:
case FSZ_IN_FLAG_SDINLINE:
case 0x80:
case 0x7F:
// sector directory or list inlined
ret.ptr=(uint8_t*)(initrd_p + *(sb->flags&FSZ_SB_FLAG_BIGINODE?
(uint64_t*)&in->data.big.inlinedata : (uint64_t*)&in->data.small.inlinedata) * ss);
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(initrd_p[518]&1? in + 2048 : in + 1024))*ss);
break;
case FSZ_IN_FLAG_DIRECT:
case 0:
// direct data
ret.ptr=(uint8_t*)(initrd_p + in->sec * ss);
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(in+448)) * ss);
break;
// sector directory (only one level supported here, and no holes in files)
case FSZ_IN_FLAG_SECLIST0:
case FSZ_IN_FLAG_SD:
ret.ptr=(uint8_t*)(initrd_p + (unsigned int)(((FSZ_SectorList *)(initrd_p+in->sec*ss))->sec) * ss);
case 0x81:
case 1:
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(initrd_p + *((uint64_t*)(in+448))*ss)) * ss);
break;
default:
ret.size=0;
@ -158,7 +154,6 @@ again:
}
return ret;
}
#endif
/**
* cpio archive
@ -297,9 +292,7 @@ file_t jamesm_initrd(unsigned char *initrd_p, char *kernel)
* Static file system drivers registry
*/
file_t (*fsdrivers[]) (unsigned char *, char *) = {
#ifdef _FS_Z_H_
fsz_initrd,
#endif
cpio_initrd,
tar_initrd,
sfs_initrd,

View file

@ -18,7 +18,7 @@ SECTIONS
__environment = .;
. += 4096;
__paging = .;
. += (23*4096);
. += (50*4096);
__corestack = .;
. += 4096;
__bss_end = .;

Binary file not shown.

Binary file not shown.

View file

@ -37,6 +37,13 @@ extern "C" {
#define BOOTBOOT_MAGIC "BOOT"
/* default virtual addresses for level 0 and 1 static loaders */
#define BOOTBOOT_MMIO 0xfffffffff8000000 /* memory mapped IO virtual address */
#define BOOTBOOT_FB 0xfffffffffc000000 /* frame buffer virtual address */
#define BOOTBOOT_INFO 0xffffffffffe00000 /* bootboot struct virtual address */
#define BOOTBOOT_ENV 0xffffffffffe01000 /* environment string virtual address */
#define BOOTBOOT_CORE 0xffffffffffe02000 /* core loadable segment start */
/* minimum protocol level:
* hardcoded kernel name, static kernel memory addresses */
#define PROTOCOL_MINIMAL 0

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
donate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

View file

@ -15,8 +15,8 @@ Fordítás
Nézz bele a Makefile-ba, az elején fogsz látni konfigurálható változókat.
- DISKSIZE: a teljes generálnadó lemezkép mérete megabájtban
- BOOTSIZE: a rendszerbetöltő partíció mérete megabájtban
- DISKSIZE: a teljes generálandó lemezkép mérete Megabájtban
- BOOTSIZE: a rendszerbetöltő partíció mérete Megabájtban
- BOOTTYPE: a rendszerbetöltő partíció FAT típusa, 16 vagy 32 (12 már nem támogatott)
- PLATFORM: vagy "x86" vagy "rpi", ez választja ki, melyik lemezképet generálja

View file

@ -30,7 +30,7 @@ Executing `make all` will create the following files:
- disk-(PLATFORM).img: a hybrid disk image with GPT partitions
The disk-x86.img is a special hybrid image, which can be renamed to disk-x86.iso and then burnt to a CDROM; it can also be
booted from an USB stick in a BIOS machine as well as an UEFI machine.
booted from an USB stick in a BIOS machine as well as in an UEFI machine.
The disk-rpi.img can be written to an SDCard (Class 10) and booted on a Raspberry Pi 3 and 4.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -28,7 +28,7 @@
*
*/
mmio = 0xfffffffff8000000;
mmio = 0xfffffffff8000000; /* these are configurable for level 2 loaders */
fb = 0xfffffffffc000000;
PHDRS
{

View file

@ -53,8 +53,10 @@
;*
;* At first big enough free hole, initrd. Usually at 1Mbyte.
;*
;* WARNING: supports BOOTBOOT Protocol level 1 only (static mappings)
;*
DEBUG equ 1
BBDEBUG equ 1
;get Core boot parameter block
include "bootboot.inc"
@ -102,14 +104,14 @@ macro prot_readsector
macro DBG msg
{
if DEBUG eq 1
if BBDEBUG eq 1
real_print msg
end if
}
macro DBG32 msg
{
if DEBUG eq 1
if BBDEBUG eq 1
prot_realmode
real_print msg
real_protmode
@ -1035,7 +1037,7 @@ protmode_start:
.getgpt: xor eax, eax
xor edi, edi
prot_readsector
if DEBUG eq 1
if BBDEBUG eq 1
cmp byte [iscdrom], 0
jz @f
DBG32 dbg_cdrom
@ -1671,7 +1673,13 @@ end if
;ebx=ptr to core segment, ecx=segment size, edx=bss size
.mkcore: or ecx, ecx
jz .badcore
mov edi, dword [bootboot.initrd_ptr]
mov eax, ecx
add eax, edx
cmp eax, 2*1024*1024 - 256*1024 - 2*4096; 2M minus stack for 256 cores minus bootboot and environment
jl @f
mov esi, bigcore
jmp prot_diefunc
@@: mov edi, dword [bootboot.initrd_ptr]
add edi, dword [bootboot.initrd_size]
mov dword [core_ptr], edi
mov dword [core_len], ecx
@ -2200,7 +2208,6 @@ longmode_init:
include "tinf.inc"
;encryption support for FS/Z
if FSZ_SUPPORT eq 1
; --- SHA-256 ---
sha_init: xor eax, eax
mov dword [sha_l], eax
@ -2462,7 +2469,6 @@ crc32_calc: xor edx, edx
dec cx
jnz .next
.end: ret
end if
;*********************************************************************
;* Data *
@ -2483,7 +2489,6 @@ GDT_value: dw $-GDT_table
dd GDT_table
dd 0,0
;lookup tables for initrd encryption
if FSZ_SUPPORT eq 1
dw 0
crclkp: dd 000000000h, 0F26B8303h, 0E13B70F7h, 01350F3F4h, 0C79A971Fh, 035F1141Ch, 026A1E7E8h, 0D4CA64EBh
dd 08AD958CFh, 078B2DBCCh, 06BE22838h, 09989AB3Bh, 04D43CFD0h, 0BF284CD3h, 0AC78BF27h, 05E133C24h
@ -2526,7 +2531,6 @@ sha256_k: dd 0428a2f98h, 071374491h, 0b5c0fbcfh, 0e9b5dba5h, 03956c25
dd 0a2bfe8a1h, 0a81a664bh, 0c24b8b70h, 0c76c51a3h, 0d192e819h, 0d6990624h, 0f40e3585h, 0106aa070h
dd 019a4c116h, 01e376c08h, 02748774ch, 034b0bcb5h, 0391c0cb3h, 04ed8aa4ah, 05b9cca4fh, 0682e6ff3h
dd 0748f82eeh, 078a5636fh, 084c87814h, 08cc70208h, 090befffah, 0a4506cebh, 0bef9a3f7h, 0c67178f2h
end if
idt16: dw 3FFh
dq 0
lbapacket: ;lba packet for BIOS
@ -2553,7 +2557,7 @@ iscdrom: db 0
bsp_done: ;flag to indicate APs can run
fattype: db 0
bkp: dd ' '
if DEBUG eq 1
if BBDEBUG eq 1
dbg_cpu db " * Detecting CPU",10,13,0
dbg_A20 db " * Enabling A20",10,13,0
dbg_mem db " * E820 Memory Map",10,13,0
@ -2587,6 +2591,7 @@ nord: db "Initrd not found",0
nolib: db "/sys not found in initrd",0
nocore: db "Kernel not found in initrd",0
badcore: db "Kernel is not a valid executable",0
bigcore: db "Kernel is too big",0
novbe: db "VESA VBE error, no framebuffer",0
nogzip: db "Unable to uncompress",0
notcdsect: db "Not 2048 sector aligned",0
@ -2644,7 +2649,6 @@ hdist: dw ?
hclen: dw ?
tinf_bss_end:
if FSZ_SUPPORT eq 1
virtual at tinf_bss_start
pass: db 256 dup ?
sha_d: db 64 dup ?
@ -2667,7 +2671,6 @@ iv: db 32 dup ?
pl: dd ?
_i: dd ?
end virtual
end if
;-----------bound check-------------
;fasm will generate an error if the code

View file

@ -37,6 +37,13 @@ bootboot = 8000h
; this define is in the 18th line of bootboot.h
bootboot_MAGIC equ 'BOOT'
; minimum protocol level:
; hardcoded kernel name, static kernel memory addresses
PROTOCOL_MINIMAL equ 0

View file

@ -27,24 +27,19 @@
;* @brief Filesystem drivers for initial ramdisk.
;*
FSZ_SUPPORT equ 1
;*********************************************************************
;* File System Drivers *
;*********************************************************************
USE32
fsdrivers:
if FSZ_SUPPORT eq 1
dw fsz_initrd
end if
dw cpio_initrd
dw tar_initrd
dw sfs_initrd
dw jamesm_initrd
dw 0
if FSZ_SUPPORT eq 1
; ----------- FS/Z ----------
; Find the kernel on initrd (only supports 4096 logical sector sizes)
; IN: esi: initrd pointer, ecx: initrd end, edi: kernel filename
@ -329,7 +324,6 @@ fsz_initrd:
mov esi, dword [bootboot.initrd_ptr]
add esi, eax
ret
end if
; ----------- cpio ----------
; Find the kernel on initrd

View file

@ -28,8 +28,6 @@
*
*/
// DEBUG already defined in efidebug.h
#define BBDEBUG 1
//#define GOP_DEBUG BBDEBUG
@ -48,8 +46,6 @@
// get BOOTBOOT specific stuff
#include "../bootboot.h"
#include "tinf.h"
// comment out this include if you don't want FS/Z support
//#include "../../osZ/include/osZ/fsZ.h"
/*** ELF64 defines and structs ***/
#define ELFMAG "\177ELF"
@ -302,9 +298,11 @@ 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
UINT64 fb_addr = BOOTBOOT_FB; // virtual addresses
UINT64 bb_addr = BOOTBOOT_INFO;
UINT64 env_addr= BOOTBOOT_ENV;
UINT64 core_addr=BOOTBOOT_CORE;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
EFI_FILE_HANDLE RootDir;
EFI_FILE_PROTOCOL *Root;
@ -318,7 +316,6 @@ char *kernelname="sys/core";
// alternative environment name
char *cfgname="sys/config";
#ifdef _FS_Z_H_
/**
* SHA-256
*/
@ -850,7 +847,6 @@ int ReadLine(unsigned char *buf, int l)
}
return i;
}
#endif
/**
* function to convert ascii to number
@ -922,6 +918,24 @@ int hex2bin(unsigned char *str, int size)
return v;
}
/**
* Add a mapping to paging tables
*/
int freep = 24;
void MapPage(UINT64 virt, UINT64 phys)
{
int i,j;
j = (virt>>(9+12)) & 0x1FF;
if(!paging[22*512 + j] || (paging[22*512 + j] & 0xFF) == 0x83) {
if(freep == 37) return;
paging[22*512 + j]=(UINT64)((UINT8 *)paging+freep*PAGESIZE+3);
freep++;
}
i = (paging[22*512 + j] - (UINT64)((UINT8 *)paging)) >> 12;
j = (virt>>(12)) & 0x1FF;
paging[i*512 + j] = phys | 1;
}
// get filesystem drivers for initrd
#include "fs.h"
@ -1157,7 +1171,7 @@ LoadCore()
}
// if every driver failed, try brute force, scan for the first elf or pe executable
if(core.ptr==NULL) {
DBG(L" * Autodetecting kernel%s\n","");
DBG(L" * Autodetecting kernel%s\n",L"");
i=initrd.size;
core.ptr=initrd.ptr;
while(i-->0) {
@ -1194,6 +1208,7 @@ LoadCore()
core.size = phdr->p_filesz + (ehdr->e_type==3?0x4000:0);
ptr = (UINT8*)ehdr + phdr->p_offset;
bss = phdr->p_memsz - core.size;
core_addr = phdr->p_vaddr;
entrypoint = ehdr->e_entry;
break;
}
@ -1230,6 +1245,7 @@ LoadCore()
core.size = (pehdr->entry_point-pehdr->code_base) + pehdr->text_size + pehdr->data_size;
ptr = core.ptr;
bss = pehdr->bss_size;
core_addr = (INT64)pehdr->code_base;
entrypoint = (INT64)pehdr->entry_point;
if(pehdr->sym_table > 0 && pehdr->numsym > 0) {
pe_sym *s;
@ -1244,9 +1260,12 @@ LoadCore()
}
}
}
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)))
if(ptr==NULL || core.size<2 || entrypoint==0 || (core_addr&(PAGESIZE-1)) || (bb_addr>>30)!=0x3FFFFFFFF ||
(bb_addr & (PAGESIZE-1)) || (env_addr>>30)!=0x3FFFFFFFF || (env_addr&(PAGESIZE-1)) || (fb_addr>>30)!=0x3FFFFFFFF ||
(fb_addr&(1024*1024*2-1)))
return report(EFI_LOAD_ERROR,L"Kernel is not a valid executable");
if(core.size+bss > 16*1024*1024)
return report(EFI_LOAD_ERROR,L"Kernel is too big");
// create core segment
uefi_call_wrapper(BS->AllocatePages, 4, 0, 2,
(core.size + bss + PAGESIZE-1)/PAGESIZE, (EFI_PHYSICAL_ADDRESS*)&core.ptr);
@ -1330,7 +1349,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
EFI_MP_SERVICES_PROTOCOL *mp;
UINT8 pibuffer[100];
EFI_PROCESSOR_INFORMATION *pibuf=(EFI_PROCESSOR_INFORMATION*)pibuffer;
UINTN bsp_num=0, i, j=0, handle_size=0,memory_map_size=0, map_key=0, desc_size=0;
UINTN bsp_num=0, i, j=0, x,y, handle_size=0,memory_map_size=0, map_key=0, desc_size=0;
UINT32 desc_version=0;
UINT64 lba_s=0,lba_e=0,sysptr;
MMapEnt *mmapent, *last=NULL;
@ -1718,44 +1737,48 @@ gzerr: return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
}
// create page tables
uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, 23+(bootboot->numcores+3)/4, (EFI_PHYSICAL_ADDRESS*)&paging);
uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, 37+(bootboot->numcores+3)/4, (EFI_PHYSICAL_ADDRESS*)&paging);
if (paging == NULL) {
return report(EFI_OUT_OF_RESOURCES,L"AllocatePages");
}
ZeroMem((void*)paging,23*PAGESIZE);
ZeroMem((void*)paging,37*PAGESIZE);
DBG(L" * Pagetables PML4 @%lx\n",paging);
//PML4
paging[0]=(UINT64)((UINT8 *)paging+4*PAGESIZE)+3; // pointer to 2M PDPE (16G RAM identity mapped)
paging[511]=(UINT64)((UINT8 *)paging+PAGESIZE)+3; // pointer to 4k PDPE (core mapped at -2M)
//4k PDPE
paging[512+511]=(UINT64)((UINT8 *)paging+2*PAGESIZE+3);
//4k PDE
for(i=0;i<31;i++)
paging[2*512+480+i]=(UINT64)(((UINT8 *)(bootboot->fb_ptr)+(i<<21))+0x83); //map framebuffer
paging[2*512+511]=(UINT64)((UINT8 *)paging+3*PAGESIZE+3);
//4k PT
paging[3*512+0]=(UINT64)(bootboot)+1;
paging[3*512+1]=(UINT64)(env.ptr)+1;
for(i=0;i<(core.size/PAGESIZE);i++)
paging[3*512+2+i]=(UINT64)((UINT8 *)core.ptr+i*PAGESIZE+3);
for(i=0; i<(UINTN)((bootboot->numcores+3)/4); i++)
paging[3*512+511-i]=(UINT64)((UINT8 *)paging+(23+i)*PAGESIZE+3); // core stacks
paging[0]=(UINT64)((UINT8 *)paging+PAGESIZE)+3; // pointer to 2M PDPE (16G RAM identity mapped)
paging[511]=(UINT64)((UINT8 *)paging+20*PAGESIZE)+3; // pointer to 4k PDPE (core mapped at -2M)
//identity mapping
//2M PDPE
for(i=0;i<16;i++)
paging[4*512+i]=(UINT64)((UINT8 *)paging+(7+i)*PAGESIZE+3);
paging[512+i]=(UINT64)((UINT8 *)paging+(3+i)*PAGESIZE+3);
//first 2M mapped per page
paging[7*512]=(UINT64)((UINT8 *)paging+5*PAGESIZE+3);
paging[3*512]=(UINT64)((UINT8 *)paging+2*PAGESIZE+3);
for(i=0;i<512;i++)
paging[5*512+i]=(UINT64)(i*PAGESIZE+3);
paging[2*512+i]=(UINT64)(i*PAGESIZE+3);
//2M PDE
for(i=1;i<512*16;i++)
paging[7*512+i]=(UINT64)((i<<21)+0x83);
paging[3*512+i]=(UINT64)((i<<21)+0x83);
//kernel mapping
//4k PDPE
paging[20*512+511]=(UINT64)((UINT8 *)paging+22*PAGESIZE+3);
//4k PDE
j = (fb_addr>>(9+12)) & 0x1FF;
for(i=0;j+i<511 && i<63;i++)
paging[22*512+j+i]=(UINT64)(((UINT8 *)(bootboot->fb_ptr)+(i<<21))+0x83); // map framebuffer
paging[22*512+511]=(UINT64)((UINT8 *)paging+23*PAGESIZE+3);
//4k PT
//dynamically map these. Main struct, environment string and code segment
for(i=0;i<(core.size/PAGESIZE);i++)
MapPage(core_addr + i*PAGESIZE, (UINT64)((UINT8 *)core.ptr+i*PAGESIZE+3));
MapPage(bb_addr, (UINT64)(bootboot)+1);
MapPage(env_addr, (UINT64)(env.ptr)+1);
// stack at the top of the memory
for(i=0; i<(UINTN)((bootboot->numcores+3)/4); i++)
paging[23*512+511-i]=(UINT64)((UINT8 *)paging+(37+i)*PAGESIZE+3); // core stacks
// Get memory map
int cnt=3;
get_memory_map:
DBG(L" * Memory Map @%lx %d bytes #%d\n",memory_map, memory_map_size, 4-cnt);
DBG(L" * Memory Map @%lx %d bytes try #%d\n",memory_map, memory_map_size, 4-cnt);
mmapent=(MMapEnt *)&(bootboot->mmap);
status = uefi_call_wrapper(BS->GetMemoryMap, 5,
&memory_map_size, memory_map, &map_key, &desc_size, &desc_version);
@ -1814,6 +1837,14 @@ get_memory_map:
return report(status,L"ExitBootServices");
}
// clear the screen
for(j=y=0;y<bootboot->fb_height;y++) {
i=j;
for(x=0;x<bootboot->fb_width;x+=2,i+=8)
*((uint64_t*)((uint64_t)bootboot->fb_ptr + i))=0;
j+=bootboot->fb_scanline;
}
// release AP spinlock
bsp_done = 1;
bootboot_startcore((VOID*)bsp_num);

View file

@ -28,51 +28,48 @@
*
*/
#ifdef _FS_Z_H_
/**
* FS/Z initrd (OS/Z's native file system)
*/
file_t fsz_initrd(unsigned char *initrd_p, char *kernel)
{
FSZ_SuperBlock *sb = (FSZ_SuperBlock *)initrd_p;
file_t ret = { NULL, 0 };
if(initrd_p==NULL || CompareMem(sb->magic,FSZ_MAGIC,4) || kernel==NULL){
if(initrd_p==NULL || CompareMem(initrd_p + 512,"FS/Z",4) || kernel==NULL){
return ret;
}
unsigned char passphrase[256],chk[32],iv[32];
UINT64 i,j,k,l,ss=1<<(sb->logsec+11);
FSZ_DirEnt *ent;
FSZ_Inode *in=(FSZ_Inode *)(initrd_p+sb->rootdirfid*ss);
unsigned int i,j,k,l,ss=1<<(*((uint16_t*)(initrd_p+520))+11);
unsigned char *ent, *in=(initrd_p+*((uint64_t*)(initrd_p+560))*ss);
SHA256_CTX ctx;
DBG(L" * FS/Z %s\n",a2u(kernel));
//decrypt initrd
while(sb->enchash!=0) {
while(*((uint32_t*)(initrd_p+708))!=0) {
Print(L" * Passphrase? ");
l=ReadLine(passphrase,sizeof(passphrase));
if(!l) {
Print(L"\n");
return ret;
}
if(sb->enchash!=crc32_calc((char*)passphrase,l)) {
if(*((uint32_t*)(initrd_p+708))!=crc32_calc((char*)passphrase,l)) {
Print(L"\rBOOTBOOT-ERROR: Bad passphrase\n");
continue;
}
Print(L"\r * Decrypting...\r");
SHA256_Init(&ctx);
SHA256_Update(&ctx,passphrase,l);
SHA256_Update(&ctx,&sb->magic,6);
SHA256_Update(&ctx,initrd_p+512,6);
SHA256_Final(chk,&ctx);
for(i=0;i<sizeof(sb->encrypt);i++) sb->encrypt[i]^=chk[i];
for(i=0;i<28;i++) initrd_p[i+680]^=chk[i];
SHA256_Init(&ctx);
SHA256_Update(&ctx,&sb->encrypt,sizeof(sb->encrypt));
SHA256_Update(&ctx,initrd_p+680,28);
SHA256_Final(iv,&ctx);
if(sb->flags&FSZ_SB_EALG_AESCBC) {
if(((initrd_p[518]>>2)&7)==1) {
aes_init(iv);
for(k=ss,j=1;j<sb->numsec;k+=ss,j++) {
for(k=ss,j=1;j<*((uint32_t*)(initrd_p+528));k+=ss,j++) {
aes_dec(initrd_p+k,ss);
}
} else {
for(k=ss,j=1;j<sb->numsec;j++) {
for(k=ss,j=1;j<*((uint32_t*)(initrd_p+528));j++) {
CopyMem(chk,iv,32);
for(i=0;i<ss;i++) {
if(i%32==0) {
@ -85,8 +82,8 @@ file_t fsz_initrd(unsigned char *initrd_p, char *kernel)
}
}
}
ZeroMem(sb->encrypt,sizeof(sb->encrypt)+4);
sb->checksum=crc32_calc((char *)sb->magic,508);
ZeroMem(initrd_p+680,28+4);
*((uint32_t*)(initrd_p+1020))=crc32_calc((char *)initrd_p+512,508);
Print(L" \r");
}
// Get the inode
@ -96,60 +93,59 @@ file_t fsz_initrd(unsigned char *initrd_p, char *kernel)
again:
while(*e!='/'&&*e!=0){e++;}
if(*e=='/'){e++;}
if(!CompareMem(in->magic,FSZ_IN_MAGIC,4)){
if(!CompareMem(in,"FSIN",4)){
//is it inlined?
if(!CompareMem(sb->flags&FSZ_SB_FLAG_BIGINODE? in->data.big.inlinedata : in->data.small.inlinedata,FSZ_DIR_MAGIC,4)){
ent=(FSZ_DirEnt *)(sb->flags&FSZ_SB_FLAG_BIGINODE? in->data.big.inlinedata : in->data.small.inlinedata);
} else if(!CompareMem(initrd_p+in->sec*ss,FSZ_DIR_MAGIC,4)){
if(!CompareMem(initrd_p[518]&1? in + 2048 : in + 1024,"FSDR",4)){
ent=(initrd_p[518]&1? in + 2048 : in + 1024);
} else if(!CompareMem(initrd_p+*((uint64_t*)(in+448))*ss,"FSDR",4)){
// go, get the sector pointed
ent=(FSZ_DirEnt *)(initrd_p+in->sec*ss);
ent=(initrd_p+*((uint64_t*)(in+448))*ss);
} else {
return ret;
}
//skip header
FSZ_DirEntHeader *hdr=(FSZ_DirEntHeader *)ent; ent++;
unsigned char *hdr=ent; ent+=128;
//iterate on directory entries
int j=hdr->numentries;
int j=*((uint64_t*)(hdr+16));
while(j-->0){
if(!CompareMem(ent->name,s,e-s)) {
if(!CompareMem(ent + 17,s,e-s)) {
if(*e==0) {
i=ent->fid;
i=*((uint64_t*)(ent+0));
break;
} else {
s=e;
in=(FSZ_Inode *)(initrd_p+ent->fid*ss);
in=(initrd_p+*((uint64_t*)(ent+0))*ss);
goto again;
}
}
ent++;
ent+=128;
}
} else {
i=0;
}
if(i!=0) {
// fid -> inode ptr -> data ptr
FSZ_Inode *in=(FSZ_Inode *)(initrd_p+i*ss);
if(!CompareMem(in->magic,FSZ_IN_MAGIC,4)){
ret.size=in->size;
switch(FSZ_FLAG_TRANSLATION(in->flags)) {
case FSZ_IN_FLAG_INLINE:
unsigned char *in=(initrd_p+i*ss);
if(!CompareMem(in,"FSIN",4)){
ret.size=*((uint64_t*)(in+464));
switch(in[488]) {
case 0xFF:
// inline data
ret.ptr=(UINT8*)(initrd_p+i*ss+1024);
ret.ptr=(uint8_t*)(initrd_p+i*ss+(initrd_p[518]&1? 2048 : 1024));
break;
case FSZ_IN_FLAG_SECLIST:
case FSZ_IN_FLAG_SDINLINE:
case 0x80:
case 0x7F:
// sector directory or list inlined
ret.ptr=(UINT8*)(initrd_p + *(sb->flags&FSZ_SB_FLAG_BIGINODE?
(UINT64*)&in->data.big.inlinedata : (UINT64*)&in->data.small.inlinedata) * ss);
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(initrd_p[518]&1? in + 2048 : in + 1024))*ss);
break;
case FSZ_IN_FLAG_DIRECT:
case 0:
// direct data
ret.ptr=(UINT8*)(initrd_p + in->sec * ss);
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(in+448)) * ss);
break;
// sector directory (only one level supported here, and no holes in files)
case FSZ_IN_FLAG_SECLIST0:
case FSZ_IN_FLAG_SD:
ret.ptr=(UINT8*)(initrd_p + (unsigned int)(((FSZ_SectorList *)(initrd_p+in->sec*ss))->sec) * ss);
case 0x81:
case 1:
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(initrd_p + *((uint64_t*)(in+448))*ss)) * ss);
break;
default:
ret.size=0;
@ -159,7 +155,6 @@ again:
}
return ret;
}
#endif
/**
* cpio archive
@ -289,9 +284,7 @@ file_t jamesm_initrd(unsigned char *initrd_p, char *kernel)
* Static file system drivers registry
*/
file_t (*fsdrivers[]) (unsigned char *, char *) = {
#ifdef _FS_Z_H_
fsz_initrd,
#endif
cpio_initrd,
tar_initrd,
sfs_initrd,