:: commit 6540239006bc011f964200b90d012bdc19a649ee

mintsuki <mintsuki@protonmail.com> — 2020-05-30 13:44

parents: e427ab4b64

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 $
tab: 248 wrap: offon