Skip to content

Commit 3dfb6d8

Browse files
committed
kernel: support for multiboot modules (WIP)
1 parent 6dc45c2 commit 3dfb6d8

18 files changed

Lines changed: 418 additions & 114 deletions

File tree

api/kernel/os.hpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <string>
2727
#include <sstream>
2828
#include <vector>
29+
#include <boot/multiboot.h>
2930

3031
/**
3132
* The entrypoint for OS services
@@ -36,6 +37,7 @@ class OS {
3637
public:
3738
using print_func = delegate<void(const char*, size_t)>;
3839
using Plugin = delegate<void()>;
40+
using Span_mods = gsl::span<multiboot_module_t>;
3941

4042
/**
4143
* Returns the version of the OS from when
@@ -204,6 +206,23 @@ class OS {
204206
/** Start the OS. @todo Should be `init()` - and not accessible from ABI */
205207
static void start(uint32_t boot_magic, uint32_t boot_addr);
206208

209+
/** Get "kernel modules", provided by multiboot */
210+
static Span_mods modules() {
211+
212+
if (bootinfo_ and bootinfo_->flags & MULTIBOOT_INFO_MODS) {
213+
214+
Expects(bootinfo_->mods_count > 0
215+
and bootinfo_->mods_count < std::numeric_limits<int>::max());
216+
217+
return Span_mods{
218+
reinterpret_cast<multiboot_module_t*>(bootinfo_->mods_addr),
219+
static_cast<int>(bootinfo_->mods_count) };
220+
221+
}
222+
223+
return nullptr;
224+
}
225+
207226
private:
208227

