Add possibility to pick separate entry point to stivale
diff --git a/STIVALE.md b/STIVALE.md
index e70da03f..fd501657 100644
--- a/STIVALE.md
+++ b/STIVALE.md
@@ -32,7 +32,9 @@ The kernel MUST NOT request to load itself at an address lower than `0x100000`
### 64-bit kernel
-`rip` will be the entry point as defined in the ELF file.
+`rip` will be the entry point as defined in the ELF file, unless the `entry_point`
+field in the stivale header is set to a non-0 value, in which case, it is set to
+the value of `entry_point`.
At entry, the bootloader will have setup paging such that there is a 4GiB identity
mapped block of memory at `0x0000000000000000`, a 2GiB mapped area of memory
@@ -41,6 +43,10 @@ to `0xffffffff80000000` virtual. This area is for the higher half kernels.
Further more, a 4GiB area of memory from `0x0000000000000000` physical to
`0x0000000100000000` physical to `0xffff800000000000` virtual is mapped.
+If the kernel is dynamic and not statically linked, the bootloader will relocate it.
+Furthermore if bit 2 of the flags field in the stivale header is set, the bootloader
+will perform kernel address space layout randomisation (KASLR).
+
The kernel should NOT modify the bootloader page tables, and it should only use them
to bootstrap its own virtual memory manager and its own page tables.
@@ -67,7 +73,9 @@ The A20 gate is enabled.
### 32-bit kernel
-`eip` will be the entry point as defined in the ELF file.
+`eip` will be the entry point as defined in the ELF file, unless the `entry_point`
+field in the stivale header is set to a non-0 value, in which case, it is set to
+the value of `entry_point`.
At entry all segment registers are loaded as 32 bit code/data segments.
All segment bases are `0x00000000` and all limits are `0xffffffff`.
@@ -112,6 +120,8 @@ struct stivale_header {
uint16_t framebuffer_height; // is requested. If all values are set to 0
uint16_t framebuffer_bpp; // then the bootloader will pick the best possible
// video mode automatically (recommended).
+ uint64_t entry_point; // If not 0, this field will be jumped to at entry
+ // instead of the ELF entry point.
} __attribute__((packed));
```
diff --git a/qloader2.bin b/qloader2.bin
index f225ba00..4c7ebf33 100644
Binary files a/qloader2.bin and b/qloader2.bin differ
diff --git a/src/lib/elf.c b/src/lib/elf.c
index 08228033..d5dcb8ea 100644
--- a/src/lib/elf.c
+++ b/src/lib/elf.c
@@ -216,6 +216,8 @@ int elf64_load_section(struct file_handle *fd, void *buffer, const char *name, s
if (!strcmp(&names[section.sh_name], name)) {
if (section.sh_size > limit)
return 3;
+ if (section.sh_size < limit)
+ return 4;
fread(fd, buffer, section.sh_offset, section.sh_size);
return elf64_apply_relocations(fd, &hdr, buffer, section.sh_addr, section.sh_size, slide);
}
@@ -258,6 +260,8 @@ int elf32_load_section(struct file_handle *fd, void *buffer, const char *name, s
if (!strcmp(&names[section.sh_name], name)) {
if (section.sh_size > limit)
return 3;
+ if (section.sh_size < limit)
+ return 4;
fread(fd, buffer, section.sh_offset, section.sh_size);
return 0;
}
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index 6fa320e9..0b641175 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -16,12 +16,11 @@
struct stivale_header {
uint64_t stack;
- // Flags
- // bit 0 0 = text mode, 1 = graphics mode
uint16_t flags;
uint16_t framebuffer_width;
uint16_t framebuffer_height;
uint16_t framebuffer_bpp;
+ uint64_t entry_point;
} __attribute__((packed));
struct stivale_module {
@@ -134,6 +133,8 @@ void stivale_load(char *cmdline, int boot_drive) {
panic("stivale: Section .stivalehdr not found.");
case 3:
panic("stivale: Section .stivalehdr exceeds the size of the struct.");
+ case 4:
+ panic("stivale: Section .stivalehdr is smaller than size of the struct.");
}
print("stivale: Requested stack at %X\n", stivale_hdr.stack);
@@ -150,6 +151,9 @@ void stivale_load(char *cmdline, int boot_drive) {
break;
}
+ if (stivale_hdr.entry_point != 0)
+ entry_point = stivale_hdr.entry_point;
+
print("stivale: Kernel slide: %X\n", slide);
print("stivale: Top used address in ELF: %X\n", top_used_addr);
diff --git a/test/test.asm b/test/test.asm
index 6f8ab040..aaed2b0f 100644
--- a/test/test.asm
+++ b/test/test.asm
@@ -9,6 +9,7 @@ stivale_header:
dw 0 ; fb_width
dw 0 ; fb_height
dw 0 ; fb_bpp
+ dq 0
section .bss
@@ -29,4 +30,4 @@ _start:
mov [rdx], rax
mov [rdx+8], rbx
mov [rdx+16], rcx
- jmp $
\ No newline at end of file
+ jmp $
