Skip to content

Commit

Permalink
Add simple terminal FB output, cleanup build system
Browse files Browse the repository at this point in the history
  • Loading branch information
marv7000 committed Aug 9, 2024
1 parent f80ee9b commit 2ea95c1
Show file tree
Hide file tree
Showing 22 changed files with 390 additions and 142 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.29)
set(MENIX_SRC ${CMAKE_CURRENT_SOURCE_DIR})

# Project version.
set(MENIX_VERSION 0.1.6)
set(MENIX_VERSION 0.1.7)

# Project license.
set(MENIX_LICENSE "LGPL")
Expand All @@ -32,6 +32,7 @@ endif()

set(CMAKE_C_STANDARD 23)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_SYSTEM_NAME Generic)

project(menix
VERSION ${MENIX_VERSION}
Expand Down
28 changes: 17 additions & 11 deletions include/menix/boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@

#include <menix/common.h>
#include <menix/log.h>
#include <menix/memory/vm.h>
#include <menix/memory/pm.h>
#include <menix/video/fb.h>

#include "menix/memory/pm.h"

#define boot_log(fmt, ...) kmesg("[Boot] " fmt, ##__VA_ARGS__)

typedef struct
{
void* address; // Start of the file
Expand All @@ -21,13 +17,23 @@ typedef struct
// Information provided to the kernel by the boot protocol.
typedef struct
{
const char* cmd; // Command line
usize fb_num; // Amount of frame buffers
FrameBuffer* fb; // Available frame buffer(s)
usize pm_num; // Amount of memory map entries
const char* cmd; // Command line

usize fb_num; // Amount of frame buffers
FrameBuffer* fb; // Available frame buffer(s)

// This is architecture dependent, but almost every architecture should have it.
#if defined(CONFIG_arch_x86) || defined(CONFIG_arch_aarch64) || defined(CONFIG_arch_riscv64)
usize mm_num; // Amount of memory map entries
PhysMemory* memory_map; // Physical memory mapping
usize file_num; // Amount of files loaded
BootFile* files; // Available files
void* kernel_virt; // Virtual address of the kernel.
PhysAddr kernel_phys; // Physical address of the kernel.
void* phys_map; // Memory mapped lower memory address.
#endif

usize file_num; // Amount of files loaded
BootFile* files; // Available files

#ifdef CONFIG_acpi
void* acpi_rsdp; // ACPI RSDP table.
#endif
Expand Down
File renamed without changes.
11 changes: 11 additions & 0 deletions include/menix/io/terminal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Console/Terminal IO

#pragma once
#include <menix/common.h>
#include <menix/video/fb.h>

// Initializes the console with a framebuffer. This is optional. If `fb` is NULL,
// the console will only output to serial.
void terminal_init(FrameBuffer* fb);

void terminal_putchar(u32 ch);
11 changes: 11 additions & 0 deletions include/menix/util/builtin_font.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 12x8 Built-in font.

#pragma once
#include <menix/common.h>

#define FONT_WIDTH 8
#define FONT_HEIGHT 12

#define FONT_GLYPH_SIZE ((FONT_WIDTH * FONT_HEIGHT) / 8)

extern char builtin_font[256 * FONT_GLYPH_SIZE];
3 changes: 3 additions & 0 deletions kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ file(WRITE ${MENIX_MODULES} "#pragma once\n// This file is automatically generat

# Set toolchain.
include(${MENIX_SRC}/toolchain/compiler/${CMAKE_C_COMPILER_ID}.cmake)
include(${MENIX_SRC}/toolchain/compiler/common.cmake)
include(${MENIX_CONFIG_SRC})
include(${MENIX_SRC}/toolchain/arch/${MENIX_ARCH}.cmake)
include(${MENIX_SRC}/toolchain/arch/defaults.cmake)
Expand All @@ -28,6 +29,7 @@ include_directories(${MENIX_SRC}/kernel/arch/${MENIX_ARCH}/include/)

add_subdirectory(arch/${MENIX_ARCH_DIR})
add_subdirectory(boot)
add_subdirectory(io)
add_subdirectory(klibc)
add_subdirectory(memory)
add_subdirectory(mod)
Expand All @@ -39,6 +41,7 @@ add_subdirectory(video)
target_link_libraries(menix PUBLIC
menix_arch_${MENIX_ARCH_DIR}
menix_boot
menix_io
menix_klibc
menix_memory
menix_mod
Expand Down
10 changes: 1 addition & 9 deletions kernel/arch/x86/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,7 @@ add_architecture(x86
boot/interrupts.c
boot/idt.c
arch.c
serial.c
io/serial.c
vm.c
pm.c
)

add_option(page_size NUMBER 0x1000)

# add_option(smp BOOL ON)
add_option(max_cpus NUMBER 128)

require_option(efi)
require_option(acpi)
34 changes: 23 additions & 11 deletions kernel/arch/x86/arch.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
// x86 platform initialization

#include <menix/arch.h>
#include <menix/io/serial.h>
#include <menix/log.h>
#include <menix/memory/vm.h>
#include <menix/serial.h>

#include <gdt.h>
#include <idt.h>
#include <interrupts.h>

static Cpu* cpus;

void arch_early_init()
{
gdt_init();
Expand All @@ -19,6 +21,18 @@ void arch_early_init()

void arch_init(BootInfo* info)
{
// Initialize physical and virtual memory managers.
pm_init(info->phys_map, info->memory_map, info->mm_num);
vm_init(info->phys_map, info->kernel_phys, info->memory_map, info->mm_num);

// Print memory map.
kmesg("Physical memory map:\n");
for (usize i = 0; i < info->mm_num; i++)
{
kmesg(" [%u] 0x%p - 0x%p [%s]\n", i, info->memory_map[i].address,
info->memory_map[i].address + info->memory_map[i].length,
(info->memory_map[i].usage == PhysMemoryUsage_Free) ? "Usable" : "Reserved");
}
}

void arch_stop(BootInfo* info)
Expand All @@ -27,6 +41,14 @@ void arch_stop(BootInfo* info)
asm volatile("hlt");
}

Cpu* arch_current_cpu()
{
u64 id;
// The CPU ID is stored in GS (thread local memory).
asm volatile("mov %%gs:0, %0" : "=r"(id) : : "memory");
return &cpus[id];
}

void arch_dump_registers()
{
CpuRegisters regs;
Expand All @@ -46,7 +68,6 @@ void arch_dump_registers()
asm_get_register(regs.r13, r13);
asm_get_register(regs.r14, r14);
asm_get_register(regs.r15, r15);

asm_get_register(regs.cs, cs);
asm_get_register(regs.ss, ss);

Expand All @@ -56,12 +77,3 @@ void arch_dump_registers()
kmesg("r12: 0x%p r13: 0x%p r14: 0x%p r15: 0x%p\n", regs.r12, regs.r13, regs.r14, regs.r15);
kmesg("cs: 0x%p ss: 0x%p\n", regs.cs, regs.ss);
}

Cpu cpus[CONFIG_max_cpus];

Cpu* arch_current_cpu()
{
u64 id;
asm volatile("mov %%gs:0, %0" : "=r"(id) : : "memory");
return &cpus[id];
}
2 changes: 1 addition & 1 deletion kernel/arch/x86/serial.c → kernel/arch/x86/io/serial.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// x86 Serial interface

#include <menix/common.h>
#include <menix/serial.h>
#include <menix/io/serial.h>

#include <io.h>

Expand Down
3 changes: 1 addition & 2 deletions kernel/arch/x86/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ void pm_init(void* phys_base, PhysMemory* mem_map, usize num_entries)
}
}

kmesg("Initialized physical memory management\n Free memory = %u MiB\n",
(num_free_pages * CONFIG_page_size) / MiB);
kmesg("Initialized physical memory management, free memory = %u MiB\n", (num_free_pages * CONFIG_page_size) / MiB);
}

void pm_update_phys_base(void* phys_base)
Expand Down
92 changes: 43 additions & 49 deletions kernel/boot/boot_limine/limine_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <menix/arch.h>
#include <menix/boot.h>
#include <menix/common.h>
#include <menix/io/terminal.h>
#include <menix/log.h>
#include <menix/memory/alloc.h>
#include <menix/memory/pm.h>
Expand Down Expand Up @@ -39,19 +40,42 @@ LIMINE_REQUEST(dtb_request, LIMINE_DTB_REQUEST, 0); // Get device tree blob i
void kernel_boot()
{
arch_early_init();
boot_log("Initialized architecture\n");
boot_log("Booting using Limine protocol\n");

BootInfo info = {0};

// Get framebuffer.
kassert(framebuffer_request.response, "Unable to get a framebuffer!\n");
kmesg("Got frame buffer:\n");
// TODO: Convert to kalloc'ed memory.
FrameBuffer buffers[framebuffer_request.response->framebuffer_count];
info.fb_num = framebuffer_request.response->framebuffer_count;
info.fb = buffers;
for (usize i = 0; i < info.fb_num; i++)
{
const struct limine_framebuffer* buf = framebuffer_request.response->framebuffers[i];
buffers[i].base = buf->address;
buffers[i].width = buf->width;
buffers[i].height = buf->height;
buffers[i].bpp = buf->bpp;
buffers[i].pitch = buf->pitch;
buffers[i].red_shift = buf->red_mask_shift;
buffers[i].red_size = buf->red_mask_size;
buffers[i].green_shift = buf->green_mask_shift;
buffers[i].green_size = buf->green_mask_size;
buffers[i].blue_shift = buf->blue_mask_shift;
buffers[i].blue_size = buf->blue_mask_size;
}
// Check if we got a framebuffer to draw on and initialize console if we do.
if (info.fb && info.fb_num > 0)
terminal_init(info.fb);

// Get the memory map.
kassert(memmap_request.response, "Unable to get memory map!\n");
struct limine_memmap_response* const res = memmap_request.response;
boot_log("Bootloader provided memory map at 0x%p\n", res);
boot_log("Free blocks:\n", res);
kmesg("Bootloader provided memory map at 0x%p\n", res);

PhysMemory map[res->entry_count];
info.pm_num = res->entry_count;
info.mm_num = res->entry_count;
info.memory_map = map;

for (usize i = 0; i < res->entry_count; i++)
Expand All @@ -71,54 +95,51 @@ void kernel_boot()
case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE: map[i].usage = PhysMemoryUsage_Bootloader; break;
default: map[i].usage = PhysMemoryUsage_Unknown; break;
}

if (map[i].usage == PhysMemoryUsage_Free)
boot_log(" [%u] Address = 0x%p, Size = 0x%p\n", i, map[i].address, map[i].length);
}
// Make sure the first 4 GiB are identity mapped so we can write to "physical" memory.
kassert(hhdm_request.response, "Unable to get HHDM response!\n");
boot_log("HHDM offset: 0x%p\n", hhdm_request.response->offset);
kmesg("HHDM offset: 0x%p\n", hhdm_request.response->offset);
kassert(kernel_address_request.response, "Unable to get kernel address info!\n")
boot_log("Kernel loaded at: 0x%p (0x%p)\n", kernel_address_request.response->virtual_base,
kernel_address_request.response->physical_base);
kmesg("Kernel loaded at: 0x%p (0x%p)\n", kernel_address_request.response->virtual_base,
kernel_address_request.response->physical_base);

// Initialize virtual memory using the memory map we got.
pm_init((void*)hhdm_request.response->offset, map, res->entry_count);
vm_init((void*)hhdm_request.response->offset, (PhysAddr)kernel_address_request.response->physical_base, map,
res->entry_count);
info.kernel_phys = (PhysAddr)kernel_address_request.response->physical_base;
info.kernel_virt = (void*)kernel_address_request.response->virtual_base;
info.phys_map = (void*)hhdm_request.response->offset;

// Get boot timestamp.
kassert(boot_time_request.response, "Unable to get boot timestamp!\n");
boot_log("Boot timestamp: %u\n", (u32)boot_time_request.response->boot_time);
kmesg("Boot timestamp: %u\n", (u32)boot_time_request.response->boot_time);

#ifdef CONFIG_acpi
// Get ACPI RSDP table.
kassert(rsdp_request.response, "Unable to get ACPI RSDP table!\n");
boot_log("ACPI System Table at 0x%p\n", rsdp_request.response->address);
kmesg("ACPI System Table at 0x%p\n", rsdp_request.response->address);
info.acpi_rsdp = rsdp_request.response->address;
#endif

#ifdef CONFIG_open_firmware
kassert(dtb_request.response, "Unable to get device tree!\n");
boot_log("FDT blob at 0x%p\n", dtb_request.response->dtb_ptr);
kmesg("FDT blob at 0x%p\n", dtb_request.response->dtb_ptr);
info.fdt_blob = dtb_request.response->dtb_ptr;
#endif

// Get kernel file.
kassert(kernel_file_request.response, "Unable to get kernel file info!\n");
struct limine_kernel_file_response* const kernel_res = kernel_file_request.response;
boot_log("Kernel file loaded at: 0x%p, Size = 0x%X\n", kernel_res->kernel_file->address,
kernel_res->kernel_file->size);
kmesg("Kernel file loaded at: 0x%p, Size = 0x%X\n", kernel_res->kernel_file->address,
kernel_res->kernel_file->size);

self_set_kernel(kernel_res->kernel_file->address);

// Get command line.
boot_log("Command line: \"%s\"\n", kernel_res->kernel_file->cmdline);
kmesg("Command line: \"%s\"\n", kernel_res->kernel_file->cmdline);
info.cmd = kernel_res->kernel_file->cmdline;

// Get modules.
kassert(module_request.response, "Unable to get modules!\n");
boot_log("Got files:\n");
kmesg("Got files:\n");
const struct limine_module_response* module_res = module_request.response;
// TODO: Convert to kalloc'ed memory.
BootFile files[module_res->module_count];
Expand All @@ -128,39 +149,12 @@ void kernel_boot()
files[i].address = module_res->modules[i]->address;
files[i].size = module_res->modules[i]->size;
files[i].path = module_res->modules[i]->path;
boot_log(" Address = 0x%p, Size = 0x%p, Path = \"%s\"\n", files[i].address, files[i].size, files[i].path);
kmesg(" Address = 0x%p, Size = 0x%p, Path = \"%s\"\n", files[i].address, files[i].size, files[i].path);
}
info.file_num = module_res->module_count;
info.files = files;

