...
This commit is contained in:
@@ -4,6 +4,8 @@ SECTIONS
|
|||||||
{
|
{
|
||||||
. = 2M;
|
. = 2M;
|
||||||
|
|
||||||
|
kernel_start = .;
|
||||||
|
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
*(.multiboot)
|
*(.multiboot)
|
||||||
|
|||||||
@@ -104,19 +104,7 @@ void console_clear() {
|
|||||||
// - `x`: u32 (hex)
|
// - `x`: u32 (hex)
|
||||||
// - `c`: char (ascii)
|
// - `c`: char (ascii)
|
||||||
// - `s`: char* (ascii string)
|
// - `s`: char* (ascii string)
|
||||||
//
|
void kvprintf(const char *fmt, va_list args) {
|
||||||
// ```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);
|
|
||||||
|
|
||||||
bool should_format = false;
|
bool should_format = false;
|
||||||
|
|
||||||
for (size_t i = 0; fmt[i] != '\0'; i++) {
|
for (size_t i = 0; fmt[i] != '\0'; i++) {
|
||||||
@@ -135,25 +123,46 @@ void kprintf(const char *fmt, ...) {
|
|||||||
console_putchar(character, VGA_DEFAULT_COLOR);
|
console_putchar(character, VGA_DEFAULT_COLOR);
|
||||||
} else if (fmt[i] == 'd') {
|
} else if (fmt[i] == 'd') {
|
||||||
u32 val = va_arg(args, u32);
|
u32 val = va_arg(args, u32);
|
||||||
char buf[21];
|
char buf[ITOA32_BUFSIZE];
|
||||||
itoa(val, buf);
|
itoa32(val, buf);
|
||||||
for (size_t j = 0; buf[j] != '\0'; j++) {
|
for (size_t j = 0; buf[j] != '\0'; j++) {
|
||||||
console_putchar(buf[j], VGA_DEFAULT_COLOR);
|
console_putchar(buf[j], VGA_DEFAULT_COLOR);
|
||||||
}
|
}
|
||||||
} else if (fmt[i] == 'u') {
|
} else if (fmt[i] == 'u') {
|
||||||
u32 val = va_arg(args, u32);
|
u32 val = va_arg(args, u32);
|
||||||
char buf[21];
|
char buf[UITOA32_BUFSIZE];
|
||||||
uitoa(val, buf);
|
uitoa32(val, buf);
|
||||||
for (size_t j = 0; buf[j] != '\0'; j++) {
|
for (size_t j = 0; buf[j] != '\0'; j++) {
|
||||||
console_putchar(buf[j], VGA_DEFAULT_COLOR);
|
console_putchar(buf[j], VGA_DEFAULT_COLOR);
|
||||||
}
|
}
|
||||||
} else if (fmt[i] == 'x') {
|
} else if (fmt[i] == 'x') {
|
||||||
u32 val = va_arg(args, u32);
|
u32 val = va_arg(args, u32);
|
||||||
char buf[17];
|
char buf[UITOA32_HEX_BUFSIZE];
|
||||||
uitoa_hex(val, buf);
|
uitoa32_hex(val, buf);
|
||||||
for (size_t j = 0; buf[j] != '\0'; j++) {
|
for (size_t j = 0; buf[j] != '\0'; j++) {
|
||||||
console_putchar(buf[j], VGA_DEFAULT_COLOR);
|
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 {
|
} else {
|
||||||
console_putchar(fmt[i], VGA_DEFAULT_COLOR);
|
console_putchar(fmt[i], VGA_DEFAULT_COLOR);
|
||||||
}
|
}
|
||||||
@@ -163,6 +172,26 @@ void kprintf(const char *fmt, ...) {
|
|||||||
console_putchar(fmt[i], VGA_DEFAULT_COLOR);
|
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);
|
va_end(args);
|
||||||
}
|
}
|
||||||
@@ -27,3 +27,4 @@ void console_putchar(char character, u8 color);
|
|||||||
void console_clear();
|
void console_clear();
|
||||||
|
|
||||||
void kprintf(const char *fmt, ...);
|
void kprintf(const char *fmt, ...);
|
||||||
|
void kvprintf(const char *fmt, va_list args);
|
||||||
154
src/boot/entry.c
154
src/boot/entry.c
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
#pragma once
|
||||||
|
|
||||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x36d76289
|
#define MULTIBOOT_BOOTLOADER_MAGIC 0x36d76289
|
||||||
@@ -25,7 +44,7 @@
|
|||||||
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
||||||
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
||||||
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
#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 {
|
typedef struct {
|
||||||
u8 red;
|
u8 red;
|
||||||
@@ -69,15 +88,15 @@ typedef struct {
|
|||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 biosdev;
|
u32 biosdev;
|
||||||
u32 slice;
|
u32 partition;
|
||||||
u32 part;
|
u32 sub_partition;
|
||||||
} multiboot_tag_bootdev;
|
} multiboot_tag_bootdev;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 addr;
|
u64 base_address;
|
||||||
u64 len;
|
u64 length;
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 zero;
|
u32 reserved;
|
||||||
} multiboot_mmap_entry;
|
} multiboot_mmap_entry;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -108,7 +127,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
u64 framebuffer_addr;
|
u64 framebuffer_address;
|
||||||
u32 framebuffer_pitch;
|
u32 framebuffer_pitch;
|
||||||
u32 framebuffer_width;
|
u32 framebuffer_width;
|
||||||
u32 framebuffer_height;
|
u32 framebuffer_height;
|
||||||
@@ -217,5 +236,5 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 load_base_addr;
|
u32 load_base_address;
|
||||||
} multiboot_tag_load_base_addr;
|
} multiboot_tag_load_base_address;
|
||||||
|
|||||||
20
src/boot/panic.c
Normal file
20
src/boot/panic.c
Normal 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
3
src/boot/panic.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void boot_panic(const char *fmt, ...);
|
||||||
74
src/boot/start.c
Normal file
74
src/boot/start.c
Normal 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
13
src/boot/util.h
Normal 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");
|
||||||
|
}
|
||||||
@@ -21,49 +21,18 @@ void reverse(char *str, size_t length) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void itoa(i32 value, char *buffer) {
|
void itoa32(i32 value, char *buffer) {
|
||||||
char temp[21];
|
|
||||||
int i = 0, j = 0;
|
|
||||||
int negative = 0;
|
|
||||||
|
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
negative = 1;
|
*buffer++ = '-';
|
||||||
if (value == I32_MIN) {
|
|
||||||
const char *min_str = "9223372036854775808";
|
|
||||||
for (i = 0; min_str[i] != '\0'; i++)
|
|
||||||
temp[i] = min_str[i];
|
|
||||||
i = 19;
|
|
||||||
} else {
|
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uitoa32((u32)value, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == 0 && !negative) {
|
void uitoa32(u32 value, char *buffer) {
|
||||||
buffer[0] = '0';
|
char tmp[11];
|
||||||
buffer[1] = '\0';
|
int i = 0;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(negative && value == I32_MIN)) {
|
|
||||||
while (value > 0) {
|
|
||||||
temp[i++] = '0' + (value % 10);
|
|
||||||
value /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negative) {
|
|
||||||
temp[i++] = '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i > 0) {
|
|
||||||
buffer[j++] = temp[--i];
|
|
||||||
}
|
|
||||||
buffer[j] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
void uitoa(u32 value, char *buffer) {
|
|
||||||
char temp[21];
|
|
||||||
int i = 0, j = 0;
|
|
||||||
|
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
@@ -72,20 +41,20 @@ void uitoa(u32 value, char *buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (value > 0) {
|
while (value > 0) {
|
||||||
temp[i++] = '0' + (value % 10);
|
tmp[i++] = '0' + (value % 10);
|
||||||
value /= 10;
|
value /= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i > 0) {
|
for (int j = 0; j < i; j++)
|
||||||
buffer[j++] = temp[--i];
|
buffer[j] = tmp[i - j - 1];
|
||||||
}
|
|
||||||
buffer[j] = '\0';
|
buffer[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void uitoa_hex(u32 value, char *buffer) {
|
void uitoa32_hex(u32 value, char *buffer) {
|
||||||
const char *digits = "0123456789abcdef";
|
static const char hex[] = "0123456789abcdef";
|
||||||
char temp[17];
|
char tmp[9];
|
||||||
int pos = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
@@ -93,13 +62,96 @@ void uitoa_hex(u32 value, char *buffer) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (value > 0 && pos < 16) {
|
while (value > 0) {
|
||||||
temp[pos++] = digits[value & 0xF];
|
tmp[i++] = hex[value & 0xF];
|
||||||
value >>= 4;
|
value >>= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < pos; i++) {
|
for (int j = 0; j < i; j++)
|
||||||
buffer[i] = temp[pos - i - 1];
|
buffer[j] = tmp[i - j - 1];
|
||||||
|
|
||||||
|
buffer[i] = '\0';
|
||||||
}
|
}
|
||||||
buffer[pos] = '\0';
|
|
||||||
|
void itoa64(i64 value, char *buffer) {
|
||||||
|
if (value < 0) {
|
||||||
|
*buffer++ = '-';
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uitoa64((u64)value, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uitoa64(u64 value, char *buffer) {
|
||||||
|
char *p = buffer;
|
||||||
|
|
||||||
|
if (value == 0) {
|
||||||
|
*p++ = '0';
|
||||||
|
*p = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const u64 powers[] = {
|
||||||
|
10000000000000000000ULL,
|
||||||
|
1000000000000000000ULL,
|
||||||
|
100000000000000000ULL,
|
||||||
|
10000000000000000ULL,
|
||||||
|
1000000000000000ULL,
|
||||||
|
100000000000000ULL,
|
||||||
|
10000000000000ULL,
|
||||||
|
1000000000000ULL,
|
||||||
|
100000000000ULL,
|
||||||
|
10000000000ULL,
|
||||||
|
1000000000ULL,
|
||||||
|
100000000ULL,
|
||||||
|
10000000ULL,
|
||||||
|
1000000ULL,
|
||||||
|
100000ULL,
|
||||||
|
10000ULL,
|
||||||
|
1000ULL,
|
||||||
|
100ULL,
|
||||||
|
10ULL,
|
||||||
|
1ULL
|
||||||
|
};
|
||||||
|
|
||||||
|
bool started = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
u64 power = powers[i];
|
||||||
|
u32 digit = 0;
|
||||||
|
|
||||||
|
while (value >= power) {
|
||||||
|
value -= power;
|
||||||
|
digit++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digit || started) {
|
||||||
|
*p++ = '0' + digit;
|
||||||
|
started = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void uitoa64_hex(u64 value, char *buffer) {
|
||||||
|
static const char hex[] = "0123456789abcdef";
|
||||||
|
char tmp[17];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (value == 0) {
|
||||||
|
buffer[0] = '0';
|
||||||
|
buffer[1] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (value > 0) {
|
||||||
|
tmp[i++] = hex[value & 0xF];
|
||||||
|
value >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < i; j++)
|
||||||
|
buffer[j] = tmp[i - j - 1];
|
||||||
|
|
||||||
|
buffer[i] = '\0';
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,18 @@
|
|||||||
int strcmp(const char *a, const char *b);
|
int strcmp(const char *a, const char *b);
|
||||||
void reverse(char *str, size_t length);
|
void reverse(char *str, size_t length);
|
||||||
|
|
||||||
void itoa(i32 value, char *buffer);
|
#define ITOA32_BUFSIZE 12
|
||||||
void uitoa(u32 value, char *buffer);
|
#define UITOA32_BUFSIZE 11
|
||||||
void uitoa_hex(u32 value, char *buffer);
|
#define UITOA32_HEX_BUFSIZE 9
|
||||||
|
|
||||||
|
#define ITOA64_BUFSIZE 21
|
||||||
|
#define UITOA64_BUFSIZE 21
|
||||||
|
#define UITOA64_HEX_BUFSIZE 17
|
||||||
|
|
||||||
|
void itoa32(i32 value, char *buffer);
|
||||||
|
void uitoa32(u32 value, char *buffer);
|
||||||
|
void uitoa32_hex(u32 value, char *buffer);
|
||||||
|
|
||||||
|
void itoa64(i64 value, char *buffer);
|
||||||
|
void uitoa64(u64 value, char *buffer);
|
||||||
|
void uitoa64_hex(u64 value, char *buffer);
|
||||||
|
|||||||
Reference in New Issue
Block a user