This commit is contained in:
nub31
2025-12-30 01:36:52 +01:00
parent dae0f9e852
commit 532d3e7b48
11 changed files with 309 additions and 238 deletions

View File

@@ -104,19 +104,7 @@ void console_clear() {
// - `x`: u32 (hex)
// - `c`: char (ascii)
// - `s`: char* (ascii string)
//
// ```c
// printf(
// "The answer is %d is located at offset %x in file %s",
// 42,
// 0x2000
// "hitchhiker.txt"
// );
// ```
void kprintf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
void kvprintf(const char *fmt, va_list args) {
bool should_format = false;
for (size_t i = 0; fmt[i] != '\0'; i++) {
@@ -135,25 +123,46 @@ void kprintf(const char *fmt, ...) {
console_putchar(character, VGA_DEFAULT_COLOR);
} else if (fmt[i] == 'd') {
u32 val = va_arg(args, u32);
char buf[21];
itoa(val, buf);
char buf[ITOA32_BUFSIZE];
itoa32(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++) {
console_putchar(buf[j], VGA_DEFAULT_COLOR);
}
} else if (fmt[i] == 'u') {
u32 val = va_arg(args, u32);
char buf[21];
uitoa(val, buf);
char buf[UITOA32_BUFSIZE];
uitoa32(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++) {
console_putchar(buf[j], VGA_DEFAULT_COLOR);
}
} else if (fmt[i] == 'x') {
u32 val = va_arg(args, u32);
char buf[17];
uitoa_hex(val, buf);
char buf[UITOA32_HEX_BUFSIZE];
uitoa32_hex(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++) {
console_putchar(buf[j], VGA_DEFAULT_COLOR);
}
} else if (fmt[i] == 'D') {
i64 val = va_arg(args, i64);
char buf[ITOA64_BUFSIZE];
itoa64(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++) {
console_putchar(buf[j], VGA_DEFAULT_COLOR);
}
} else if (fmt[i] == 'U') {
u64 val = va_arg(args, u64);
char buf[UITOA64_BUFSIZE];
uitoa64(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++)
console_putchar(buf[j], VGA_DEFAULT_COLOR);
} else if (fmt[i] == 'X') {
u64 val = va_arg(args, u64);
char buf[UITOA64_HEX_BUFSIZE];
uitoa64_hex(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++)
console_putchar(buf[j], VGA_DEFAULT_COLOR);
} else {
console_putchar(fmt[i], VGA_DEFAULT_COLOR);
}
@@ -163,6 +172,26 @@ void kprintf(const char *fmt, ...) {
console_putchar(fmt[i], VGA_DEFAULT_COLOR);
}
}
}
// Supported formats:
// - `d`: i32 (decimal)
// - `u`: u32 (decimal)
// - `x`: u32 (hex)
// - `c`: char (ascii)
// - `s`: char* (ascii string)
//
// ```c
// printf(
// "The answer is %d is located at offset %x in file %s",
// 42,
// 0x2000
// "hitchhiker.txt"
// );
// ```
void kprintf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
kvprintf(fmt, args);
va_end(args);
}

View File

@@ -26,4 +26,5 @@
void console_putchar(char character, u8 color);
void console_clear();
void kprintf(const char *fmt, ...);
void kprintf(const char *fmt, ...);
void kvprintf(const char *fmt, va_list args);

View File

