Skip to content

Commit 8bcf1ea

Browse files
authored
Merge pull request #1293 from alfred-bratterud/dev
Multiboot modules + chainloading
2 parents fe3491d + 5e11225 commit 8bcf1ea

28 files changed

Lines changed: 619 additions & 117 deletions

api/kernel/os.hpp

Lines changed: 28 additions & 13 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,15 +37,16 @@ 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
/**
41-
* Returns the version of the OS from when
43+
* Returns the version of the OS from when
4244
* the service was built.
4345
**/
4446
static const std::string& version() noexcept
4547
{ return version_field; }
4648

47-
/**
49+
/**
4850
* Returns the commandline arguments provided,
4951
* if any, to the VM passed on by multiboot or
5052
* other mechanisms. The first argument is always
@@ -113,7 +115,7 @@ class OS {
113115
* The on_panic handler will be called directly after a panic,
114116
* or any condition which will deliberately cause the OS to become
115117
* unresponsive. After the handler is called, the OS goes to sleep.
116-
* This handler can thus be used to, for example, automatically
118+
* This handler can thus be used to, for example, automatically
117119
* have the OS restart on any crash.
118120
**/
119121
typedef void (*on_panic_func) ();
@@ -204,6 +206,22 @@ 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 < std::numeric_limits<int>::max());
215+
216+
return Span_mods{
217+
reinterpret_cast<multiboot_module_t*>(bootinfo_->mods_addr),
218+
static_cast<int>(bootinfo_->mods_count) };
219+
220+
}
221+
222+
return nullptr;
223+
}
224+
207225
private:
208226

209227
/** Process multiboot info. Called by 'start' if multibooted **/
@@ -216,15 +234,6 @@ class OS {
216234
static bool is_softreset_magic(uint32_t value);
217235
static void resume_softreset(intptr_t boot_addr);
218236

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-
228237
struct Plugin_struct {
229238
Plugin_struct(Plugin f, const char* n)
230239
: func_{f}, name_{n}
@@ -234,13 +243,19 @@ class OS {
234243
const char* name_;
235244
};
236245

246+
static constexpr int PAGE_SHIFT = 12;
247+
static bool power_;
248+
static bool boot_sequence_passed_;
249+
static MHz cpu_mhz_;
250+
static std::string version_field;
237251
static std::vector<Plugin_struct> plugins_;
238-
239252
static uintptr_t low_memory_size_;
240253
static uintptr_t high_memory_size_;
241254
static uintptr_t memory_end_;
242255
static uintptr_t heap_max_;
243256
static const uintptr_t elf_binary_size_;
257+
static multiboot_info_t* bootinfo_;
258+
static std::string cmdline;
244259

245260
// Prohibit copy and move operations
246261
OS(OS&) = delete;
File renamed without changes.

etc/scripts/grubify.sh

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
KERNEL=${1-build/test_grub}
33
DISK=${DISK-$KERNEL.grub.img}
44
MOUNTDIR=${MOUNTDIR-/mnt}
5-
MOUNT_OPTS="sync,rw"
6-
BLOCKCCOUNT=10000
5+
MOUNT_OPTS="rw"
6+
7+
# GRUB uses roughly 4.6 Mb of disk
8+
GRUB_KB=5000
9+
710
set -e
811

912
function unmount {
@@ -23,18 +26,25 @@ function clean {
2326

2427

2528
function create_disk {
26-
echo -e ">>> Creating FAT file system on $DISK with $BLOCKSIZE blocks"
27-
# NOTE: mkfs with the '-C' option creates the disk before creating FS
28-
# fallocate -l 10MiB $DISK
2929

3030
if [ -f $DISK ]
3131
then
3232
echo -e ">>> $DISK allready exists. Preserving existing image as $DISK.bak"
3333
mv $DISK $DISK.bak
3434
fi
3535

36+
# Kernel size in Kb
37+
KERN_KB=$(( ($(stat -c%s "$KERNEL") / 1024) ))
38+
39+
# Estimate some overhead for the FAT
40+
FAT_KB=$(( ($KERN_KB + $GRUB_KB) / 10 ))
3641

37-
mkfs.fat -C $DISK $BLOCKCCOUNT
42+
DISK_KB=$(( $KERN_KB + $GRUB_KB + $FAT_KB ))
43+
44+
echo ">>> Estimated disk size: $GRUB_KB Kb GRUB + $KERN_KB Kb kernel + $FAT_KB Kb FAT = $DISK_KB Kb"
45+
echo ">>> Creating FAT file system on $DISK"
46+
47+
mkfs.fat -C $DISK $DISK_KB
3848
}
3949

4050
function mount_loopback {
@@ -58,6 +68,7 @@ function mount_loopback {
5868
function copy_kernel {
5969
echo ">>> Copying kernel '$KERNEL' to $MOUNTDIR/boot/includeos_service"
6070
sudo cp $KERNEL $MOUNTDIR/boot/includeos_service
71+
sync
6172
}
6273

6374
function build {
@@ -130,6 +141,9 @@ copy_kernel
130141
echo -e ">>> Running grub install"
131142
sudo grub-install --target=i386-pc --force --boot-directory $MOUNTDIR/boot/ $LOOP
132143

144+
echo -e ">>> Synchronize file cache"
145+
sync
146+
133147
unmount
134148

135149
echo -e ">>> Done. You can now boot $DISK"

src/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ add_custom_command(
2727
# TODO: i wanted to use a glob, but then found out that not everything is included
2828
set(OS_OBJECTS
2929
kernel/kernel_start.cpp kernel/sanity_checks.cpp kernel/syscalls.cpp
30-
kernel/irq_manager.cpp
30+
kernel/irq_manager.cpp kernel/multiboot.cpp
3131
kernel/os.cpp kernel/cpuid.cpp kernel/memmap.cpp kernel/pci_manager.cpp
3232
kernel/heap.cpp kernel/service_stub.cpp kernel/main_call.cpp
3333
kernel/elf.cpp kernel/terminal.cpp kernel/terminal_disk.cpp
@@ -37,7 +37,7 @@ set(OS_OBJECTS
3737
util/memstream.c util/async.cpp util/statman.cpp util/logger.cpp
3838
util/os_statman.cpp util/sha1.cpp
3939
util/syslog_facility.cpp util/syslogd.cpp util/uri.cpp util/percent_encoding.cpp
40-
util/tar.cpp util/path_to_regex.cpp
40+
util/tar.cpp util/path_to_regex.cpp util/elf_binary.cpp
4141
crt/c_abi.c crt/string.c crt/quick_exit.cpp crt/cxx_abi.cpp
4242
hw/ide.cpp hw/pci_device.cpp hw/ps2.cpp hw/serial.cpp hw/serial1.cpp
4343
hw/cmos.cpp hw/block_device.cpp hw/msi.cpp hw/pci_msi.cpp

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/elf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include <string>
2525
#include <unistd.h>
2626
#include <vector>
27-
#include "../../vmbuild/elf.h"
27+
#include <util/elf.h>
2828

2929
static const char* boot_stringz = "Bootloader area";
3030
extern "C" char _ELF_START_;

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

0 commit comments

Comments
 (0)