209228
/** Process multiboot info. Called by 'start' if multibooted **/
@@ -216,15 +235,6 @@ class OS {
216235
static bool is_softreset_magic(uint32_t value);
217236
static void resume_softreset(intptr_t boot_addr);
218237

219-
static constexpr int PAGE_SHIFT = 12;
220-
221-
static bool power_;
222-
static bool boot_sequence_passed_;
223-
224-
static MHz cpu_mhz_;
225-
226-
static std::string version_field;
227-
228238
struct Plugin_struct {
229239
Plugin_struct(Plugin f, const char* n)
230240
: func_{f}, name_{n}
@@ -234,14 +244,18 @@ class OS {
234244
const char* name_;
235245
};
236246

247+
static constexpr int PAGE_SHIFT = 12;
248+
static bool power_;
249+
static bool boot_sequence_passed_;
250+
static MHz cpu_mhz_;
251+
static std::string version_field;
237252
static std::vector<Plugin_struct> plugins_;
238-
239253
static uintptr_t low_memory_size_;
240254
static uintptr_t high_memory_size_;
241255
static uintptr_t memory_end_;
242256
static uintptr_t heap_max_;
243257
static const uintptr_t elf_binary_size_;
244-
258+
static multiboot_info_t* bootinfo_;
245259
static std::string cmdline;
246260

247261
// Prohibit copy and move operations

src/crt/c_abi.c

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@
2626
#include <kprint>
2727

2828
#define HEAP_ALIGNMENT 63
29-
caddr_t heap_begin;
30-
caddr_t heap_end;
29+
void* heap_begin;
30+
void* heap_end;
31+
32+
extern char _ELF_SYM_START_;
33+
extern char _end;
34+
3135

3236
/// IMPLEMENTATION OF Newlib I/O:
3337
#undef stdin
@@ -42,10 +46,25 @@ __FILE* stderr;
4246
const uintptr_t __stack_chk_guard = _STACK_GUARD_VALUE_;
4347
extern void panic(const char* why) __attribute__((noreturn));
4448

45-
void _init_c_runtime()
46-
{
47-
extern char _ELF_SYM_START_;
48-
extern char _end;
49+
void _init_bss() {
50+
/// Initialize .bss section
51+
extern char _BSS_START_, _BSS_END_;
52+
streamset8(&_BSS_START_, 0, &_BSS_END_ - &_BSS_START_);
53+
54+
}
55+
56+
void _init_heap(uintptr_t free_mem_begin) {
57+
// NOTE: Initialize the heap before exceptions
58+
// cache-align heap, because its not aligned
59+
heap_begin = (void*) free_mem_begin + HEAP_ALIGNMENT;
60+
heap_begin = (void*) ((size_t)heap_begin & ~HEAP_ALIGNMENT);
61+
// heap end tracking, used with sbrk
62+
heap_end = heap_begin;
63+
64+
65+
}
66+
67+
uintptr_t _move_symbols(void* sym_loc) {
4968

5069
/// read out size of symbols **before** moving them
5170
extern int _get_elf_section_datasize(const void*);
@@ -54,23 +73,25 @@ void _init_c_runtime()
5473

5574
/// move ELF symbols to safe area
5675
extern void _move_elf_syms_location(const void*, void*);
57-
_move_elf_syms_location(&_ELF_SYM_START_, &_end);
76+
_move_elf_syms_location(&_ELF_SYM_START_, sym_loc);
5877

59-
/// Initialize .bss section
60-
extern char _BSS_START_, _BSS_END_;
61-
streamset8(&_BSS_START_, 0, &_BSS_END_ - &_BSS_START_);
78+
return elfsym_size;
79+
80+
}
81+
82+
void _crt_sanity_checks() {
6283

63-
/// Initialize the heap before exceptions
64-
// set heap start at end of ELF symbols
65-
heap_begin = &_end + elfsym_size;
66-
// cache-align heap, because its not aligned
67-
heap_begin += HEAP_ALIGNMENT;
68-
heap_begin = (char*) ((uintptr_t)heap_begin & ~(uintptr_t) HEAP_ALIGNMENT);
69-
// heap end tracking, used with sbrk
70-
heap_end = heap_begin;
7184
// validate that heap is aligned
7285
int validate_heap_alignment =
73-
((uintptr_t)heap_begin & (uintptr_t) HEAP_ALIGNMENT) == 0;
86+
((uintptr_t)heap_begin & (uintptr_t) HEAP_ALIGNMENT) == 0;
87+
88+
assert(heap_begin >= (void*) &_end);
89+
assert(heap_end >= heap_begin);
90+
assert(validate_heap_alignment);
91+
};
92+
93+
void _init_c_runtime()
94+
{
7495

7596
/// initialize newlib I/O
7697
_REENT_INIT_PTR(_REENT);
@@ -89,10 +110,8 @@ void _init_c_runtime()
89110
extern void _init_elf_parser();
90111
_init_elf_parser();
91112

92-
// sanity checks
93-
assert(heap_begin >= &_end);
94-
assert(heap_end >= heap_begin);
95-
assert(validate_heap_alignment);
113+
_crt_sanity_checks();
114+
96115
}
97116

98117
// stack-protector

src/kernel/kernel_start.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,43 @@
2222

2323
#define MULTIBOOT_CMDLINE_LOC 0x7000
2424

25-
extern "C" void __init_sanity_checks();
26-
extern "C" void kernel_sanity_checks();
27-
extern "C" void _init_c_runtime();
28-
extern "C" void _init_syscalls();
29-
extern "C" void _init();
25+
extern "C" {
26+
void __init_sanity_checks();
27+
void kernel_sanity_checks();
28+
uintptr_t _multiboot_free_begin(uintptr_t boot_addr);
29+
uintptr_t _move_symbols(uintptr_t loc);
30+
void _init_bss();
31+
void _init_heap(uintptr_t);
32+
void _init_c_runtime();
33+
void _init_syscalls();
34+
void _init();
35+
extern uintptr_t _end;
36+
}
3037

3138
extern "C"
3239
void kernel_start(uintptr_t magic, uintptr_t addr)
3340
{
41+
3442
// generate checksums of read-only areas etc.
3543
__init_sanity_checks();
3644

45+
uintptr_t free_mem_begin = reinterpret_cast<uintptr_t>(&_end);
46+
3747
// Save multiboot string before symbols overwrite area after binary
3848
if (magic == MULTIBOOT_BOOTLOADER_MAGIC) {
39-
char* cmdline = reinterpret_cast<char*>(reinterpret_cast<multiboot_info_t*>(addr)->cmdline);
40-
strcpy(reinterpret_cast<char*>(MULTIBOOT_CMDLINE_LOC), cmdline);
41-
((multiboot_info_t*) addr)->cmdline = MULTIBOOT_CMDLINE_LOC;
49+
free_mem_begin = _multiboot_free_begin(addr);
4250
}
4351

52+
// Preserve symbols from the ELF binary
53+
free_mem_begin += _move_symbols(free_mem_begin);
54+
55+
56+
// Initialize zero-initialized vars
57+
_init_bss();
58+
59+
// Initialize heap
60+
_init_heap(free_mem_begin);
61+
4462
// Initialize stack-unwinder, call global constructors etc.
4563
_init_c_runtime();
4664

src/kernel/multiboot.cpp

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,72 @@
1616
// limitations under the License.
1717

1818
#include <os>
19+
#include <kprint>
1920
#include <boot/multiboot.h>
2021

2122
#define MYINFO(X,...) INFO("Kernel", X, ##__VA_ARGS__)
2223

24+
extern "C" {
25+
26+
extern uintptr_t _end;
27+
28+
// Function to deterimine the end of multiboot provided data
29+
// (e.g. multiboot's data area as offset to the _end symbol)
30+
uintptr_t _multiboot_free_begin(uintptr_t boot_addr){
31+
32+
multiboot_info_t* bootinfo = (multiboot_info_t*) boot_addr;
33+
uintptr_t multi_end = reinterpret_cast<uintptr_t>(&_end);
34+
35+
if (bootinfo->flags & MULTIBOOT_INFO_CMDLINE
36+
and bootinfo->cmdline > multi_end) {
37+
debug("* Multiboot cmdline end: 0x%x \n", bootinfo->cmdline);
38+
multi_end = bootinfo->cmdline;
39+
}
40+
41+
debug("* Multiboot end: 0x%x \n", multi_end);
42+
43+
44+
if (not bootinfo->mods_count)
45+
return multi_end;
46+
47+
multiboot_module_t* mods_list = (multiboot_module_t*)bootinfo->mods_addr;
48+
debug("* Module list @ %p \n",mods_list);
49+
50+
for (multiboot_module_t* mod = mods_list;
51+
mod < mods_list + bootinfo->mods_count;
52+
mod ++) {
53+
54+
debug("\t * Module @ %p \n", (void*)mod->mod_start);
55+
debug("\t * Args: %s \n ", (char*)mod->cmdline);
56+
debug("\t * End: %p \n ", (char*)mod->mod_end);
57+
58+
if (mod->mod_end > multi_end)
59+
multi_end = mod->mod_end;
60+
61+
}
62+
63+
debug("* Multiboot end: 0x%x \n", multi_end);
64+
return multi_end;
65+
}
66+
}
67+
2368
void OS::multiboot(uint32_t boot_magic, uint32_t boot_addr){
2469
MYINFO("Booted with multiboot");
25-
INFO2("* magic value: 0x%x Multiboot info at 0x%x", boot_magic, boot_addr);
2670

27-
multiboot_info_t* bootinfo = (multiboot_info_t*) boot_addr;
71+
INFO2("* magic value: 0x%x Multiboot info at 0x%x", boot_magic, boot_addr);
72+
bootinfo_ = (multiboot_info_t*) boot_addr;
2873

29-
if (! bootinfo->flags & MULTIBOOT_INFO_MEMORY) {
74+
if (! bootinfo_->flags & MULTIBOOT_INFO_MEMORY) {
3075
INFO2("* No memory info provided in multiboot info");
3176
return;
3277
}
3378

3479
uint32_t mem_low_start = 0;
35-
uint32_t mem_low_end = (bootinfo->mem_lower * 1024) - 1;
36-
uint32_t mem_low_kb = bootinfo->mem_lower;
80+
uint32_t mem_low_end = (bootinfo_->mem_lower * 1024) - 1;
81+
uint32_t mem_low_kb = bootinfo_->mem_lower;
3782
uint32_t mem_high_start = 0x100000;
38-
uint32_t mem_high_end = mem_high_start + (bootinfo->mem_upper * 1024) - 1;
39-
uint32_t mem_high_kb = bootinfo->mem_upper;
83+
uint32_t mem_high_end = mem_high_start + (bootinfo_->mem_upper * 1024) - 1;
84+
uint32_t mem_high_kb = bootinfo_->mem_upper;
4085

4186
OS::low_memory_size_ = mem_low_kb * 1024;
4287
OS::high_memory_size_ = mem_high_kb * 1024;
@@ -49,26 +94,39 @@ void OS::multiboot(uint32_t boot_magic, uint32_t boot_addr){
4994
mem_high_start, mem_high_end, mem_high_kb);
5095
INFO2("");
5196

52-
if (bootinfo->flags & MULTIBOOT_INFO_CMDLINE) {
53-
INFO2("* Booted with parameters @ %p: %s",(void*)bootinfo->cmdline, (char*)bootinfo->cmdline);
54-
cmdline = std::string((char*) bootinfo->cmdline);
97+
if (bootinfo_->flags & MULTIBOOT_INFO_CMDLINE) {
98+
INFO2("* Booted with parameters @ 0x%x: %s", bootinfo_->cmdline,
99+
reinterpret_cast<const char*>(bootinfo_->cmdline));
100+
cmdline = reinterpret_cast<const char*>(bootinfo_->cmdline);
55101
}
56102

57-
if (bootinfo->flags & MULTIBOOT_INFO_MEM_MAP) {
103+
if (bootinfo_->flags & MULTIBOOT_INFO_MEM_MAP) {
58104
INFO2("* Multiboot provided memory map (%i entries @ %p)",
59-
bootinfo->mmap_length / sizeof(multiboot_memory_map_t), (void*)bootinfo->mmap_addr);
60-
gsl::span<multiboot_memory_map_t> mmap { reinterpret_cast<multiboot_memory_map_t*>(bootinfo->mmap_addr),
61-
(int)(bootinfo->mmap_length / sizeof(multiboot_memory_map_t))};
105+
bootinfo_->mmap_length / sizeof(multiboot_memory_map_t), (void*)bootinfo_->mmap_addr);
106+
gsl::span<multiboot_memory_map_t> mmap { reinterpret_cast<multiboot_memory_map_t*>(bootinfo_->mmap_addr),
107+
(int)(bootinfo_->mmap_length / sizeof(multiboot_memory_map_t))};
62108

63109
for (auto map : mmap) {
64110
const char* str_type = map.type & MULTIBOOT_MEMORY_AVAILABLE ? "FREE" : "RESERVED";
65111
INFO2("\t 0x%08llx - 0x%08llx %s (%llu Kb.)",
66112
map.addr, map.addr + map.len - 1, str_type, map.len / 1024 );
67113

68114
if (not (map.type & MULTIBOOT_MEMORY_AVAILABLE)) {
69-
memory_map().assign_range({static_cast<uintptr_t>(map.addr), static_cast<uintptr_t>(map.addr + map.len - 1), "Reserved", "Multiboot / BIOS"});
115+
memory_map().assign_range({static_cast<uintptr_t>(map.addr),
116+
static_cast<uintptr_t>(map.addr + map.len - 1), "Reserved", "Multiboot / BIOS"});
70117
}
71118
}
72119
printf("\n");
73120
}
121+
122+
Span_mods mods = modules();
123+
124+
if (not mods.empty()) {
125+
MYINFO("OS loaded with %i modules", mods.size());
126+
for (auto mod : mods) {
127+
INFO2("* %s @ 0x%x - 0x%x, size: %ib",
128+
reinterpret_cast<char*>(mod.cmdline),
129+
mod.mod_start, mod.mod_end, mod.mod_end - mod.mod_start);
130+
}
131+
}
74132
}

0 commit comments

Comments
 (0)