|
@@ -19,6 +19,7 @@
|
|
|
|
|
|
#include <boot/multiboot.h>
|
|
|
#include <common.h>
|
|
|
+#include <log.h>
|
|
|
#include <cpu.h>
|
|
|
#include <memory.h>
|
|
|
#include <heap.h>
|
|
@@ -35,19 +36,53 @@
|
|
|
#include <module.h>
|
|
|
#include <exec/elf.h>
|
|
|
|
|
|
-#define MAX_CMDLINE_LENGTH 256
|
|
|
+#define DO_TASK(x, ...) x(__VA_ARGS__); advance_progress()
|
|
|
|
|
|
-extern bool_t video_initialized;
|
|
|
+#define MAX_CMDLINE_LENGTH 256
|
|
|
|
|
|
static char cmdline[MAX_CMDLINE_LENGTH] = "";
|
|
|
static uintptr_t lowest_physical = 0;
|
|
|
static multiboot_tag_mmap_t *mmap = NULL;
|
|
|
static multiboot_tag_sections_t *kernel_sections = NULL;
|
|
|
+static size_t tasks_completed = 0, num_tasks = 12;
|
|
|
+static const char *manager_path = "";
|
|
|
|
|
|
+bool_t video_initialized = FALSE;
|
|
|
const elf32_symbol_t *kernel_symtab = NULL;
|
|
|
dword_t kernel_symcount = 0;
|
|
|
const char *kernel_strtab = NULL;
|
|
|
|
|
|
+void *get_kernel_symbol(const char *name)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < kernel_symcount; i++)
|
|
|
+ {
|
|
|
+ if (strcmp(name, &kernel_strtab[kernel_symtab[i].st_name]) == 0)
|
|
|
+ {
|
|
|
+ return (void*)kernel_symtab[i].st_value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+const char *lookup_kernel_symbol_name(uintptr_t address)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < kernel_symcount; i++)
|
|
|
+ {
|
|
|
+ if (address >= kernel_symtab[i].st_value && address < (kernel_symtab[i].st_value + kernel_symtab[i].st_size))
|
|
|
+ {
|
|
|
+ return &kernel_strtab[kernel_symtab[i].st_name];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static dword_t __attribute__((__noreturn__)) system_idle_thread(void *param)
|
|
|
{
|
|
|
UNUSED_PARAMETER(param);
|
|
@@ -85,6 +120,7 @@ static void scan_multiboot_info(multiboot_tag_t *mboot)
|
|
|
{
|
|
|
multiboot_tag_module_t *module = (multiboot_tag_module_t*)tag;
|
|
|
if (module->mod_end > lowest_physical) lowest_physical = module->mod_end;
|
|
|
+ num_tasks++;
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -145,117 +181,149 @@ static bool_t load_kernel_symbols()
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
-void *get_kernel_symbol(const char *name)
|
|
|
+static void setup_memory_management(void)
|
|
|
{
|
|
|
- int i;
|
|
|
+ if (!mmap) KERNEL_CRASH("The bootloader failed to supply a memory map");
|
|
|
+ memory_init(mmap, PAGE_ALIGN_UP(lowest_physical));
|
|
|
+ heap_init();
|
|
|
|
|
|
- for (i = 0; i < kernel_symcount; i++)
|
|
|
+ map_memory_internal((void*)TEXT_VIDEO_MEMORY,
|
|
|
+ (void*)TEXT_VIDEO_MEMORY,
|
|
|
+ TEXT_HEIGHT * TEXT_WIDTH * sizeof(word_t),
|
|
|
+ PAGE_PRESENT | PAGE_WRITABLE);
|
|
|
+}
|
|
|
+
|
|
|
+static void parse_command_line(void)
|
|
|
+{
|
|
|
+ static char cmdline_copy[MAX_CMDLINE_LENGTH];
|
|
|
+ strcpy(cmdline_copy, cmdline);
|
|
|
+
|
|
|
+ char *token;
|
|
|
+ for (token = strtok(cmdline_copy, " "); token != NULL; token = strtok(NULL, " "))
|
|
|
{
|
|
|
- if (strcmp(name, &kernel_strtab[kernel_symtab[i].st_name]) == 0)
|
|
|
+ char *separator = strchr(token, ':');
|
|
|
+ if (separator == NULL) continue;
|
|
|
+
|
|
|
+ char *value = separator + 1;
|
|
|
+ *separator = '\0';
|
|
|
+
|
|
|
+ if (strcmp(token, "manager") == 0)
|
|
|
{
|
|
|
- return (void*)kernel_symtab[i].st_value;
|
|
|
+ manager_path = value;
|
|
|
}
|
|
|
- }
|
|
|
+ else if (strcmp(token, "debug") == 0)
|
|
|
+ {
|
|
|
+ char *ptr = strchr(value, ',');
|
|
|
|
|
|
- return NULL;
|
|
|
+ if (ptr)
|
|
|
+ {
|
|
|
+ *ptr = '\0';
|
|
|
+ log_level_t min_level = *(ptr + 1) - '0';
|
|
|
+ if (min_level >= LOG_DEBUG || min_level <= LOG_CRITICAL) debug_min_level = min_level;
|
|
|
+ }
|
|
|
+
|
|
|
+ debug_channel = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void kernel_main(uintptr_t mboot_tags, size_t mboot_size)
|
|
|
+static handle_t start_system_manager(void)
|
|
|
{
|
|
|
- extern int _end;
|
|
|
+ char *root_disk = strdup(manager_path);
|
|
|
+ char *slash = strchr(root_disk, '/');
|
|
|
+ if (slash == NULL) KERNEL_CRASH("Invalid or missing system manager path");
|
|
|
+ *slash = 0;
|
|
|
|
|
|
- int i = 0;
|
|
|
- const char *manager_path = "";
|
|
|
+ log_write(LOG_NORMAL, "Mounting root disk: %s\n", root_disk);
|
|
|
+ dword_t ret = syscall_mount(root_disk, root_disk, NULL, MOUNT_FLAG_READONLY);
|
|
|
+ if (ret != ERR_SUCCESS) KERNEL_CRASH("Cannot mount root disk");
|
|
|
+ free(root_disk);
|
|
|
|
|
|
- pre_initialization();
|
|
|
+ handle_t manager_process;
|
|
|
+ handle_t main_thread;
|
|
|
+
|
|
|
+ process_params_t parameters;
|
|
|
+ parameters.command_line = cmdline;
|
|
|
+ parameters.standard_input = INVALID_HANDLE;
|
|
|
+ parameters.standard_output = INVALID_HANDLE;
|
|
|
+ parameters.standard_error = INVALID_HANDLE;
|
|
|
|
|
|
- clearscreen();
|
|
|
- for (i = 0; i < 80; i++) putchar('-');
|
|
|
- puts("The Monolithium Kernel 0.1 - By Alexander Andrejevic");
|
|
|
- for (i = 0; i < 80; i++) putchar('-');
|
|
|
+ log_write(LOG_NORMAL, "Starting the system manager: %s\n", manager_path);
|
|
|
+ ret = syscall_create_process(manager_path, 0, ¶meters, &manager_process, &main_thread);
|
|
|
+ if (ret != ERR_SUCCESS) KERNEL_CRASH("Cannot start system manager");
|
|
|
|
|
|
- lowest_physical = PAGE_ALIGN_UP((uintptr_t)&_end) - 0x7FF00000;
|
|
|
- if ((mboot_tags + mboot_size) > lowest_physical) lowest_physical = mboot_tags + mboot_size;
|
|
|
+ syscall_close_object(main_thread);
|
|
|
+ return manager_process;
|
|
|
+}
|
|
|
|
|
|
- multiboot_tag_t *mboot = (multiboot_tag_t*)(PAGE_ALIGN_UP((uintptr_t)&_end) + PAGE_OFFSET(mboot_tags));
|
|
|
- map_memory_internal((void*)mboot_tags, mboot, mboot_size, PAGE_PRESENT | PAGE_WRITABLE);
|
|
|
- scan_multiboot_info(mboot);
|
|
|
+static void draw_progress_bar(void)
|
|
|
+{
|
|
|
+ static const char text[] = "The Monolithium kernel is loading, please wait...";
|
|
|
|
|
|
- if (!mmap) KERNEL_CRASH("The bootloader failed to supply a memory map");
|
|
|
- memory_init(mmap, PAGE_ALIGN_UP(lowest_physical));
|
|
|
- heap_init();
|
|
|
+ word_t *video_mem = (word_t*)(video_initialized ? VIDEO_MEMORY : TEXT_VIDEO_MEMORY);
|
|
|
+ memset(video_mem, 0x00, TEXT_HEIGHT * TEXT_WIDTH * sizeof(word_t));
|
|
|
|
|
|
- map_memory_internal((void*)TEXT_VIDEO_MEMORY,
|
|
|
- (void*)TEXT_VIDEO_MEMORY,
|
|
|
- TEXT_HEIGHT * TEXT_WIDTH * sizeof(word_t),
|
|
|
- PAGE_PRESENT | PAGE_WRITABLE);
|
|
|
+ int i;
|
|
|
+ size_t length = sizeof(text) - 1;
|
|
|
+ size_t text_start = 10 * TEXT_WIDTH + (TEXT_WIDTH - length) / 2;
|
|
|
+ for (i = 0; i < length; i++) video_mem[text_start + i] = text[i] | 0x0700;
|
|
|
|
|
|
- if (kernel_sections) load_kernel_symbols();
|
|
|
+ video_mem[11 * TEXT_WIDTH + 14] = 0x07DA;
|
|
|
+ for (i = 15; i < TEXT_WIDTH - 15; i++) video_mem[11 * TEXT_WIDTH + i] = 0x07C4;
|
|
|
+ video_mem[12 * TEXT_WIDTH - 15] = 0x07BF;
|
|
|
|
|
|
- printf("%-70s", "Initializing devices...");
|
|
|
- device_init();
|
|
|
- set_text_color(TEXT_COLOR_GREEN | TEXT_COLOR_STRONG);
|
|
|
- puts("done");
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
+ video_mem[12 * TEXT_WIDTH + 14] = video_mem[13 * TEXT_WIDTH - 15] = 0x07B3;
|
|
|
|
|
|
- char *token;
|
|
|
- for (token = strtok(cmdline, " "); token != NULL; token = strtok(NULL, " "))
|
|
|
- {
|
|
|
- char *separator = strchr(token, ':');
|
|
|
- if (separator == NULL) continue;
|
|
|
+ video_mem[13 * TEXT_WIDTH + 14] = 0x07C0;
|
|
|
+ for (i = 15; i < TEXT_WIDTH - 15; i++) video_mem[13 * TEXT_WIDTH + i] = 0x07C4;
|
|
|
+ video_mem[14 * TEXT_WIDTH - 15] = 0x07D9;
|
|
|
+}
|
|
|
|
|
|
- char *value = separator + 1;
|
|
|
- *separator = '\0';
|
|
|
+static void advance_progress(void)
|
|
|
+{
|
|
|
+ word_t *video_mem = (word_t*)(video_initialized ? VIDEO_MEMORY : TEXT_VIDEO_MEMORY);
|
|
|
+ size_t old_status = tasks_completed * 50 / num_tasks;
|
|
|
+ size_t new_status = (tasks_completed + 1) * 50 / num_tasks;
|
|
|
|
|
|
- if (strcmp(token, "manager") == 0) manager_path = value;
|
|
|
- }
|
|
|
+ int i;
|
|
|
+ for (i = old_status; i < new_status; i++) video_mem[12 * TEXT_WIDTH + i + 15] = 0x7020;
|
|
|
+ tasks_completed++;
|
|
|
+}
|
|
|
|
|
|
- printf("%-70s", "Initializing timer...");
|
|
|
- timer_init();
|
|
|
- set_text_color(TEXT_COLOR_GREEN | TEXT_COLOR_STRONG);
|
|
|
- puts("done");
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
-
|
|
|
- printf("%-70s", "Initializing clock...");
|
|
|
- clock_init();
|
|
|
- set_text_color(TEXT_COLOR_GREEN | TEXT_COLOR_STRONG);
|
|
|
- puts("done");
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
-
|
|
|
- printf("%-70s", "Initializing processes...");
|
|
|
- process_init();
|
|
|
- set_text_color(TEXT_COLOR_GREEN | TEXT_COLOR_STRONG);
|
|
|
- puts("done");
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
-
|
|
|
- printf("%-70s", "Initializing threads...");
|
|
|
- thread_init();
|
|
|
- set_text_color(TEXT_COLOR_GREEN | TEXT_COLOR_STRONG);
|
|
|
- puts("done");
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
+void kernel_main(uintptr_t mboot_tags, size_t mboot_size)
|
|
|
+{
|
|
|
+ log_write(LOG_NORMAL, "Monolithium 0.1\n");
|
|
|
|
|
|
- thread_t *idle;
|
|
|
- ASSERT(create_system_thread(system_idle_thread, 0, THREAD_PRIORITY_IDLE, 0, NULL, &idle) == ERR_SUCCESS);
|
|
|
+ pre_initialization();
|
|
|
+ log_write(LOG_NORMAL, "Pre-initialization complete\n");
|
|
|
+
|
|
|
+ draw_progress_bar();
|
|
|
|
|
|
- printf("%-70s", "Initializing users...");
|
|
|
- user_init();
|
|
|
- set_text_color(TEXT_COLOR_GREEN | TEXT_COLOR_STRONG);
|
|
|
- puts("done");
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
+ extern int _end;
|
|
|
+ lowest_physical = PAGE_ALIGN_UP((uintptr_t)&_end) - 0x7FF00000;
|
|
|
+ if ((mboot_tags + mboot_size) > lowest_physical) lowest_physical = mboot_tags + mboot_size;
|
|
|
|
|
|
- printf("%s", "Scanning the PCI bus...\n");
|
|
|
- pci_init();
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
+ multiboot_tag_t *mboot = (multiboot_tag_t*)(PAGE_ALIGN_UP((uintptr_t)&_end) + PAGE_OFFSET(mboot_tags));
|
|
|
+ map_memory_internal((void*)mboot_tags, mboot, mboot_size, PAGE_PRESENT | PAGE_WRITABLE);
|
|
|
+ DO_TASK(scan_multiboot_info, mboot);
|
|
|
+ DO_TASK(parse_command_line);
|
|
|
+ DO_TASK(setup_memory_management);
|
|
|
+ if (kernel_sections) load_kernel_symbols();
|
|
|
+ DO_TASK(device_init);
|
|
|
+ DO_TASK(timer_init);
|
|
|
+ DO_TASK(clock_init);
|
|
|
+ DO_TASK(process_init);
|
|
|
+ DO_TASK(thread_init);
|
|
|
|
|
|
- printf("%-70s", "Initializing video subsystem...");
|
|
|
- video_init();
|
|
|
+ thread_t *idle;
|
|
|
+ ASSERT(create_system_thread(system_idle_thread, 0, THREAD_PRIORITY_IDLE, 0, NULL, &idle) == ERR_SUCCESS);
|
|
|
+
|
|
|
+ DO_TASK(user_init);
|
|
|
+ DO_TASK(pci_init);
|
|
|
+ DO_TASK(video_init);
|
|
|
unmap_memory_internal((void*)TEXT_VIDEO_MEMORY, TEXT_HEIGHT * TEXT_WIDTH * sizeof(word_t));
|
|
|
video_initialized = TRUE;
|
|
|
|
|
|
- set_text_color(TEXT_COLOR_GREEN | TEXT_COLOR_STRONG);
|
|
|
- puts("done");
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
-
|
|
|
multiboot_tag_t *tag;
|
|
|
for (tag = mboot; tag->type != MULTIBOOT_INFO_END; tag = (multiboot_tag_t*)(((uintptr_t)tag + tag->size + 7) & ~7))
|
|
|
{
|
|
@@ -269,54 +337,21 @@ void kernel_main(uintptr_t mboot_tags, size_t mboot_size)
|
|
|
dword_t ret = module_load_from_physical(mod, module->string);
|
|
|
if (ret == ERR_SUCCESS)
|
|
|
{
|
|
|
- printf("Loaded module %s at 0x%08X\n", mod->name, mod->base_address);
|
|
|
+ log_write(LOG_NORMAL, "Loaded module %s at 0x%08X\n", mod->name, mod->base_address);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (mod->name) printf("Cannot load module %s: %s\n", mod->name, get_error_string(ret));
|
|
|
- else printf("Cannot load module from physical address 0x%08X: %s\n", module->mod_start, get_error_string(ret));
|
|
|
+ if (mod->name) log_write(LOG_ERROR, "Cannot load module %s: %s\n", mod->name, get_error_string(ret));
|
|
|
+ else log_write(LOG_ERROR, "Cannot load module from physical address 0x%08X: %s\n", module->mod_start, get_error_string(ret));
|
|
|
free(mod);
|
|
|
}
|
|
|
|
|
|
+ advance_progress();
|
|
|
// TODO: Reclaim pages
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- char *root_disk = strdup(manager_path);
|
|
|
- char *slash = strchr(root_disk, '/');
|
|
|
- if (slash == NULL) KERNEL_CRASH("Invalid or missing system manager path");
|
|
|
- *slash = 0;
|
|
|
-
|
|
|
- char message[256] = "Mounting root disk ";
|
|
|
- strcat(message, root_disk);
|
|
|
- strcat(message, "...");
|
|
|
- printf("%-70s", message);
|
|
|
-
|
|
|
- dword_t ret = syscall_mount(root_disk, root_disk, NULL, MOUNT_FLAG_READONLY);
|
|
|
- if (ret != ERR_SUCCESS) KERNEL_CRASH("Cannot mount root disk");
|
|
|
-
|
|
|
- free(root_disk);
|
|
|
-
|
|
|
- set_text_color(TEXT_COLOR_GREEN | TEXT_COLOR_STRONG);
|
|
|
- puts("done");
|
|
|
- set_text_color(TEXT_COLOR_RED | TEXT_COLOR_GREEN | TEXT_COLOR_BLUE);
|
|
|
-
|
|
|
- sprintf(message, "Starting system manager: %s", manager_path);
|
|
|
- printf("%-70s", message);
|
|
|
-
|
|
|
- handle_t manager_process;
|
|
|
- handle_t main_thread;
|
|
|
-
|
|
|
- process_params_t parameters;
|
|
|
- parameters.command_line = "";
|
|
|
- parameters.standard_input = INVALID_HANDLE;
|
|
|
- parameters.standard_output = INVALID_HANDLE;
|
|
|
- parameters.standard_error = INVALID_HANDLE;
|
|
|
-
|
|
|
- ret = syscall_create_process(manager_path, 0, ¶meters, &manager_process, &main_thread);
|
|
|
- if (ret != ERR_SUCCESS) KERNEL_CRASH("Cannot start system manager");
|
|
|
-
|
|
|
- syscall_close_object(main_thread);
|
|
|
+ handle_t manager_process = DO_TASK(start_system_manager);
|
|
|
syscall_wait_process(manager_process, NO_TIMEOUT);
|
|
|
|
|
|
KERNEL_CRASH("The system manager has stopped working");
|