// Get framebuffer.
kassert(framebuffer_request.response, "Unable to get a framebuffer!\n");
boot_log("Got frame buffer:\n");
// TODO: Convert to kalloc'ed memory.
FrameBuffer buffers[framebuffer_request.response->framebuffer_count];
info.fb_num = framebuffer_request.response->framebuffer_count;
info.fb = buffers;
for (usize i = 0; i < info.fb_num; i++)
{
const struct limine_framebuffer* buf = framebuffer_request.response->framebuffers[i];
buffers[i].base = buf->address;
buffers[i].width = buf->width;
buffers[i].height = buf->height;
buffers[i].bpp = buf->bpp;
buffers[i].pitch = buf->pitch;
buffers[i].red_shift = buf->red_mask_shift;
buffers[i].red_size = buf->red_mask_size;
buffers[i].green_shift = buf->green_mask_shift;
buffers[i].green_size = buf->green_mask_size;
buffers[i].blue_shift = buf->blue_mask_shift;
buffers[i].blue_size = buf->blue_mask_size;
boot_log(" [%i] Address = 0x%p, Resolution = %ux%ux%u\n", i, buffers[i].base, buffers[i].width,
buffers[i].height, buffers[i].bpp);
}

arch_init(&info);
boot_log("Handing control to main function\n");
kernel_main(&info);
boot_log("Got control back from main function\n");
arch_stop(&info);
}
6 changes: 6 additions & 0 deletions kernel/io/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Input/Output

include(${MENIX_UTIL_PATH})
add_library(menix_io
terminal.c
)
Loading

0 comments on commit 2ea95c1

Please sign in to comment.