update main #1

Merged
Sinipelto merged 240 commits from Bananymous/banan-os:main into main 2023-11-20 13:20:51 +02:00
10 changed files with 185 additions and 153 deletions
Showing only changes of commit be3efb0b92 - Show all commits

View File

@ -4,6 +4,7 @@
#include <kernel/LockGuard.h> #include <kernel/LockGuard.h>
#include <kernel/Memory/kmalloc.h> #include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
#include <kernel/multiboot2.h>
extern uint8_t g_kernel_start[]; extern uint8_t g_kernel_start[];
extern uint8_t g_kernel_end[]; extern uint8_t g_kernel_end[];
@ -138,6 +139,16 @@ namespace Kernel
// Map (0 -> phys_kernel_end) to (KERNEL_OFFSET -> virt_kernel_end) // Map (0 -> phys_kernel_end) to (KERNEL_OFFSET -> virt_kernel_end)
map_range_at(0, KERNEL_OFFSET, (uintptr_t)g_kernel_end - KERNEL_OFFSET, Flags::ReadWrite | Flags::Present); map_range_at(0, KERNEL_OFFSET, (uintptr_t)g_kernel_end - KERNEL_OFFSET, Flags::ReadWrite | Flags::Present);
// Map multiboot info
vaddr_t multiboot_data_start = (vaddr_t)g_multiboot2_info & PAGE_ADDR_MASK;
vaddr_t multiboot_data_end = (vaddr_t)g_multiboot2_info + g_multiboot2_info->total_size;
map_range_at(
V2P(multiboot_data_start),
multiboot_data_start,
multiboot_data_end - multiboot_data_start,
Flags::ReadWrite | Flags::Present
);
// Map executable kernel memory as executable // Map executable kernel memory as executable
map_range_at( map_range_at(
V2P(g_kernel_execute_start), V2P(g_kernel_execute_start),

View File

@ -1,11 +1,3 @@
# Declare constants for the multiboot header
.set ALIGN, 1<<0 # align loaded modules on page boundaries
.set MEMINFO, 1<<1 # provide memory map
.set VIDEOINFO, 1<<2 # provide video info
.set MB_FLAGS, ALIGN | MEMINFO | VIDEOINFO # this is the Multiboot 'flag' field
.set MB_MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
.set MB_CHECKSUM, -(MB_MAGIC + MB_FLAGS) #checksum of above, to prove we are multiboot
.set PG_PRESENT, 1<<0 .set PG_PRESENT, 1<<0
.set PG_READ_WRITE, 1<<1 .set PG_READ_WRITE, 1<<1
.set PG_PAGE_SIZE, 1<<7 .set PG_PAGE_SIZE, 1<<7
@ -15,19 +7,37 @@
.code32 .code32
# Multiboot header # multiboot2 header
.section .multiboot, "aw" .section .multiboot, "aw"
.align 4 multiboot2_start:
.long MB_MAGIC .align 8
.long MB_FLAGS .long 0xE85250D6
.long MB_CHECKSUM
.skip 20
.long 0 .long 0
.long 800 .long multiboot2_end - multiboot2_start
.long 600 .long -(0xE85250D6 + (multiboot2_end - multiboot2_start))
# framebuffer tag
.align 8
.short 5
.short 0
.long 20
.long 1920
.long 1080
.long 32 .long 32
# legacy start
.align 8
.short 3
.short 0
.long 12
.long V2P(_start)
.align 8
.short 0
.short 0
.long 8
multiboot2_end:
.section .bss, "aw", @nobits .section .bss, "aw", @nobits
# Create stack # Create stack
.global g_boot_stack_bottom .global g_boot_stack_bottom
@ -40,11 +50,11 @@
g_kernel_cmdline: g_kernel_cmdline:
.skip 4096 .skip 4096
.global g_multiboot_info .global g_multiboot2_info
g_multiboot_info: g_multiboot2_info:
.skip 8 .skip 8
.global g_multiboot_magic .global g_multiboot2_magic
g_multiboot_magic: g_multiboot2_magic:
.skip 8 .skip 8
.section .data .section .data
@ -119,19 +129,6 @@ check_requirements:
.exit: .exit:
jmp system_halt jmp system_halt
copy_kernel_commandline:
pushl %esi
pushl %edi
movl V2P(g_multiboot_info), %esi
addl $16, %esi
movl (%esi), %esi
movl $1024, %ecx
movl $V2P(g_kernel_cmdline), %edi
rep movsl
popl %edi
popl %esi
ret
enable_sse: enable_sse:
movl %cr0, %eax movl %cr0, %eax
andw $0xFFFB, %ax andw $0xFFFB, %ax
@ -170,10 +167,9 @@ initialize_paging:
_start: _start:
# Initialize stack and multiboot info # Initialize stack and multiboot info
movl $V2P(g_boot_stack_top), %esp movl $V2P(g_boot_stack_top), %esp
movl %eax, V2P(g_multiboot_magic) movl %eax, V2P(g_multiboot2_magic)
movl %ebx, V2P(g_multiboot_info) movl %ebx, V2P(g_multiboot2_info)
call copy_kernel_commandline
call check_requirements call check_requirements
call enable_sse call enable_sse
@ -201,7 +197,7 @@ long_mode:
jmp *%rcx jmp *%rcx
higher_half: higher_half:
addq $KERNEL_OFFSET, g_multiboot_info addq $KERNEL_OFFSET, g_multiboot2_info
# call global constuctors # call global constuctors
call _init call _init

View File

@ -1,57 +0,0 @@
#pragma once
#include <stdint.h>
#define MULTIBOOT_FLAGS_FRAMEBUFFER (1 << 12)
#define MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_TEXT 2
struct framebuffer_info_t
{
uint64_t addr;
uint32_t pitch;
uint32_t width;
uint32_t height;
uint8_t bpp;
uint8_t type;
uint8_t color_info[6];
};
struct multiboot_memory_map_t
{
uint32_t size;
uint64_t base_addr;
uint64_t length;
uint32_t type;
} __attribute__((packed));
// https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format
struct multiboot_info_t
{
uint32_t flags;
uint32_t mem_lower;
uint32_t mem_upper;
uint32_t boot_device;
uint32_t cmdline;
uint32_t mods_count;
uint32_t mods_addr;
uint32_t syms[4];
uint32_t mmap_length;
uint32_t mmap_addr;
uint32_t drives_length;
uint32_t drives_addr;
uint32_t config_table;
uint32_t boot_loader_name;
uint32_t apm_table;
uint32_t vbe_control_info;
uint32_t vbe_mode_info;
uint16_t vbe_mode;
uint16_t vbe_interface_seg;
uint16_t vbe_interface_off;
uint16_t vbe_interface_len;
framebuffer_info_t framebuffer;
};
extern "C" multiboot_info_t* g_multiboot_info;
extern "C" uint32_t g_multiboot_magic;

View File

@ -0,0 +1,75 @@
#pragma once
#include <stdint.h>
// https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information
#define MULTIBOOT2_TAG_END 0
#define MULTIBOOT2_TAG_CMDLINE 1
#define MULTIBOOT2_TAG_MMAP 6
#define MULTIBOOT2_TAG_FRAMEBUFFER 8
#define MULTIBOOT2_TAG_OLD_RSDP 14
#define MULTIBOOT2_TAG_NEW_RSDP 15
#define MULTIBOOT2_FRAMEBUFFER_TYPE_RGB 1
struct multiboot2_tag_t
{
uint32_t type;
uint32_t size;
multiboot2_tag_t* next() { return (multiboot2_tag_t*)((uintptr_t)this + ((size + 7) & ~7)); }
} __attribute__((packed));
struct multiboot2_cmdline_tag_t : public multiboot2_tag_t
{
char cmdline[];
} __attribute__((packed));
struct multiboot2_mmap_entry_t
{
uint64_t base_addr;
uint64_t length;
uint32_t type;
uint32_t reserved;
} __attribute__((packed));
struct multiboot2_mmap_tag_t : public multiboot2_tag_t
{
uint32_t entry_size;
uint32_t entry_version;
multiboot2_mmap_entry_t entries[];
} __attribute__((packed));
struct multiboot2_framebuffer_tag_t : public multiboot2_tag_t
{
uint64_t framebuffer_addr;
uint32_t framebuffer_pitch;
uint32_t framebuffer_width;
uint32_t framebuffer_height;
uint8_t framebuffer_bpp;
uint8_t framebuffer_type;
uint8_t reserved;
} __attribute__((packed));
struct multiboot2_rsdp_tag_t : public multiboot2_tag_t
{
uint8_t data[];
} __attribute__((packed));
struct multiboot2_info_t
{
uint32_t total_size;
uint32_t reserved;
multiboot2_tag_t tags[];
} __attribute__((packed));
extern "C" multiboot2_info_t* g_multiboot2_info;
extern "C" uint32_t g_multiboot2_magic;
inline multiboot2_tag_t* multiboot2_find_tag(uint32_t type)
{
for (auto* tag = g_multiboot2_info->tags; tag->type != MULTIBOOT2_TAG_END; tag = tag->next())
if (tag->type == type)
return tag;
return nullptr;
}

View File

@ -2,6 +2,7 @@
#include <BAN/StringView.h> #include <BAN/StringView.h>
#include <kernel/ACPI.h> #include <kernel/ACPI.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
#include <kernel/multiboot2.h>
#include <lai/core.h> #include <lai/core.h>
@ -84,6 +85,12 @@ namespace Kernel
static const RSDP* locate_rsdp() static const RSDP* locate_rsdp()
{ {
// Check the multiboot headers
if (auto* rsdp_new = (multiboot2_rsdp_tag_t*)multiboot2_find_tag(MULTIBOOT2_TAG_NEW_RSDP))
return (const RSDP*)rsdp_new->data;
if (auto* rsdp_old = (multiboot2_rsdp_tag_t*)multiboot2_find_tag(MULTIBOOT2_TAG_OLD_RSDP))
return (const RSDP*)rsdp_old->data;
// Look in main BIOS area below 1 MB // Look in main BIOS area below 1 MB
for (uintptr_t addr = P2V(0x000E0000); addr < P2V(0x000FFFFF); addr += 16) for (uintptr_t addr = P2V(0x000E0000); addr < P2V(0x000FFFFF); addr += 16)
if (is_rsdp(addr)) if (is_rsdp(addr))

View File

@ -1,7 +1,7 @@
#include <kernel/LockGuard.h> #include <kernel/LockGuard.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
#include <kernel/multiboot.h> #include <kernel/multiboot2.h>
extern uint8_t g_kernel_end[]; extern uint8_t g_kernel_end[];
@ -26,21 +26,23 @@ namespace Kernel
void Heap::initialize_impl() void Heap::initialize_impl()
{ {
if (!(g_multiboot_info->flags & (1 << 6))) auto* mmap_tag = (multiboot2_mmap_tag_t*)multiboot2_find_tag(MULTIBOOT2_TAG_MMAP);
if (mmap_tag == nullptr)
Kernel::panic("Bootloader did not provide a memory map"); Kernel::panic("Bootloader did not provide a memory map");
for (size_t i = 0; i < g_multiboot_info->mmap_length;) for (size_t offset = sizeof(*mmap_tag); offset < mmap_tag->size; offset += mmap_tag->entry_size)
{ {
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)P2V(g_multiboot_info->mmap_addr + i); auto* mmap_entry = (multiboot2_mmap_entry_t*)((uintptr_t)mmap_tag + offset);
if (mmmt->type == 1)
if (mmap_entry->type == 1)
{ {
paddr_t start = mmmt->base_addr; paddr_t start = mmap_entry->base_addr;
if (start < V2P(g_kernel_end)) if (start < V2P(g_kernel_end))
start = V2P(g_kernel_end); start = V2P(g_kernel_end);
if (auto rem = start % PAGE_SIZE) if (auto rem = start % PAGE_SIZE)
start += PAGE_SIZE - rem; start += PAGE_SIZE - rem;
paddr_t end = mmmt->base_addr + mmmt->length; paddr_t end = mmap_entry->base_addr + mmap_entry->length;
if (auto rem = end % PAGE_SIZE) if (auto rem = end % PAGE_SIZE)
end -= rem; end -= rem;
@ -48,7 +50,6 @@ namespace Kernel
if (end > start + PAGE_SIZE) if (end > start + PAGE_SIZE)
MUST(m_physical_ranges.emplace_back(start, end - start)); MUST(m_physical_ranges.emplace_back(start, end - start));
} }
i += mmmt->size + sizeof(uint32_t);
} }
size_t total = 0; size_t total = 0;

View File

@ -1,55 +1,54 @@
#include <BAN/Errors.h> #include <BAN/Errors.h>
#include <kernel/Debug.h> #include <kernel/Debug.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
#include <kernel/multiboot.h> #include <kernel/multiboot2.h>
#include <kernel/Terminal/VesaTerminalDriver.h> #include <kernel/Terminal/VesaTerminalDriver.h>
using namespace Kernel; using namespace Kernel;
VesaTerminalDriver* VesaTerminalDriver::create() VesaTerminalDriver* VesaTerminalDriver::create()
{ {
if (!(g_multiboot_info->flags & MULTIBOOT_FLAGS_FRAMEBUFFER)) auto* framebuffer_tag = (multiboot2_framebuffer_tag_t*)multiboot2_find_tag(MULTIBOOT2_TAG_FRAMEBUFFER);
if (framebuffer_tag == nullptr)
{ {
dprintln("Bootloader did not provide framebuffer"); dprintln("Bootloader did not provide framebuffer");
return nullptr; return nullptr;
} }
auto& framebuffer = g_multiboot_info->framebuffer; if (framebuffer_tag->framebuffer_type != MULTIBOOT2_FRAMEBUFFER_TYPE_RGB)
if (framebuffer.type == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS)
{ {
if (framebuffer.bpp != 24 && framebuffer.bpp != 32) dprintln("unsupported framebuffer type {}", framebuffer_tag->framebuffer_type);
{
dprintln("Unsupported bpp {}", framebuffer.bpp);
return nullptr;
}
dprintln("Graphics Mode {}x{} ({} bpp)", framebuffer.width, framebuffer.height, framebuffer.bpp);
}
else if (framebuffer.type == MULTIBOOT_FRAMEBUFFER_TYPE_TEXT)
{
dprintln("Text Mode is currently not supported");
return nullptr;
}
else
{
dprintln("Unknown framebuffer type {}", framebuffer.type);
return nullptr; return nullptr;
} }
uint64_t first_page = framebuffer.addr / PAGE_SIZE; if (framebuffer_tag->framebuffer_bpp != 24 && framebuffer_tag->framebuffer_bpp != 32)
uint64_t last_page = BAN::Math::div_round_up<uint64_t>(framebuffer.addr + framebuffer.pitch * framebuffer.height, PAGE_SIZE); {
uint64_t needed_pages = last_page - first_page + 1; dprintln("Unsupported bpp {}", framebuffer_tag->framebuffer_bpp);
return nullptr;
}
dprintln("Graphics Mode {}x{} ({} bpp)",
(uint32_t)framebuffer_tag->framebuffer_width,
(uint32_t)framebuffer_tag->framebuffer_height,
(uint8_t)framebuffer_tag->framebuffer_bpp
);
paddr_t paddr = framebuffer_tag->framebuffer_addr & PAGE_ADDR_MASK;
size_t needed_pages = range_page_count(
framebuffer_tag->framebuffer_addr,
framebuffer_tag->framebuffer_pitch * framebuffer_tag->framebuffer_height
);
vaddr_t vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET); vaddr_t vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET);
ASSERT(vaddr); ASSERT(vaddr);
PageTable::kernel().map_range_at(framebuffer.addr, vaddr, needed_pages * PAGE_SIZE, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present); PageTable::kernel().map_range_at(paddr, vaddr, needed_pages * PAGE_SIZE, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present);
auto* driver = new VesaTerminalDriver( auto* driver = new VesaTerminalDriver(
framebuffer.width, framebuffer_tag->framebuffer_width,
framebuffer.height, framebuffer_tag->framebuffer_height,
framebuffer.pitch, framebuffer_tag->framebuffer_pitch,
framebuffer.bpp, framebuffer_tag->framebuffer_bpp,
vaddr vaddr
); );
driver->set_cursor_position(0, 0); driver->set_cursor_position(0, 0);

View File

@ -12,7 +12,7 @@
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Memory/kmalloc.h> #include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
#include <kernel/multiboot.h> #include <kernel/multiboot2.h>
#include <kernel/PCI.h> #include <kernel/PCI.h>
#include <kernel/PIC.h> #include <kernel/PIC.h>
#include <kernel/Process.h> #include <kernel/Process.h>
@ -23,8 +23,6 @@
#include <kernel/Terminal/VesaTerminalDriver.h> #include <kernel/Terminal/VesaTerminalDriver.h>
#include <kernel/Timer/Timer.h> #include <kernel/Timer/Timer.h>
extern "C" const char g_kernel_cmdline[];
struct ParsedCommandLine struct ParsedCommandLine
{ {
bool force_pic = false; bool force_pic = false;
@ -35,11 +33,12 @@ struct ParsedCommandLine
static bool should_disable_serial() static bool should_disable_serial()
{ {
if (!(g_multiboot_info->flags & 0x02)) auto* cmdline_tag = (multiboot2_cmdline_tag_t*)multiboot2_find_tag(MULTIBOOT2_TAG_CMDLINE);
if (cmdline_tag == nullptr)
return false; return false;
const char* start = g_kernel_cmdline; const char* start = cmdline_tag->cmdline;
const char* current = g_kernel_cmdline; const char* current = start;
while (true) while (true)
{ {
if (!*current || *current == ' ' || *current == '\t') if (!*current || *current == ' ' || *current == '\t')
@ -60,10 +59,11 @@ static ParsedCommandLine cmdline;
static void parse_command_line() static void parse_command_line()
{ {
if (!(g_multiboot_info->flags & 0x02)) auto* cmdline_tag = (multiboot2_cmdline_tag_t*)multiboot2_find_tag(MULTIBOOT2_TAG_CMDLINE);
if (cmdline_tag == nullptr)
return; return;
BAN::StringView full_command_line(g_kernel_cmdline); BAN::StringView full_command_line(cmdline_tag->cmdline);
auto arguments = MUST(full_command_line.split(' ')); auto arguments = MUST(full_command_line.split(' '));
for (auto argument : arguments) for (auto argument : arguments)
@ -98,7 +98,7 @@ extern "C" void kernel_main()
dprintln("Serial output initialized"); dprintln("Serial output initialized");
} }
if (g_multiboot_magic != 0x2BADB002) if (g_multiboot2_magic != 0x36d76289)
{ {
dprintln("Invalid multiboot magic number"); dprintln("Invalid multiboot magic number");
return; return;

View File

@ -1,23 +1,23 @@
menuentry "banan-os" { menuentry "banan-os" {
multiboot /boot/banan-os.kernel root=/dev/sda2 multiboot2 /boot/banan-os.kernel root=/dev/sda2
} }
menuentry "banan-os (no serial)" { menuentry "banan-os (no serial)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 noserial multiboot2 /boot/banan-os.kernel root=/dev/sda2 noserial
} }
menuentry "banan-os (only serial)" { menuentry "banan-os (only serial)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 console=ttyS0 multiboot2 /boot/banan-os.kernel root=/dev/sda2 console=ttyS0
} }
menuentry "banan-os (no apic)" { menuentry "banan-os (no apic)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic multiboot2 /boot/banan-os.kernel root=/dev/sda2 noapic
} }
menuentry "banan-os (no apic, no serial)" { menuentry "banan-os (no apic, no serial)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic noserial multiboot2 /boot/banan-os.kernel root=/dev/sda2 noapic noserial
} }
menuentry "banan-os (no apic, only serial)" { menuentry "banan-os (no apic, only serial)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic console=ttyS0 multiboot2 /boot/banan-os.kernel root=/dev/sda2 noapic console=ttyS0
} }

View File

@ -2,25 +2,25 @@ insmod part_gpt
set root=(hd0,gpt2) set root=(hd0,gpt2)
menuentry "banan-os" { menuentry "banan-os" {
multiboot /boot/banan-os.kernel root=/dev/sda2 multiboot2 /boot/banan-os.kernel root=/dev/sda2
} }
menuentry "banan-os (no serial)" { menuentry "banan-os (no serial)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 noserial multiboot2 /boot/banan-os.kernel root=/dev/sda2 noserial
} }
menuentry "banan-os (only serial)" { menuentry "banan-os (only serial)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 console=ttyS0 multiboot2 /boot/banan-os.kernel root=/dev/sda2 console=ttyS0
} }
menuentry "banan-os (no apic)" { menuentry "banan-os (no apic)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic multiboot2 /boot/banan-os.kernel root=/dev/sda2 noapic
} }
menuentry "banan-os (no apic, no serial)" { menuentry "banan-os (no apic, no serial)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic noserial multiboot2 /boot/banan-os.kernel root=/dev/sda2 noapic noserial
} }
menuentry "banan-os (no apic, only serial)" { menuentry "banan-os (no apic, only serial)" {
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic console=ttyS0 multiboot2 /boot/banan-os.kernel root=/dev/sda2 noapic console=ttyS0
} }