@@ -1,154 +0,0 @@
#include <def.h>
#include "console.h"
#include "multiboot2.h"
static inline void hlt() {
asm("hlt");
}
static inline void cli() {
asm("cli");
}
void kpanic(const char *message) {
kprintf("panic: %s\n", message);
while (true) {
cli();
hlt();
}
}
u32 align(u32 num, u32 alignment) {
return (num + alignment - 1) & ~(alignment - 1);
}
void c_start(u32 magic, uptr multiboot_info) {
console_clear();
if (magic != MULTIBOOT_BOOTLOADER_MAGIC) {
kpanic("Magic is wrong");
}
uptr next = multiboot_info + 8;
while (true) {
multiboot_tag *tag = (multiboot_tag*)next;
if (tag->type == MULTIBOOT_TAG_TYPE_END) {
break;
}
switch (tag->type) {
case MULTIBOOT_TAG_TYPE_CMDLINE: {
multiboot_tag_string *tag_cmdline = (multiboot_tag_string*)tag;
kprintf("cmdline: %s\n", tag_cmdline->string);
break;
}
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: {
multiboot_tag_string *tag_bootloader = (multiboot_tag_string*)tag;
kprintf("bootloader: %s\n", tag_bootloader->string);
break;
}
case MULTIBOOT_TAG_TYPE_MODULE: {
multiboot_tag_module *tag_module = (multiboot_tag_module*)tag;
kprintf("MULTIBOOT_TAG_TYPE_MODULE\n");
break;
}
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: {
multiboot_tag_basic_meminfo *tag_basic_meminfo = (multiboot_tag_basic_meminfo*)tag;
kprintf("MULTIBOOT_TAG_TYPE_BASIC_MEMINFO\n");
break;
}
case MULTIBOOT_TAG_TYPE_BOOTDEV: {
multiboot_tag_bootdev *tag_bootdev = (multiboot_tag_bootdev*)tag;
kprintf("MULTIBOOT_TAG_TYPE_BOOTDEV\n");
break;
}
case MULTIBOOT_TAG_TYPE_MMAP: {
multiboot_tag_mmap *tag_mmap = (multiboot_tag_mmap*)tag;
kprintf("MULTIBOOT_TAG_TYPE_MMAP\n");
break;
}
case MULTIBOOT_TAG_TYPE_VBE: {
multiboot_tag_vbe *tag_vbe = (multiboot_tag_vbe*)tag;
kprintf("MULTIBOOT_TAG_TYPE_VBE\n");
break;
}
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: {
multiboot_tag_framebuffer *tag_framebuffer = (multiboot_tag_framebuffer*)tag;
kprintf("MULTIBOOT_TAG_TYPE_FRAMEBUFFER\n");
break;
}
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: {
multiboot_tag_elf_sections *tag_elf_sections = (multiboot_tag_elf_sections*)tag;
kprintf("MULTIBOOT_TAG_TYPE_ELF_SECTIONS\n");
break;
}
case MULTIBOOT_TAG_TYPE_APM: {
multiboot_tag_apm *tag_apm = (multiboot_tag_apm*)tag;
kprintf("MULTIBOOT_TAG_TYPE_APM\n");
break;
}
case MULTIBOOT_TAG_TYPE_EFI32: {
multiboot_tag_efi32 *tag_efi32 = (multiboot_tag_efi32*)tag;
kprintf("MULTIBOOT_TAG_TYPE_EFI32\n");
break;
}
case MULTIBOOT_TAG_TYPE_EFI64: {
multiboot_tag_efi64 *tag_efi64 = (multiboot_tag_efi64*)tag;
kprintf("MULTIBOOT_TAG_TYPE_EFI64\n");
break;
}
case MULTIBOOT_TAG_TYPE_SMBIOS: {
multiboot_tag_smbios *tag_smbios = (multiboot_tag_smbios*)tag;
kprintf("MULTIBOOT_TAG_TYPE_SMBIOS\n");
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_OLD: {
multiboot_tag_old_acpi *tag_old_acpi = (multiboot_tag_old_acpi*)tag;
kprintf("MULTIBOOT_TAG_TYPE_ACPI_OLD\n");
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_NEW: {
multiboot_tag_new_acpi *tag_new_acpi = (multiboot_tag_new_acpi*)tag;
kprintf("MULTIBOOT_TAG_TYPE_ACPI_NEW\n");
break;
}
case MULTIBOOT_TAG_TYPE_NETWORK: {
multiboot_tag_network *tag_network = (multiboot_tag_network*)tag;
kprintf("MULTIBOOT_TAG_TYPE_NETWORK\n");
break;
}
case MULTIBOOT_TAG_TYPE_EFI_MMAP: {
multiboot_tag_efi_mmap *tag_efi_mmap = (multiboot_tag_efi_mmap*)tag;
kprintf("MULTIBOOT_TAG_TYPE_EFI_MMAP\n");
break;
}
case MULTIBOOT_TAG_TYPE_EFI_BS: {
// note(nub31): Just a flag, no data
break;
}
case MULTIBOOT_TAG_TYPE_EFI32_IH: {
multiboot_tag_efi32_ih *tag_efi32_ih = (multiboot_tag_efi32_ih*)tag;
kprintf("MULTIBOOT_TAG_TYPE_EFI32_IH\n");
break;
}
case MULTIBOOT_TAG_TYPE_EFI64_IH: {
multiboot_tag_efi64_ih *tag_efi64_ih = (multiboot_tag_efi64_ih*)tag;
kprintf("MULTIBOOT_TAG_TYPE_EFI64_IH\n");
break;
}
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: {
multiboot_tag_load_base_addr *tag_load_base_addr = (multiboot_tag_load_base_addr*)tag;
kprintf("MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR\n");
break;
}
default: {
kpanic("Unhandled multiboot tag");
break;
}
}
next = align(next + tag->size, MULTIBOOT_TAG_ALIGN);
}
}

View File

@@ -1,3 +1,22 @@
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#define MULTIBOOT_BOOTLOADER_MAGIC 0x36d76289
@@ -25,7 +44,7 @@
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDRESS 21
typedef struct {
u8 red;
@@ -69,15 +88,15 @@ typedef struct {
u32 type;
u32 size;
u32 biosdev;
u32 slice;
u32 part;
u32 partition;
u32 sub_partition;
} multiboot_tag_bootdev;
typedef struct {
u64 addr;
u64 len;
u64 base_address;
u64 length;
u32 type;
u32 zero;
u32 reserved;
} multiboot_mmap_entry;
typedef struct {
@@ -108,7 +127,7 @@ typedef struct {
typedef struct {
u32 type;
u32 size;
u64 framebuffer_addr;
u64 framebuffer_address;
u32 framebuffer_pitch;
u32 framebuffer_width;
u32 framebuffer_height;
@@ -217,5 +236,5 @@ typedef struct {
typedef struct {
u32 type;
u32 size;
u32 load_base_addr;
} multiboot_tag_load_base_addr;
u32 load_base_address;
} multiboot_tag_load_base_address;

20
src/boot/panic.c Normal file
View File

@@ -0,0 +1,20 @@
#include "panic.h"
#include "console.h"
#include "util.h"
#include <def.h>
void boot_panic(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
kprintf("panic: ");
kvprintf(fmt, args);
kprintf("\n");
va_end(args);
while (true) {
cli();
hlt();
}
}

3
src/boot/panic.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
void boot_panic(const char *fmt, ...);

74
src/boot/start.c Normal file
View File

@@ -0,0 +1,74 @@
#include <def.h>
#include "console.h"
#include "multiboot2.h"
#include "panic.h"
#include "util.h"
static void *multiboot_find_tag(uptr multiboot_info, u32 type) {
uptr next = multiboot_info + 8;
while (true) {
multiboot_tag *tag = (multiboot_tag*)next;
if (tag->type == MULTIBOOT_TAG_TYPE_END) {
return NULL;
}
if (tag->type == type) {
return tag;
}
next = align(next + tag->size, MULTIBOOT_TAG_ALIGN);
}
}
#define MAX_REGIONS 64
typedef struct {
u64 base_address;
u64 length;
} region;
extern uptr kernel_start;
extern uptr kernel_end;
static region regions[MAX_REGIONS] = {0};
static u32 region_count = 0;
static void find_memory_regions(uptr multiboot_info) {
multiboot_tag_mmap *tag = multiboot_find_tag(multiboot_info, MULTIBOOT_TAG_TYPE_MMAP);
if (tag == NULL) {
boot_panic("Multiboot did not provide mmap tag");
}
u32 entry_count = (tag->size - 16) / tag->entry_size;
u8 *entry_ptr = (u8*)tag->entries;
for (u32 i = 0; i < entry_count; ++i) {
multiboot_mmap_entry *entry = (multiboot_mmap_entry*)entry_ptr;
if (entry->type == MULTIBOOT_MEMORY_AVAILABLE) {
if (region_count >= MAX_REGIONS) {
boot_panic("Too many memory regions");
}
regions[region_count++] = (region){ entry->base_address, entry->length };
}
entry_ptr += tag->entry_size;
}
}
void c_start(u32 magic, uptr multiboot_info) {
console_clear();
if (magic != MULTIBOOT_BOOTLOADER_MAGIC) {
boot_panic("Expected bootloader magic 0x%x, but got 0x%x", MULTIBOOT_BOOTLOADER_MAGIC, magic);
}
find_memory_regions(multiboot_info);
for (u32 i = 0; i < region_count; ++i) {
kprintf("base: 0x%X, length: 0x%X\n", regions[i].base_address, regions[i].length);
}
}

13
src/boot/util.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
static inline u32 align(u32 num, u32 alignment) {
return (num + alignment - 1) & ~(alignment - 1);
}
static inline void hlt() {
asm("hlt");
}
static inline void cli() {
asm("cli");
}