aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-02-02 22:27:27 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-02-02 22:27:27 +0200
commit36e8ee0cdaa904ee00710b1d2df16691729cc93d (patch)
tree16e3836af7ef9efa6da1bbde4248ae5ad956bf58
parentlibk: add its own makefile (diff)
downloadkernel.cpp-36e8ee0cdaa904ee00710b1d2df16691729cc93d.tar.xz
Print some multiboot2 information
-rw-r--r--boot.asm28
-rw-r--r--grub.cfg7
-rw-r--r--kernel.cc76
-rw-r--r--libk/stdlib.h22
-rw-r--r--libk/stdlib/console.cc9
-rw-r--r--libk/type_traits.h10
-rw-r--r--libk/types.h9
-rw-r--r--linker.ld5
-rw-r--r--makefile27
-rw-r--r--multiboot2.h416
-rw-r--r--readme.md4
-rw-r--r--vga.cc63
-rw-r--r--vga.h9
13 files changed, 608 insertions, 77 deletions
diff --git a/boot.asm b/boot.asm
index e4897e4..d787d64 100644
--- a/boot.asm
+++ b/boot.asm
@@ -1,9 +1,6 @@
; Declare constants for the multiboot header.
-MBALIGN equ 1 << 0 ; align loaded modules on page boundaries
-MEMINFO equ 1 << 1 ; provide memory map
-FLAGS equ MBALIGN | MEMINFO ; this is the Multiboot 'flag' field
-MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
-CHECKSUM equ -(MAGIC + FLAGS) ; checksum of above, to prove we are multiboot
+MAGIC equ 0xE85250D6 ; multiboot2 magic
+ARCH equ 0 ; protected mode i386
; Declare a multiboot header that marks the program as a kernel. These are magic
; values that are documented in the multiboot standard. The bootloader will
@@ -11,10 +8,19 @@ CHECKSUM equ -(MAGIC + FLAGS) ; checksum of above, to prove we are multiboot
; 32-bit boundary. The signature is in its own section so the header can be
; forced to be within the first 8 KiB of the kernel file.
section .multiboot
-align 4
- dd MAGIC
- dd FLAGS
- dd CHECKSUM
+header_start:
+ dd MAGIC
+ dd ARCH
+ dd header_end - header_start ; header length
+ dd 0x100000000 - (MAGIC + ARCH + (header_end - header_start))
+
+ ; optional multiboot tags here
+
+ ; required end tag (u16, u16, u32) = (0, 0, 8)
+ dw 0 ; type
+ dw 0 ; flags
+ dd 8 ; size
+header_end:
; The multiboot standard does not define the value of the stack pointer register
; (esp) and it is up to the kernel to provide a stack. This allocates room for a
@@ -29,7 +35,7 @@ align 4
section .bss
align 16
stack_bottom:
-resb 16384 ; 16 KiB
+ resb 16384 ; 16 KiB
stack_top:
; The linker script specifies _start as the entry point to the kernel and the
@@ -54,6 +60,8 @@ _start:
; stack (as it grows downwards on x86 systems). This is necessarily done
; in assembly as languages such as C cannot function without a stack.
mov esp, stack_top
+ push ebx
+ push eax
; This is a good place to initialize crucial processor state before the
; high-level kernel is entered. It's best to minimize the early
diff --git a/grub.cfg b/grub.cfg
index b2f8404..d41ece4 100644
--- a/grub.cfg
+++ b/grub.cfg
@@ -1,3 +1,6 @@
-menuentry "myos" {
- multiboot /boot/myos.bin
+set timeout=0
+set default=0
+
+menuentry "glitch" {
+ multiboot2 /boot/glitch.elf splash
}
diff --git a/kernel.cc b/kernel.cc
index 3df1903..ffc7180 100644
--- a/kernel.cc
+++ b/kernel.cc
@@ -1,6 +1,3 @@
-#include <stdlib.h>
-#include <types.h>
-
/* Check if the compiler thinks you are targeting the wrong operating system. */
#if defined(__linux__)
#error "You are not using a cross-compiler"
@@ -11,16 +8,81 @@
#error "This tutorial needs to be compiled with a ix86-elf compiler"
#endif
+#include "multiboot2.h"
#include "vga.h"
+#include <stdlib.h>
+#include <types.h>
-extern "C" void kernel_main(void) {
+extern "C" void kernel_main(uint32_t mb_magic, uint32_t mb_addr) {
VGA terminal;
- console_set(&terminal);
+ Console::set(&terminal);
terminal.set_color(VGA::VGA_COLOR_CYAN, VGA::VGA_COLOR_BROWN);
- terminal.write("Hello, kernel World! xxx--\n", "--xyxyxz\n", 10);
+ printk("Hello, kernel World!\n");
+
+ printk("multiboot magic: 0x", mb_magic,
+ mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC ? " is valid" : " is invalid",
+ '\n');
+ printk("multiboot addr: 0x", mb_addr, '\n');
+
+ if (mb_addr & 7) {
+ printk("unaligned mbi\n");
+ }
+
+ struct multiboot_tag *tag;
+ const uint32_t size = *(unsigned *)mb_addr;
+ printk("Announced mbi size 0x", size, '\n');
+
+ for (tag = (struct multiboot_tag *)(mb_addr + 8);
+ tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag +
+ ((tag->size + 7) & ~7))) {
+
+ switch (tag->type) {
+ case MULTIBOOT_TAG_TYPE_CMDLINE:
+ printk("Command line = [", ((struct multiboot_tag_string *)tag)->string,
+ "]\n");
+ break;
+ case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
+ printk("Boot loader name = [",
+ ((struct multiboot_tag_string *)tag)->string, "]\n");
+ break;
+ case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
+ printk("mem_lower = ",
+ ((struct multiboot_tag_basic_meminfo *)tag)->mem_lower, "KB\n",
+ "mem_upper = ",
+ ((struct multiboot_tag_basic_meminfo *)tag)->mem_upper, "KB\n");
+ break;
+ case MULTIBOOT_TAG_TYPE_BOOTDEV:
+ printk("Boot device 0x", ((struct multiboot_tag_bootdev *)tag)->biosdev,
+ " slice ", ((struct multiboot_tag_bootdev *)tag)->slice, " part ",
+ ((struct multiboot_tag_bootdev *)tag)->part, '\n');
+ break;
+ case MULTIBOOT_TAG_TYPE_MMAP: {
+ multiboot_memory_map_t *mmap;
+
+ printk("mmap\n");
+
+ for (mmap = ((struct multiboot_tag_mmap *)tag)->entries;
+ (multiboot_uint8_t *)mmap < (multiboot_uint8_t *)tag + tag->size;
+ mmap = (multiboot_memory_map_t *)((unsigned long)mmap +
+ ((struct multiboot_tag_mmap *)tag)
+ ->entry_size))
+ printk(" base_addr = 0x", (unsigned)(mmap->addr >> 32), ' ',
+ (unsigned)(mmap->addr & 0xffffffff), " length = 0x",
+ (unsigned)(mmap->len >> 32), ' ',
+ (unsigned)(mmap->len & 0xffffffff), " type = 0x",
+ (unsigned)mmap->type, '\n');
+ } break;
+ default:
+ printk("Tag 0x", tag->type, ", Size 0x", tag->size, '\n');
+ break;
+ } // switch(tag->type)
+ } // for(each tag)
- printk("This is printk\n");
+ tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag +
+ ((tag->size + 7) & ~7));
+ printk("Total mbi size 0x", (unsigned)tag - mb_addr, '\n');
abort();
}
diff --git a/libk/stdlib.h b/libk/stdlib.h
index 3e6619d..44bacf4 100644
--- a/libk/stdlib.h
+++ b/libk/stdlib.h
@@ -1,14 +1,32 @@
#pragma once
#include <string.h>
+#include <type_traits.h>
class Console {
public:
+ virtual void write(char c) = 0;
virtual void write(const String &msg) = 0;
+ virtual void write(int n) = 0;
+ virtual void write(unsigned int n) = 0;
+
+ static void set(Console *ptr);
+ static Console *get();
};
-void console_set(Console *ptr);
+template <typename T> void printk(const T &a) {
+ if (auto *c = Console::get()) {
+ if constexpr (is_same<T, const char *>())
+ c->write(String(a));
+ else
+ c->write(a);
+ }
+}
-void printk(const String &msg);
+template <typename T, typename... Args>
+void printk(const T &a, const Args &...x) {
+ printk(a);
+ printk(x...);
+}
__attribute__((__noreturn__)) void abort();
diff --git a/libk/stdlib/console.cc b/libk/stdlib/console.cc
index dbc9b86..dee6a8f 100644
--- a/libk/stdlib/console.cc
+++ b/libk/stdlib/console.cc
@@ -2,18 +2,13 @@
static Console *global_console = nullptr;
-void console_set(Console *ptr) {
+void Console::set(Console *ptr) {
if (ptr != nullptr) {
global_console = ptr;
}
}
-void printk(const String &msg) {
- if (global_console == nullptr)
- return;
-
- global_console->write(msg);
-}
+Console *Console::get() { return global_console; }
void abort() {
/*
diff --git a/libk/type_traits.h b/libk/type_traits.h
new file mode 100644
index 0000000..cef30c1
--- /dev/null
+++ b/libk/type_traits.h
@@ -0,0 +1,10 @@
+#pragma once
+
+template <class T, T v> struct integral_constant {
+ constexpr T operator()() const { return v; }
+ constexpr operator T() const { return v; }
+};
+
+template <class T, class U> struct is_same : integral_constant<bool, false> {};
+
+template <class T> struct is_same<T, T> : integral_constant<bool, true> {};
diff --git a/libk/types.h b/libk/types.h
index 0818342..be38cb0 100644
--- a/libk/types.h
+++ b/libk/types.h
@@ -13,9 +13,8 @@ static_assert(sizeof(uint16_t) == 2);
typedef unsigned int uint32_t;
static_assert(sizeof(uint32_t) == 4);
-//typedef unsigned long uint64_t;
-//static_assert(sizeof(uint64_t) == 8);
-
+typedef unsigned long long int uint64_t;
+static_assert(sizeof(uint64_t) == 8);
typedef char int8_t;
static_assert(sizeof(int8_t) == 1);
@@ -26,5 +25,5 @@ static_assert(sizeof(int16_t) == 2);
typedef int int32_t;
static_assert(sizeof(int32_t) == 4);
-//typedef long int64_t;
-//static_assert(sizeof(int64_t) == 8);
+typedef long long int int64_t;
+static_assert(sizeof(int64_t) == 8);
diff --git a/linker.ld b/linker.ld
index 732e5a0..7e07efc 100644
--- a/linker.ld
+++ b/linker.ld
@@ -15,9 +15,12 @@ SECTIONS
/* First put the multiboot header, as it is required to be put very early
early in the image or the bootloader won't recognize the file format.
Next we'll put the .text section. */
+ .boot :
+ {
+ *(.multiboot)
+ }
.text :
{
- *(.multiboot)
*(.text)
}
diff --git a/makefile b/makefile
index 10cfacf..b149337 100644
--- a/makefile
+++ b/makefile
@@ -9,18 +9,23 @@ export AR := llvm-ar
export NASM := nasm
export LD := ld.lld
export CXX := clang++
-export CXX_FLAGS := -std=c++20 -ffreestanding -nostdinc -fno-exceptions -fno-rtti -Wall -Wextra -O2
-CXX_INCLUDE := libk
+export CXX_FLAGS := -std=c++20 -ffreestanding \
+ -nostdlib -nostdinc -nostdinc++ \
+ -fno-exceptions -fno-rtti -Wall -Wextra -O2
+CXX_INCLUDE := $(CURDIR)/libk
CXX_OBJ := kernel.o vga.o
# $@ is target
# $< is first dependency
# $^ is all dependencies
-default: myos.bin
+default: glitch.elf
-myos.bin: boot.o $(CXX_OBJ) libk/libk.a
- $(LD) -T linker.ld -o myos.bin boot.o $(CXX_OBJ) -Llibk -lk
+check-grub: glitch.elf
+ grub-file --is-x86-multiboot2 glitch.elf
+
+glitch.elf: boot.o $(CXX_OBJ) libk/libk.a
+ $(LD) -T linker.ld -o glitch.elf boot.o $(CXX_OBJ) -Llibk -lk
boot.o: boot.asm
$(NASM) -felf32 -o $@ $^
@@ -31,17 +36,19 @@ $(CXX_OBJ): %.o : %.cc
libk/libk.a:
$(MAKE) -C libk libk.a
-iso: myos.bin
+iso: glitch.elf
mkdir -p isodir/boot/grub
- cp myos.bin isodir/boot/myos.bin
+ cp glitch.elf isodir/boot/glitch.elf
cp grub.cfg isodir/boot/grub/grub.cfg
grub-mkrescue -o myos.iso isodir
-run: myos.bin
- qemu-system-i386 -kernel myos.bin
+run: glitch.elf
+ qemu-system-i386 -kernel glitch.elf
+run-iso: iso
+ qemu-system-i386 -cdrom myos.iso
clean:
- rm boot.o $(CXX_OBJ) myos.bin
+ rm boot.o $(CXX_OBJ) glitch.elf
$(MAKE) -C libk clean
clean-iso:
diff --git a/multiboot2.h b/multiboot2.h
new file mode 100644
index 0000000..5a3db5a
--- /dev/null
+++ b/multiboot2.h
@@ -0,0 +1,416 @@
+/* multiboot2.h - Multiboot 2 header file. */
+/* 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.
+ */
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 32768
+#define MULTIBOOT_HEADER_ALIGN 8
+
+/* The magic field should contain this. */
+#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
+
+/* This should be in %eax. */
+#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+/* Alignment of the multiboot info structure. */
+#define MULTIBOOT_INFO_ALIGN 0x00000008
+
+/* Flags set in the 'flags' member of the multiboot header. */
+
+#define MULTIBOOT_TAG_ALIGN 8
+#define MULTIBOOT_TAG_TYPE_END 0
+#define MULTIBOOT_TAG_TYPE_CMDLINE 1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
+#define MULTIBOOT_TAG_TYPE_MODULE 3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
+#define MULTIBOOT_TAG_TYPE_MMAP 6
+#define MULTIBOOT_TAG_TYPE_VBE 7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
+#define MULTIBOOT_TAG_TYPE_APM 10
+#define MULTIBOOT_TAG_TYPE_EFI32 11
+#define MULTIBOOT_TAG_TYPE_EFI64 12
+#define MULTIBOOT_TAG_TYPE_SMBIOS 13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
+#define MULTIBOOT_TAG_TYPE_NETWORK 16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
+#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_HEADER_TAG_END 0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+#define MULTIBOOT_HEADER_TAG_ADDRESS 2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+#define MULTIBOOT_HEADER_TAG_EFI_BS 7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
+
+#define MULTIBOOT_ARCHITECTURE_I386 0
+#define MULTIBOOT_ARCHITECTURE_MIPS32 4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+
+#ifndef ASM_FILE
+
+typedef unsigned char multiboot_uint8_t;
+typedef unsigned short multiboot_uint16_t;
+typedef unsigned int multiboot_uint32_t;
+typedef unsigned long long multiboot_uint64_t;
+
+struct multiboot_header
+{
+ /* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+ /* ISA */
+ multiboot_uint32_t architecture;
+
+ /* Total header length. */
+ multiboot_uint32_t header_length;
+
+ /* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+};
+
+struct multiboot_header_tag
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_information_request
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t requests[0];
+};
+
+struct multiboot_header_tag_address
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+};
+
+struct multiboot_header_tag_entry_address
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_addr;
+};
+
+struct multiboot_header_tag_console_flags
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t console_flags;
+};
+
+struct multiboot_header_tag_framebuffer
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+struct multiboot_header_tag_module_align
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_relocatable
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t min_addr;
+ multiboot_uint32_t max_addr;
+ multiboot_uint32_t align;
+ multiboot_uint32_t preference;
+};
+
+struct multiboot_color
+{
+ multiboot_uint8_t red;
+ multiboot_uint8_t green;
+ multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry
+{
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
+#define MULTIBOOT_MEMORY_NVS 4
+#define MULTIBOOT_MEMORY_BADRAM 5
+ multiboot_uint32_t type;
+ multiboot_uint32_t zero;
+};
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ char string[0];
+};
+
+struct multiboot_tag_module
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+ char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+};
+
+struct multiboot_tag_bootdev
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t biosdev;
+ multiboot_uint32_t slice;
+ multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_size;
+ multiboot_uint32_t entry_version;
+ struct multiboot_mmap_entry entries[0];
+};
+
+struct multiboot_vbe_info_block
+{
+ multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+ multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+
+ struct multiboot_vbe_info_block vbe_control_info;
+ struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
+ multiboot_uint8_t framebuffer_type;
+ multiboot_uint16_t reserved;
+};
+
+struct multiboot_tag_framebuffer
+{
+ struct multiboot_tag_framebuffer_common common;
+
+ union
+ {
+ struct
+ {
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ struct multiboot_color framebuffer_palette[0];
+ };
+ struct
+ {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
+};
+
+struct multiboot_tag_elf_sections
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t num;
+ multiboot_uint32_t entsize;
+ multiboot_uint32_t shndx;
+ char sections[0];
+};
+
+struct multiboot_tag_apm
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint16_t version;
+ multiboot_uint16_t cseg;
+ multiboot_uint32_t offset;
+ multiboot_uint16_t cseg_16;
+ multiboot_uint16_t dseg;
+ multiboot_uint16_t flags;
+ multiboot_uint16_t cseg_len;
+ multiboot_uint16_t cseg_16_len;
+ multiboot_uint16_t dseg_len;
+};
+
+struct multiboot_tag_efi32
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_smbios
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t major;
+ multiboot_uint8_t minor;
+ multiboot_uint8_t reserved[6];
+ multiboot_uint8_t tables[0];
+};
+
+struct multiboot_tag_old_acpi
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_new_acpi
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_network
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t dhcpack[0];
+};
+
+struct multiboot_tag_efi_mmap
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t descr_size;
+ multiboot_uint32_t descr_vers;
+ multiboot_uint8_t efi_mmap[0];
+};
+
+struct multiboot_tag_efi32_ih
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64_ih
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_load_base_addr
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t load_base_addr;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */
diff --git a/readme.md b/readme.md
index 72aed4c..2bf96a1 100644
--- a/readme.md
+++ b/readme.md
@@ -8,3 +8,7 @@
## running
- make run
+- requires multiboot2-compliant bootloader
+
+## foreign sources
+multiboot2.h | https://git.savannah.gnu.org/git/grub.git
diff --git a/vga.cc b/vga.cc
index 17061bb..b4c9673 100644
--- a/vga.cc
+++ b/vga.cc
@@ -27,41 +27,50 @@ void VGA::put_char(char c, size_t x, size_t y, uint8_t color) {
buffer[index] = vga_entry(c, (color == 0) ? this->color : color);
}
-void VGA::write(const String &data) {
- auto it = data.begin();
- while (it) {
- switch (const auto c = it.next()) {
- case '\n':
- column = 0;
- ++row;
- break;
- default:
- put_char(c, column, row, color);
- ++column;
- }
+void VGA::write(char c) {
+ switch (c) {
+ case '\n':
+ column = 0;
+ ++row;
+ break;
+ default:
+ put_char(c, column, row, color);
+ ++column;
+ }
- if (column == max_columns) {
- column = 0;
- ++row;
- }
+ if (column == max_columns) {
+ column = 0;
+ ++row;
+ }
- if (row == max_rows) {
- // scroll up - move rows 1~25 up by one
- for (size_t y = 1; y < max_rows; y++) {
- const auto prev_y = y - 1;
- for (size_t x = 0; x < max_columns; ++x) {
- const auto prev = prev_y * max_columns + x;
- const auto idx = y * max_columns + x;
- buffer[prev] = buffer[idx];
- }
+ if (row == max_rows) {
+ // scroll up - move rows 1~25 up by one
+ for (size_t y = 1; y < max_rows; y++) {
+ const auto prev_y = y - 1;
+ for (size_t x = 0; x < max_columns; ++x) {
+ const auto prev = prev_y * max_columns + x;
+ const auto idx = y * max_columns + x;
+ buffer[prev] = buffer[idx];
}
- --row;
}
+ --row;
+ }
+}
+
+void VGA::write(const String &data) {
+ auto it = data.begin();
+ while (it) {
+ write(it.next());
}
}
void VGA::write(int n) {
char buffer[max_columns];
- itoa(n, buffer);
+ itoa<16>(n, buffer);
write(buffer);
}
+
+void VGA::write(unsigned int n) {
+ // TODO
+ write((int)n);
+}
diff --git a/vga.h b/vga.h
index b08a221..a3274c4 100644
--- a/vga.h
+++ b/vga.h
@@ -27,13 +27,10 @@ public:
~VGA() = default;
void put_char(char c, size_t x, size_t y, uint8_t color = 0);
+ void write(char c) override;
void write(const String &data) override;
- void write(int n);
-
- template <typename... Args> void write(const String &f, const Args &...a) {
- write(f);
- write(a...);
- }
+ void write(int n) override;
+ void write(unsigned int n) override;
void set_color(vga_color fg, vga_color bg) { color = (fg | bg << 4); }