feat: initial
This commit is contained in:
commit
92d8a91be4
20 changed files with 1058 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.claude
|
||||||
|
.vscode
|
||||||
|
compile_commands.json
|
||||||
|
CLAUDE.md
|
||||||
3
kernel/.gitignore
vendored
Normal file
3
kernel/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
build/
|
||||||
|
output/
|
||||||
|
iso/boot/kernel.bin
|
||||||
36
kernel/Makefile
Normal file
36
kernel/Makefile
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
root_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
source_dir := $(root_dir)/src
|
||||||
|
object_dir := $(root_dir)/build
|
||||||
|
linker_script := $(root_dir)/linker.ld
|
||||||
|
output_dir := $(root_dir)/output
|
||||||
|
|
||||||
|
LD := ld
|
||||||
|
CXX := clang++
|
||||||
|
CXXFLAGS := -std=c++20 -fpie -fno-strict-aliasing -fno-stack-protector -fno-asynchronous-unwind-tables -fno-exceptions -fno-rtti -fno-common -mno-red-zone -mgeneral-regs-only -ffreestanding -Og -g -Wall -Wextra -Wno-reserved-identifier -I$(root_dir)/include
|
||||||
|
|
||||||
|
source_files := $(shell find $(source_dir) -type f -name "*.cpp")
|
||||||
|
object_files := $(patsubst $(source_dir)/%,$(object_dir)/%.o,$(source_files))
|
||||||
|
|
||||||
|
$(object_files): $(object_dir)%.o : $(source_dir)%
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
@echo "Compiling $<"
|
||||||
|
@$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
kernel.bin: $(object_files)
|
||||||
|
@mkdir -p $(output_dir)
|
||||||
|
@echo "Linking kernel"
|
||||||
|
@$(LD) --build-id=none --no-relax -nostdlib -o $(output_dir)/kernel.bin -T $(linker_script) $(object_files)
|
||||||
|
@echo "Disassembling kernel"
|
||||||
|
@objdump -dC $(output_dir)/kernel.bin > $(output_dir)/kernel.asm
|
||||||
|
@objdump -DC $(output_dir)/kernel.bin > $(output_dir)/kernel_full.asm
|
||||||
|
|
||||||
|
|
||||||
|
iso: kernel.bin
|
||||||
|
@echo "Creating ISO"
|
||||||
|
@cp $(output_dir)/kernel.bin $(root_dir)/iso/boot/kernel.bin
|
||||||
|
@grub-mkrescue -d /usr/lib/grub/i386-pc -o $(output_dir)/kernel.iso iso
|
||||||
|
|
||||||
|
all: kernel.bin iso
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -rf $(object_dir) $(output_dir) iso/boot/kernel.bin
|
||||||
3
kernel/include/init/init.h
Normal file
3
kernel/include/init/init.h
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
[[maybe_unused]] [[noreturn]] __attribute__((used)) void init();
|
||||||
303
kernel/include/init/multiboot2.h
Normal file
303
kernel/include/init/multiboot2.h
Normal file
|
|
@ -0,0 +1,303 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "util/number.h"
|
||||||
|
#include "util/function.h"
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
namespace multiboot {
|
||||||
|
|
||||||
|
inline constexpr uint32_t magic = 0x36d76289;
|
||||||
|
inline constexpr uint32_t alignment = 8;
|
||||||
|
|
||||||
|
enum class tag_type : uint32_t {
|
||||||
|
end = 0,
|
||||||
|
cmdline = 1,
|
||||||
|
boot_loader_name = 2,
|
||||||
|
module = 3,
|
||||||
|
basic_meminfo = 4,
|
||||||
|
bootdev = 5,
|
||||||
|
mmap = 6,
|
||||||
|
vbe = 7,
|
||||||
|
framebuffer = 8,
|
||||||
|
elf_sections = 9,
|
||||||
|
apm = 10,
|
||||||
|
efi32 = 14,
|
||||||
|
efi64 = 15,
|
||||||
|
smbios = 16,
|
||||||
|
acpi_old = 17,
|
||||||
|
acpi_new = 18,
|
||||||
|
network = 19,
|
||||||
|
efi_mmap = 20,
|
||||||
|
efi_bs = 21,
|
||||||
|
efi32_ih = 22,
|
||||||
|
efi64_ih = 23,
|
||||||
|
load_base_addr = 24,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class framebuffer_type : uint8_t {
|
||||||
|
indexed = 0,
|
||||||
|
rgb = 1,
|
||||||
|
ega_text = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class mem_type : uint32_t {
|
||||||
|
available = 1,
|
||||||
|
reserved = 2,
|
||||||
|
acpi_reclaimable = 3,
|
||||||
|
nvs = 4,
|
||||||
|
badram = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct color {
|
||||||
|
uint8_t red;
|
||||||
|
uint8_t green;
|
||||||
|
uint8_t blue;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mem_entry {
|
||||||
|
uint64_t addr;
|
||||||
|
uint64_t len;
|
||||||
|
mem_type type;
|
||||||
|
uint32_t zero;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_string {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
char string[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_module {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t mod_start;
|
||||||
|
uint32_t mod_end;
|
||||||
|
char cmdline[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_basic_meminfo {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t mem_lower;
|
||||||
|
uint32_t mem_upper;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_bootdev {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t biosdev;
|
||||||
|
uint32_t slice;
|
||||||
|
uint32_t part;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_mmap {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t entry_size;
|
||||||
|
uint32_t entry_version;
|
||||||
|
mem_entry entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vbe_info_block {
|
||||||
|
uint8_t external_specification[512];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vbe_mode_info_block {
|
||||||
|
uint8_t external_specification[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_vbe {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint16_t vbe_mode;
|
||||||
|
uint16_t vbe_interface_seg;
|
||||||
|
uint16_t vbe_interface_off;
|
||||||
|
uint16_t vbe_interface_len;
|
||||||
|
vbe_info_block vbe_control_info;
|
||||||
|
vbe_mode_info_block vbe_mode_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct tag_framebuffer {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint64_t framebuffer_addr;
|
||||||
|
uint32_t framebuffer_pitch;
|
||||||
|
uint32_t framebuffer_width;
|
||||||
|
uint32_t framebuffer_height;
|
||||||
|
uint8_t framebuffer_bpp;
|
||||||
|
framebuffer_type framebuffer_type;
|
||||||
|
uint16_t reserved;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint16_t framebuffer_palette_num_colors;
|
||||||
|
color framebuffer_palette[0];
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
uint8_t framebuffer_red_field_position;
|
||||||
|
uint8_t framebuffer_red_mask_size;
|
||||||
|
uint8_t framebuffer_green_field_position;
|
||||||
|
uint8_t framebuffer_green_mask_size;
|
||||||
|
uint8_t framebuffer_blue_field_position;
|
||||||
|
uint8_t framebuffer_blue_mask_size;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_elf_sections {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t num;
|
||||||
|
uint32_t entsize;
|
||||||
|
uint32_t shndx;
|
||||||
|
char sections[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_apm {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint16_t version;
|
||||||
|
uint16_t cseg;
|
||||||
|
uint32_t offset;
|
||||||
|
uint16_t cseg_16;
|
||||||
|
uint16_t dseg;
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t cseg_len;
|
||||||
|
uint16_t cseg_16_len;
|
||||||
|
uint16_t dseg_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_efi32 {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_efi64 {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint64_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_smbios {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t major;
|
||||||
|
uint8_t minor;
|
||||||
|
uint8_t reserved[6];
|
||||||
|
uint8_t tables[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_old_acpi {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t rsdp[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_new_acpi {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t rsdp[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_network {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t dhcpack[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_efi_mmap {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t descr_size;
|
||||||
|
uint32_t descr_vers;
|
||||||
|
uint8_t efi_mmap[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_efi32_ih {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_efi64_ih {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint64_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag_load_base_addr {
|
||||||
|
tag_type type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t load_base_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct info {
|
||||||
|
uint32_t total_size;
|
||||||
|
uint32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline info* get_multiboot_info() {
|
||||||
|
auto addr = read_symbol("__multiboot_info");
|
||||||
|
uint32_t phys = *paddr_t{addr}.access<uint32_t>();
|
||||||
|
return paddr_t{phys}.access<info>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Fn>
|
||||||
|
void visit(const tag* t, Fn&& fn) {
|
||||||
|
#define MB_DISPATCH(tag_enum, TagType) \
|
||||||
|
case tag_type::tag_enum: \
|
||||||
|
if constexpr (requires { fn(static_cast<const TagType*>(nullptr)); }) \
|
||||||
|
fn(reinterpret_cast<const TagType*>(t)); \
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (t->type) {
|
||||||
|
MB_DISPATCH(cmdline, tag_string)
|
||||||
|
MB_DISPATCH(boot_loader_name, tag_string)
|
||||||
|
MB_DISPATCH(module, tag_module)
|
||||||
|
MB_DISPATCH(basic_meminfo, tag_basic_meminfo)
|
||||||
|
MB_DISPATCH(bootdev, tag_bootdev)
|
||||||
|
MB_DISPATCH(mmap, tag_mmap)
|
||||||
|
MB_DISPATCH(vbe, tag_vbe)
|
||||||
|
MB_DISPATCH(framebuffer, tag_framebuffer)
|
||||||
|
MB_DISPATCH(elf_sections, tag_elf_sections)
|
||||||
|
MB_DISPATCH(apm, tag_apm)
|
||||||
|
MB_DISPATCH(efi32, tag_efi32)
|
||||||
|
MB_DISPATCH(efi64, tag_efi64)
|
||||||
|
MB_DISPATCH(smbios, tag_smbios)
|
||||||
|
MB_DISPATCH(acpi_old, tag_old_acpi)
|
||||||
|
MB_DISPATCH(acpi_new, tag_new_acpi)
|
||||||
|
MB_DISPATCH(network, tag_network)
|
||||||
|
MB_DISPATCH(efi_mmap, tag_efi_mmap)
|
||||||
|
MB_DISPATCH(efi32_ih, tag_efi32_ih)
|
||||||
|
MB_DISPATCH(efi64_ih, tag_efi64_ih)
|
||||||
|
MB_DISPATCH(load_base_addr, tag_load_base_addr)
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MB_DISPATCH
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Fn>
|
||||||
|
void visit_all(const info* mb, Fn&& fn) {
|
||||||
|
auto ptr = reinterpret_cast<const uint8_t*>(mb) + sizeof(info);
|
||||||
|
const auto end = reinterpret_cast<const uint8_t*>(mb) + mb->total_size;
|
||||||
|
while (ptr < end) {
|
||||||
|
auto t = reinterpret_cast<const tag*>(ptr);
|
||||||
|
if (t->type == tag_type::end) break;
|
||||||
|
visit(t, fn);
|
||||||
|
ptr += (t->size + alignment - 1) & ~(alignment - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Fn>
|
||||||
|
void visit_all(Fn&& fn) {
|
||||||
|
visit_all(get_multiboot_info(), fn);
|
||||||
|
}
|
||||||
|
} // namespace multiboot
|
||||||
38
kernel/include/init/print.h
Normal file
38
kernel/include/init/print.h
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum class Color : uint8_t {
|
||||||
|
Black = 0,
|
||||||
|
Blue = 1,
|
||||||
|
Green = 2,
|
||||||
|
Cyan = 3,
|
||||||
|
Red = 4,
|
||||||
|
Magenta = 5,
|
||||||
|
Brown = 6,
|
||||||
|
LightGray = 7,
|
||||||
|
DarkGray = 8,
|
||||||
|
LightBlue = 9,
|
||||||
|
LightGreen = 10,
|
||||||
|
LightCyan = 11,
|
||||||
|
LightRed = 12,
|
||||||
|
LightMagenta = 13,
|
||||||
|
Yellow = 14,
|
||||||
|
White = 15,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TextAttr {
|
||||||
|
Color fg;
|
||||||
|
Color bg;
|
||||||
|
|
||||||
|
constexpr TextAttr(Color fg = Color::White, Color bg = Color::Black) : fg(fg), bg(bg) {}
|
||||||
|
|
||||||
|
// Returns the attribute in the high byte, ready to OR with a character value.
|
||||||
|
constexpr uint16_t word() const {
|
||||||
|
return (uint16_t)(((uint8_t)bg << 4) | (uint8_t)fg) << 8;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void print(const char* str, TextAttr attr = {});
|
||||||
|
void print_dec(uint64_t value, TextAttr attr = {});
|
||||||
|
void print_hex(uint64_t value, TextAttr attr = {});
|
||||||
39
kernel/include/memory/pointer.h
Normal file
39
kernel/include/memory/pointer.h
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "util/number.h"
|
||||||
|
|
||||||
|
constexpr uint64_t high_base = 0xFFFF800000000000;
|
||||||
|
|
||||||
|
#define read_symbol(symbol) [](){uint64_t res; asm volatile("movabsq $" symbol ", %0": "=r"(res)); return res;}()
|
||||||
|
|
||||||
|
struct paddr_t {
|
||||||
|
uint64_t address;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* access() {
|
||||||
|
return reinterpret_cast<T*>(address+high_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void* operator new(size_t, void* p) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* operator new[](size_t, void* p) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* memcpy(void* dest, const void* src, size_t n) {
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
((uint8_t*) dest)[i] = ((uint8_t*) src)[i];
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* memset(void* dest, int c, size_t n) {
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
((uint8_t*) dest)[i] = (uint8_t) c;
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
19
kernel/include/memory/sections.h
Normal file
19
kernel/include/memory/sections.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
struct KernelSection {
|
||||||
|
uint64_t vma_start;
|
||||||
|
uint64_t vma_end;
|
||||||
|
const char* name;
|
||||||
|
|
||||||
|
paddr_t phys_start() const { return paddr_t{vma_start >= high_base ? vma_start - high_base : vma_start}; }
|
||||||
|
paddr_t phys_end() const { return paddr_t{vma_end >= high_base ? vma_end - high_base : vma_end}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
extern KernelSection __reserved_ranges_start__[], __reserved_ranges_end__[];
|
||||||
|
|
||||||
|
template<typename Fn>
|
||||||
|
void for_each_reserved_section(Fn&& fn) {
|
||||||
|
for (auto* s = __reserved_ranges_start__; s < __reserved_ranges_end__; ++s)
|
||||||
|
fn(*s);
|
||||||
|
}
|
||||||
9
kernel/include/util/function.h
Normal file
9
kernel/include/util/function.h
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
struct overloaded : Ts... {
|
||||||
|
using Ts::operator()...;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
overloaded(Ts...) -> overloaded<Ts...>;
|
||||||
6
kernel/include/util/number.h
Normal file
6
kernel/include/util/number.h
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
using size_t = uint64_t;
|
||||||
|
using ssize_t = int64_t;
|
||||||
7
kernel/iso/boot/grub/grub.cfg
Normal file
7
kernel/iso/boot/grub/grub.cfg
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
set timeout=0
|
||||||
|
set default=0
|
||||||
|
|
||||||
|
menuentry "PrOSess" {
|
||||||
|
multiboot2 /boot/kernel.bin
|
||||||
|
boot
|
||||||
|
}
|
||||||
89
kernel/linker.ld
Normal file
89
kernel/linker.ld
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
ENTRY(__start)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
MULTIBOOT_HEADER_PV : ORIGIN = 16k, LENGTH = 4k
|
||||||
|
TRAMPOLINE_PV : ORIGIN = 0x0, LENGTH = 16k
|
||||||
|
START_MEMORY_PV : ORIGIN = 20k, LENGTH = 44k
|
||||||
|
|
||||||
|
KERNEL_MEMORY_P : ORIGIN = 64k, LENGTH = (1024M - ORIGIN(KERNEL_MEMORY_P))
|
||||||
|
|
||||||
|
HIGH_KERNEL_V : ORIGIN = 0xFFFF800000000000 + 64k, LENGTH = LENGTH(KERNEL_MEMORY_P)
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.boot : {
|
||||||
|
__boot_start__ = .;
|
||||||
|
KEEP(*(.multiboot_header))
|
||||||
|
__boot_end__ = .;
|
||||||
|
} > MULTIBOOT_HEADER_PV
|
||||||
|
.startup_text : {
|
||||||
|
__startup_text_start__ = .;
|
||||||
|
*(.startup_text)
|
||||||
|
__startup_text_end__ = .;
|
||||||
|
} > START_MEMORY_PV
|
||||||
|
.startup_data : {
|
||||||
|
__startup_data_start__ = .;
|
||||||
|
KEEP(*(.startup_data))
|
||||||
|
__startup_data_end__ = .;
|
||||||
|
} > START_MEMORY_PV
|
||||||
|
.text : {
|
||||||
|
__text_start__ = .;
|
||||||
|
*(EXCLUDE_FILE(*trampoline*) .text)
|
||||||
|
__text_end__ = .;
|
||||||
|
} > HIGH_KERNEL_V AT > KERNEL_MEMORY_P
|
||||||
|
.rodata : {
|
||||||
|
__rodata_start__ = .;
|
||||||
|
*(EXCLUDE_FILE(*trampoline*) .rodata)
|
||||||
|
__rodata_end__ = .;
|
||||||
|
} > HIGH_KERNEL_V AT > KERNEL_MEMORY_P
|
||||||
|
.data : {
|
||||||
|
__data_start__ = .;
|
||||||
|
*(EXCLUDE_FILE(*trampoline*) .data)
|
||||||
|
__data_end__ = .;
|
||||||
|
} > HIGH_KERNEL_V AT > KERNEL_MEMORY_P
|
||||||
|
.bss : {
|
||||||
|
__bss_start__ = .;
|
||||||
|
*(EXCLUDE_FILE(*trampoline*) .bss)
|
||||||
|
__bss_end__ = .;
|
||||||
|
} > HIGH_KERNEL_V AT > KERNEL_MEMORY_P
|
||||||
|
.reserved_ranges : {
|
||||||
|
__reserved_ranges_start__ = .;
|
||||||
|
KEEP(*(.reserved_ranges))
|
||||||
|
__reserved_ranges_end__ = .;
|
||||||
|
} > HIGH_KERNEL_V AT > KERNEL_MEMORY_P
|
||||||
|
|
||||||
|
.trampoline_text : {
|
||||||
|
__trampoline_text_start__ = .;
|
||||||
|
*trampoline*(.text)
|
||||||
|
__trampoline_text_end__ = .;
|
||||||
|
} > TRAMPOLINE_PV
|
||||||
|
|
||||||
|
.trampoline_data : {
|
||||||
|
__trampoline_data_start__ = .;
|
||||||
|
*trampoline*(.data)
|
||||||
|
__trampoline_data_end__ = .;
|
||||||
|
} > TRAMPOLINE_PV
|
||||||
|
|
||||||
|
.trampoline_bss : {
|
||||||
|
__trampoline_bss_start__ = .;
|
||||||
|
*trampoline*(.bss)
|
||||||
|
__trampoline_bss_end__ = .;
|
||||||
|
} > TRAMPOLINE_PV
|
||||||
|
|
||||||
|
.trampoline_rodata : {
|
||||||
|
__trampoline_rodata_start__ = .;
|
||||||
|
*trampoline*(.rodata)
|
||||||
|
__trampoline_rodata_end__ = .;
|
||||||
|
} > TRAMPOLINE_PV
|
||||||
|
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.comment)
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.note)
|
||||||
|
*(.note.gnu.build-id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
51
kernel/src/init/init.cpp
Normal file
51
kernel/src/init/init.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/sections.h"
|
||||||
|
#include "init/init.h"
|
||||||
|
#include "init/multiboot2.h"
|
||||||
|
#include "init/print.h"
|
||||||
|
|
||||||
|
[[maybe_unused]] [[noreturn]] __attribute__((used)) static void halt() {
|
||||||
|
while (true) __asm__ volatile ("");
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[noreturn]] __attribute__((used)) static void panic(const char* msg) {
|
||||||
|
print(msg, TextAttr{Color::Red, Color::Black});
|
||||||
|
halt();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void step(const char* name, T&& fn) {
|
||||||
|
print("Starting ", {});
|
||||||
|
print(name, {});
|
||||||
|
print("\n", {});
|
||||||
|
fn();
|
||||||
|
print("Finished ", {});
|
||||||
|
print(name, {});
|
||||||
|
print("\n", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadMultiboot() {
|
||||||
|
multiboot::visit_all(overloaded{
|
||||||
|
[](const multiboot::tag_mmap* mem) {
|
||||||
|
print("Tag Memory\n", {});
|
||||||
|
},
|
||||||
|
[](const multiboot::tag_string* str) {
|
||||||
|
print("Tag String (0x", {});
|
||||||
|
print_hex(static_cast<uint64_t>(str->type), {});
|
||||||
|
print("): ", {});
|
||||||
|
print(str->string, {});
|
||||||
|
print("\n", {});
|
||||||
|
},
|
||||||
|
[](const auto* tag) {
|
||||||
|
print("Tag (0x", {});
|
||||||
|
print_hex(static_cast<uint64_t>(tag->type), {});
|
||||||
|
print(")\n", {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[noreturn]] __attribute__((used)) void init() {
|
||||||
|
print("Reached init\n", {});
|
||||||
|
//step("multiboot", loadMultiboot);
|
||||||
|
halt();
|
||||||
|
}
|
||||||
80
kernel/src/init/print.cpp
Normal file
80
kernel/src/init/print.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include "init/print.h"
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
static constexpr uint64_t VGA_PHYS_BASE = 0xb8000;
|
||||||
|
static constexpr int VGA_COLS = 80;
|
||||||
|
static constexpr int VGA_ROWS = 25;
|
||||||
|
static constexpr int BYTES_PER_CELL = 2;
|
||||||
|
static constexpr int BYTES_PER_ROW = VGA_COLS * BYTES_PER_CELL;
|
||||||
|
static constexpr int HEX_BITS = 4;
|
||||||
|
static constexpr int HEX_TOP_SHIFT = (sizeof(uint64_t) * 8) - HEX_BITS;
|
||||||
|
|
||||||
|
static const char hex_chars[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
static volatile uint32_t* cursor() {
|
||||||
|
auto cursor_addr = read_symbol("__cursor");
|
||||||
|
return paddr_t{cursor_addr}.access<volatile uint32_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static volatile uint16_t* vga_cell(uint32_t offset) {
|
||||||
|
return paddr_t{VGA_PHYS_BASE + offset}.access<volatile uint16_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void next_line() {
|
||||||
|
*cursor() = ((*cursor() + BYTES_PER_ROW - 1) / BYTES_PER_ROW) * BYTES_PER_ROW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put_char(char ch, uint16_t attr_word) {
|
||||||
|
if (ch == '\n') {
|
||||||
|
next_line();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*vga_cell(*cursor()) = attr_word | (uint8_t)ch;
|
||||||
|
*cursor() += BYTES_PER_CELL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
*cursor() = 0;
|
||||||
|
for (int i = 0; i < VGA_COLS * VGA_ROWS; i++) {
|
||||||
|
*vga_cell(i * BYTES_PER_CELL) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(const char* str, TextAttr attr) {
|
||||||
|
uint16_t w = attr.word();
|
||||||
|
while (*str) {
|
||||||
|
put_char(*str++, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_dec(uint64_t value, TextAttr attr) {
|
||||||
|
uint16_t w = attr.word();
|
||||||
|
if (value == 0) {
|
||||||
|
put_char('0', w);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buf[20];
|
||||||
|
int len = 0;
|
||||||
|
while (value > 0) {
|
||||||
|
buf[len++] = '0' + (value % 10);
|
||||||
|
value /= 10;
|
||||||
|
}
|
||||||
|
for (int i = len - 1; i >= 0; i--) {
|
||||||
|
put_char(buf[i], w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_hex(uint64_t value, TextAttr attr) {
|
||||||
|
uint16_t w = attr.word();
|
||||||
|
put_char('0', w);
|
||||||
|
put_char('x', w);
|
||||||
|
bool leading = true;
|
||||||
|
for (int shift = HEX_TOP_SHIFT; shift >= 0; shift -= HEX_BITS) {
|
||||||
|
uint8_t nibble = (value >> shift) & 0xF;
|
||||||
|
if (leading && nibble == 0 && shift > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
leading = false;
|
||||||
|
put_char(hex_chars[nibble], w);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
kernel/src/init/sections.cpp
Normal file
28
kernel/src/init/sections.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "memory/sections.h"
|
||||||
|
|
||||||
|
#define RESERVE_SECTION(n) \
|
||||||
|
extern char __##n##_start__[], __##n##_end__[]; \
|
||||||
|
[[maybe_unused]] static const KernelSection _rsv_##n \
|
||||||
|
__attribute__((section(".reserved_ranges"), used)) = { \
|
||||||
|
(uint64_t)__##n##_start__, \
|
||||||
|
(uint64_t)__##n##_end__, \
|
||||||
|
#n \
|
||||||
|
}
|
||||||
|
|
||||||
|
RESERVE_SECTION(boot);
|
||||||
|
RESERVE_SECTION(startup_text);
|
||||||
|
RESERVE_SECTION(startup_data);
|
||||||
|
RESERVE_SECTION(text);
|
||||||
|
RESERVE_SECTION(rodata);
|
||||||
|
RESERVE_SECTION(data);
|
||||||
|
RESERVE_SECTION(bss);
|
||||||
|
[[maybe_unused]] static const KernelSection _rsv_reserved_ranges
|
||||||
|
__attribute__((section(".reserved_ranges"), used)) = {
|
||||||
|
(uint64_t)__reserved_ranges_start__,
|
||||||
|
(uint64_t)__reserved_ranges_end__,
|
||||||
|
"reserved_ranges"
|
||||||
|
};
|
||||||
|
RESERVE_SECTION(trampoline_text);
|
||||||
|
RESERVE_SECTION(trampoline_data);
|
||||||
|
RESERVE_SECTION(trampoline_bss);
|
||||||
|
RESERVE_SECTION(trampoline_rodata);
|
||||||
227
kernel/src/startup/entry.cpp
Normal file
227
kernel/src/startup/entry.cpp
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
#include "init/init.h"
|
||||||
|
|
||||||
|
extern "C" [[maybe_unused]] [[noreturn]] __attribute__((used)) void __entry64() {
|
||||||
|
init();
|
||||||
|
while (true) __asm__ volatile ("");
|
||||||
|
}
|
||||||
|
|
||||||
|
asm(R"(
|
||||||
|
.global __start
|
||||||
|
|
||||||
|
.section .startup_text, "ax"
|
||||||
|
.type __start, @function
|
||||||
|
.code32
|
||||||
|
.align 16
|
||||||
|
__start:
|
||||||
|
cli
|
||||||
|
mov $__start_stack_end, %esp
|
||||||
|
mov %ebx, __multiboot_info
|
||||||
|
call __clear
|
||||||
|
mov $__hello_string, %esi
|
||||||
|
call __print
|
||||||
|
call __check_if_x64
|
||||||
|
call __go_to_x64
|
||||||
|
jmp __stop32
|
||||||
|
__stop32:
|
||||||
|
hlt
|
||||||
|
jmp __stop32
|
||||||
|
|
||||||
|
__x64_not_supported:
|
||||||
|
mov $__x64_not_supported_string, %esi
|
||||||
|
call __print
|
||||||
|
jmp __stop32
|
||||||
|
|
||||||
|
__check_if_x64:
|
||||||
|
pushfl
|
||||||
|
pop %eax
|
||||||
|
mov %eax, %ecx
|
||||||
|
xor $(1 << 21), %eax
|
||||||
|
push %eax
|
||||||
|
popfl
|
||||||
|
pushfl
|
||||||
|
pop %eax
|
||||||
|
push %ecx
|
||||||
|
popfl
|
||||||
|
cmp %eax, %ecx
|
||||||
|
je __x64_not_supported
|
||||||
|
|
||||||
|
mov $0x80000000, %eax
|
||||||
|
cpuid
|
||||||
|
cmp $0x80000001, %eax
|
||||||
|
jb __x64_not_supported
|
||||||
|
mov $0x80000001, %eax
|
||||||
|
cpuid
|
||||||
|
test $(1 << 29), %edx
|
||||||
|
jz __x64_not_supported
|
||||||
|
mov $__x64_supported_string, %esi
|
||||||
|
call __print
|
||||||
|
ret
|
||||||
|
|
||||||
|
__go_to_x64:
|
||||||
|
push %ebx
|
||||||
|
mov $__page_level_4, %eax
|
||||||
|
mov %eax, %cr3
|
||||||
|
|
||||||
|
mov %cr4, %eax
|
||||||
|
or $(0x1 << 5), %eax
|
||||||
|
mov %eax, %cr4
|
||||||
|
|
||||||
|
mov $0xC0000080, %ecx
|
||||||
|
rdmsr
|
||||||
|
or $(0x1 << 8), %eax
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
mov %cr0, %eax
|
||||||
|
or $(0x1 << 31), %eax
|
||||||
|
mov %eax, %cr0
|
||||||
|
|
||||||
|
pop %edi
|
||||||
|
|
||||||
|
lgdt __gdt_end
|
||||||
|
jmp $0b1000, $__start64
|
||||||
|
|
||||||
|
jmp __stop32
|
||||||
|
|
||||||
|
.code64
|
||||||
|
.align 16
|
||||||
|
__start64:
|
||||||
|
mov $0b10000, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %es
|
||||||
|
mov %ax, %fs
|
||||||
|
mov %ax, %gs
|
||||||
|
mov %ax, %ss
|
||||||
|
movabsq $__start64_high, %rax
|
||||||
|
jmp* %rax
|
||||||
|
__stop64:
|
||||||
|
hlt
|
||||||
|
jmp __stop64
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.type __start64_high, @function
|
||||||
|
.code64
|
||||||
|
.align 16
|
||||||
|
__start64_high:
|
||||||
|
call __entry64
|
||||||
|
hlt
|
||||||
|
jmp __start64_high
|
||||||
|
)");
|
||||||
|
|
||||||
|
// data section
|
||||||
|
asm(R"(
|
||||||
|
.global __multiboot_info
|
||||||
|
.global __cursor
|
||||||
|
.section .startup_data, "aw"
|
||||||
|
__cursor:
|
||||||
|
.int 0x0
|
||||||
|
__hello_string:
|
||||||
|
.string "Starting PrOSess! 32bit start!\n"
|
||||||
|
__x64_not_supported_string:
|
||||||
|
.string "x64 is not supported!\n"
|
||||||
|
__x64_supported_string:
|
||||||
|
.string "x64 is supported!\n"
|
||||||
|
__multiboot_info:
|
||||||
|
.long 0x0
|
||||||
|
|
||||||
|
__start_stack:
|
||||||
|
.skip 0x1000
|
||||||
|
.align 8
|
||||||
|
__start_stack_end:
|
||||||
|
.quad 0
|
||||||
|
)");
|
||||||
|
|
||||||
|
// string operation section
|
||||||
|
asm(R"(
|
||||||
|
.section .startup_text, "ax"
|
||||||
|
.code32
|
||||||
|
.align 16
|
||||||
|
__clear:
|
||||||
|
movl $0, (__cursor)
|
||||||
|
mov $0x0, %eax
|
||||||
|
mov $0xb8000, %edi
|
||||||
|
mov $0x2000, %ecx
|
||||||
|
rep stosw
|
||||||
|
ret
|
||||||
|
|
||||||
|
__print:
|
||||||
|
mov $0xB8000, %edi
|
||||||
|
add (__cursor), %edi
|
||||||
|
__print_loop:
|
||||||
|
mov (%esi), %al
|
||||||
|
mov $0x0F, %ah
|
||||||
|
cmp $0, %al
|
||||||
|
je __print_end
|
||||||
|
cmp $'\n', %al
|
||||||
|
je __print_next_line
|
||||||
|
mov %ax, (%edi)
|
||||||
|
add $2, %edi
|
||||||
|
add $1, %esi
|
||||||
|
jmp __print_loop
|
||||||
|
__print_next_line:
|
||||||
|
sub $0xB8000, %edi
|
||||||
|
mov %edi, (__cursor)
|
||||||
|
add $0xB8000, %edi
|
||||||
|
call __next_line
|
||||||
|
mov $0xB8000, %edi
|
||||||
|
add (__cursor), %edi
|
||||||
|
add $1, %esi
|
||||||
|
jmp __print_loop
|
||||||
|
__print_end:
|
||||||
|
sub $0xB8000, %edi
|
||||||
|
mov %edi, (__cursor)
|
||||||
|
ret
|
||||||
|
|
||||||
|
__next_line:
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
mov (__cursor), %eax
|
||||||
|
|
||||||
|
leal 159(%eax), %ecx
|
||||||
|
movl $1717986919, %eax
|
||||||
|
imull %ecx
|
||||||
|
sarl $31, %ecx
|
||||||
|
sarl $6, %edx
|
||||||
|
subl %ecx, %edx
|
||||||
|
leal (%edx,%edx,4), %eax
|
||||||
|
sall $5, %eax
|
||||||
|
|
||||||
|
mov %eax, (__cursor)
|
||||||
|
pop %ecx
|
||||||
|
pop %eax
|
||||||
|
ret
|
||||||
|
)");
|
||||||
|
|
||||||
|
// tmp page table
|
||||||
|
asm(R"(
|
||||||
|
.section .startup_data, "aw"
|
||||||
|
.align 0x1000
|
||||||
|
__page_level_4:
|
||||||
|
.quad __page_level_3_low_1gb_identity_map + ((1 << 0) | (1 << 1))
|
||||||
|
.zero 0x7F8
|
||||||
|
.quad __page_level_3_kernel_1gb_identity_map + ((1 << 0) | (1 << 1))
|
||||||
|
.zero 0x7F8
|
||||||
|
|
||||||
|
.align 0x1000
|
||||||
|
__page_level_3_low_1gb_identity_map:
|
||||||
|
.quad (1 << 0) | (1 << 1) | (1 << 7) | 0x0
|
||||||
|
.zero 0xFF8 # rest of table is 0
|
||||||
|
|
||||||
|
.align 0x1000
|
||||||
|
__page_level_3_kernel_1gb_identity_map:
|
||||||
|
.quad (1 << 0) | (1 << 1) | (1 << 7) | 0x0
|
||||||
|
.zero 0xFF8 # rest of table is 0
|
||||||
|
)");
|
||||||
|
|
||||||
|
// startup gdt
|
||||||
|
asm(R"(
|
||||||
|
.section .startup_data, "aw"
|
||||||
|
.align 0x1000
|
||||||
|
__gdt:
|
||||||
|
.quad 0
|
||||||
|
.quad (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) # code segment
|
||||||
|
.quad (1 << 41) | (1 << 44) | (1 << 47) # data segment
|
||||||
|
.align 0x1000
|
||||||
|
__gdt_end:
|
||||||
|
.word __gdt_end - __gdt - 1
|
||||||
|
.quad __gdt
|
||||||
|
)");
|
||||||
16
kernel/src/startup/multiboot.cpp
Normal file
16
kernel/src/startup/multiboot.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
asm(R"(
|
||||||
|
.global __multiboot_header
|
||||||
|
.section .multiboot_header, "a"
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
__multiboot_header:
|
||||||
|
.int 0xe85250d6 # multiboot2
|
||||||
|
.int 0 # protected mode i386
|
||||||
|
.int __multiboot_header_end - __multiboot_header
|
||||||
|
.int 0x100000000 - (0xe85250d6 + 0 + (__multiboot_header_end - __multiboot_header))
|
||||||
|
|
||||||
|
.word 0
|
||||||
|
.word 0
|
||||||
|
.int 8
|
||||||
|
__multiboot_header_end:
|
||||||
|
)");
|
||||||
16
run.sh
Executable file
16
run.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
||||||
|
bear --output "$SCRIPT_DIR/compile_commands.json" -- make -C "$SCRIPT_DIR/kernel" all || exit 1
|
||||||
|
mkdir -p "$SCRIPT_DIR/testenv/dist"
|
||||||
|
cp "$SCRIPT_DIR/kernel/output/kernel.iso" "$SCRIPT_DIR/testenv/dist/kernel.iso"
|
||||||
|
cd "$SCRIPT_DIR/testenv" || exit 1
|
||||||
|
|
||||||
|
CPU="-cpu Opteron_G1-v1,pdpe1gb=on"
|
||||||
|
|
||||||
|
if [ "$1" = "debug" ]; then
|
||||||
|
qemu-system-x86_64 -nodefaults -readconfig qemuConfig.cfg $CPU -s -S -daemonize
|
||||||
|
else
|
||||||
|
qemu-system-x86_64 -nodefaults -readconfig qemuConfig.cfg $CPU
|
||||||
|
fi
|
||||||
3
testenv/.gitignore
vendored
Normal file
3
testenv/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
dist/
|
||||||
|
image_file
|
||||||
|
dump.dat
|
||||||
81
testenv/qemuConfig.cfg
Normal file
81
testenv/qemuConfig.cfg
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
[machine]
|
||||||
|
type = "q35"
|
||||||
|
[memory]
|
||||||
|
size = "6144"
|
||||||
|
[device "ich9-pcie-port-1"]
|
||||||
|
driver = "ioh3420"
|
||||||
|
multifunction = "on"
|
||||||
|
bus = "pcie.0"
|
||||||
|
addr = "1c.0"
|
||||||
|
port = "1"
|
||||||
|
chassis = "1"
|
||||||
|
[device "ich9-pcie-port-2"]
|
||||||
|
driver = "ioh3420"
|
||||||
|
multifunction = "on"
|
||||||
|
bus = "pcie.0"
|
||||||
|
addr = "1c.1"
|
||||||
|
port = "2"
|
||||||
|
chassis = "2"
|
||||||
|
[device "ich9-pcie-port-3"]
|
||||||
|
driver = "ioh3420"
|
||||||
|
multifunction = "on"
|
||||||
|
bus = "pcie.0"
|
||||||
|
addr = "1c.2"
|
||||||
|
port = "3"
|
||||||
|
chassis = "3"
|
||||||
|
[device "ich9-pcie-port-4"]
|
||||||
|
driver = "ioh3420"
|
||||||
|
multifunction = "on"
|
||||||
|
bus = "pcie.0"
|
||||||
|
addr = "1c.3"
|
||||||
|
port = "4"
|
||||||
|
chassis = "4"
|
||||||
|
[device "ich9-pci-bridge"]
|
||||||
|
driver = "i82801b11-bridge"
|
||||||
|
bus = "pcie.0"
|
||||||
|
addr = "1e.0"
|
||||||
|
[device "usbDevice"]
|
||||||
|
driver = "qemu-xhci"
|
||||||
|
bus = "pcie.0"
|
||||||
|
addr = "1d.0"
|
||||||
|
[device "video"]
|
||||||
|
driver = "virtio-vga"
|
||||||
|
bus = "pcie.0"
|
||||||
|
addr = "01.0"
|
||||||
|
[device "sata-optical-disk"]
|
||||||
|
driver = "ide-cd"
|
||||||
|
bus = "ide.0"
|
||||||
|
drive = "optical-disk"
|
||||||
|
bootindex = "1"
|
||||||
|
[drive "optical-disk"]
|
||||||
|
file = "dist/kernel.iso"
|
||||||
|
format = "raw"
|
||||||
|
if = "none"
|
||||||
|
[device "sata-disk"]
|
||||||
|
driver = "ide-hd"
|
||||||
|
bus = "ide.1"
|
||||||
|
drive = "disk"
|
||||||
|
bootindex = "2"
|
||||||
|
[drive "disk"]
|
||||||
|
file = "image_file"
|
||||||
|
format = "raw"
|
||||||
|
if = "none"
|
||||||
|
[smp-opts]
|
||||||
|
cpus = "4"
|
||||||
|
cores = "4"
|
||||||
|
threads = "1"
|
||||||
|
sockets = "1"
|
||||||
|
[device "usb-kbd"]
|
||||||
|
driver = "usb-kbd"
|
||||||
|
bus = "usbDevice.0"
|
||||||
|
[netdev "n1"]
|
||||||
|
type = "user"
|
||||||
|
hostfwd = "udp:127.0.0.1:1234-:1234"
|
||||||
|
hostfwd = "tcp:127.0.0.1:1234-:1234"
|
||||||
|
[object "net-dump"]
|
||||||
|
qom-type = "filter-dump"
|
||||||
|
netdev = "n1"
|
||||||
|
file = "dump.dat"
|
||||||
|
[device "nic"]
|
||||||
|
driver = "e1000e"
|
||||||
|
netdev = "n1"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue