From 331768669bee7bd4c2304f992106154cba0fde59 Mon Sep 17 00:00:00 2001 From: selmentdev Date: Thu, 1 Jun 2017 23:23:21 +0200 Subject: [PATCH 1/8] Project structure changed to use generic makefile build system :) --- 042-osdev-08/build.py | 77 -- 042-osdev-08/build/build.py | 46 + 042-osdev-08/build/makefile | 28 + 042-osdev-08/{ => build}/osdev.bochsrc | 0 042-osdev-08/common.h | 4 - 042-osdev-08/floppy.bin | Bin 27136 -> 0 bytes 042-osdev-08/hal.c | 14 - 042-osdev-08/int_handlers.c | 63 - 042-osdev-08/int_handlers.h | 3 - 042-osdev-08/kernel64 | Bin 9480 -> 0 bytes 042-osdev-08/make/build.mk | 635 ++++++++++ 042-osdev-08/make/macros.mk | 105 ++ 042-osdev-08/make/recurse.mk | 43 + 042-osdev-08/make/toolchain.mk | 195 +++ 042-osdev-08/makefile | 15 + 042-osdev-08/source/bootloader/project.mk | 20 + .../{ => source/bootloader/source}/stage1.asm | 0 .../{ => source/bootloader/source}/stage2.asm | 0 042-osdev-08/source/dirs.mk | 2 + 042-osdev-08/source/kernel/include/common.h | 9 + .../{ => source/kernel/include}/crt.h | 0 .../{ => source/kernel/include}/hal.h | 2 +- .../{ => source/kernel/include}/idt.h | 0 .../source/kernel/include/int_handlers.h | 35 + .../{ => source/kernel/include}/terminal.h | 0 .../kernel/include}/terminal_backend_b8000.h | 0 042-osdev-08/source/kernel/project.mk | 34 + 042-osdev-08/{ => source/kernel/source}/crt.c | 0 042-osdev-08/source/kernel/source/hal.c | 22 + 042-osdev-08/{ => source/kernel/source}/idt.c | 0 .../source/kernel/source/int_handlers.c | 36 + .../kernel/source/int_wrappers.S} | 0 .../{ => source/kernel/source}/kernel.c | 0 042-osdev-08/source/kernel/source/rtl.c | 1069 +++++++++++++++++ 042-osdev-08/source/kernel/source/ssp.c | 18 + .../{ => source/kernel/source}/terminal.c | 77 +- .../kernel/source}/terminal_backend_b8000.c | 0 042-osdev-08/stage1 | Bin 512 -> 0 bytes 042-osdev-08/stage2 | Bin 16896 -> 0 bytes 39 files changed, 2339 insertions(+), 213 deletions(-) delete mode 100644 042-osdev-08/build.py create mode 100644 042-osdev-08/build/build.py create mode 100644 042-osdev-08/build/makefile rename 042-osdev-08/{ => build}/osdev.bochsrc (100%) delete mode 100644 042-osdev-08/common.h delete mode 100644 042-osdev-08/floppy.bin delete mode 100644 042-osdev-08/hal.c delete mode 100644 042-osdev-08/int_handlers.c delete mode 100644 042-osdev-08/int_handlers.h delete mode 100644 042-osdev-08/kernel64 create mode 100644 042-osdev-08/make/build.mk create mode 100644 042-osdev-08/make/macros.mk create mode 100644 042-osdev-08/make/recurse.mk create mode 100644 042-osdev-08/make/toolchain.mk create mode 100644 042-osdev-08/makefile create mode 100644 042-osdev-08/source/bootloader/project.mk rename 042-osdev-08/{ => source/bootloader/source}/stage1.asm (100%) rename 042-osdev-08/{ => source/bootloader/source}/stage2.asm (100%) create mode 100644 042-osdev-08/source/dirs.mk create mode 100644 042-osdev-08/source/kernel/include/common.h rename 042-osdev-08/{ => source/kernel/include}/crt.h (100%) rename 042-osdev-08/{ => source/kernel/include}/hal.h (85%) rename 042-osdev-08/{ => source/kernel/include}/idt.h (100%) create mode 100644 042-osdev-08/source/kernel/include/int_handlers.h rename 042-osdev-08/{ => source/kernel/include}/terminal.h (100%) rename 042-osdev-08/{ => source/kernel/include}/terminal_backend_b8000.h (100%) create mode 100644 042-osdev-08/source/kernel/project.mk rename 042-osdev-08/{ => source/kernel/source}/crt.c (100%) create mode 100644 042-osdev-08/source/kernel/source/hal.c rename 042-osdev-08/{ => source/kernel/source}/idt.c (100%) create mode 100644 042-osdev-08/source/kernel/source/int_handlers.c rename 042-osdev-08/{int_wrappers.s => source/kernel/source/int_wrappers.S} (100%) rename 042-osdev-08/{ => source/kernel/source}/kernel.c (100%) create mode 100644 042-osdev-08/source/kernel/source/rtl.c create mode 100644 042-osdev-08/source/kernel/source/ssp.c rename 042-osdev-08/{ => source/kernel/source}/terminal.c (72%) rename 042-osdev-08/{ => source/kernel/source}/terminal_backend_b8000.c (100%) delete mode 100644 042-osdev-08/stage1 delete mode 100644 042-osdev-08/stage2 diff --git a/042-osdev-08/build.py b/042-osdev-08/build.py deleted file mode 100644 index cd28be0..0000000 --- a/042-osdev-08/build.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/python -import os -import subprocess -from glob import glob - -def fix_stage1_size(): - stage2_size = os.stat("stage2").st_size - kernel_size = os.stat("kernel64").st_size - - stage2_size = (stage2_size + kernel_size + 511) / 512 - - if stage2_size >= 255: - raise Exception("stage2 & kernel are too large") - - with open("stage1", "rb+") as f: - d = f.read() - idx = d.index("\xb0\xcc\x90\x90") - d = bytearray(d) - d[idx+1] = stage2_size - f.seek(0) - f.write(d) - - -cmds_to_run = [] - -cc_flags = "-std=c99 -nostdlib -c -O0 -Wall -Wextra -masm=intel -ggdb" -ld_flags = "-std=c99 -nostdlib -o kernel64 -O0 -Wall -Wextra -masm=intel -ggdb" - -objfiles = [] - -for fname in glob("*.c"): - cmds_to_run.append("gcc %s %s" % (fname, cc_flags)) - objfiles.append("%s.o" % os.path.splitext(fname)[0]) - -as_flags = "-masm=intel -ggdb -c" - -for fname in glob("*.s"): - cmds_to_run.append("gcc %s %s" % (fname, as_flags)) - objfiles.append("%s.o" % os.path.splitext(fname)[0]) - -cmds_to_run.extend([ - "gcc %s %s" % (' '.join(objfiles), ld_flags), - "strip kernel64", - "nasm stage1.asm", - "nasm stage2.asm", - fix_stage1_size -]) - -files_to_img = [ - "stage1", - "stage2", - "kernel64" -] - -for cmd in cmds_to_run: - if type(cmd) is str: - print "Running:", cmd - print subprocess.check_output(cmd, shell=True) - else: - print "Calling:", cmd.func_name - cmd() - -buf = [] -for fn in files_to_img: - with open(fn, "rb") as f: - d = f.read() - buf.append(d) - - if len(d) % 512 == 0: - continue - - padding_size = 512 - len(d) % 512 - buf.append("\0" * padding_size); - -with open("floppy.bin", "wb") as f: - f.write(''.join(buf)) - diff --git a/042-osdev-08/build/build.py b/042-osdev-08/build/build.py new file mode 100644 index 0000000..6eabc7a --- /dev/null +++ b/042-osdev-08/build/build.py @@ -0,0 +1,46 @@ +#!/usr/bin/python +import os +import subprocess +from glob import glob + +def fix_stage1_size(): + stage2_size = os.stat("bootloader/stage2").st_size + kernel_size = os.stat("kernel/kernel64.elf").st_size + + stage2_size = (stage2_size + kernel_size + 511) / 512 + + if stage2_size >= 255: + raise Exception("stage2 & kernel are too large") + + with open("bootloader/stage1", "rb+") as f: + d = f.read() + idx = d.index("\xb0\xcc\x90\x90") + d = bytearray(d) + d[idx+1] = stage2_size + f.seek(0) + f.write(d) + +fix_stage1_size() + +files_to_img = [ + "bootloader/stage1", + "bootloader/stage2", + "kernel/kernel64.elf" +] + +buf = [] +for fn in files_to_img: + with open(fn, "rb") as f: + d = f.read() + print("length: " + str(len(d))) + buf.append(d) + + if len(d) % 512 == 0: + continue + + padding_size = 512 - len(d) % 512 + buf.append("\0" * padding_size); + +with open("floppy.bin", "wb") as f: + f.write(''.join(buf)) + diff --git a/042-osdev-08/build/makefile b/042-osdev-08/build/makefile new file mode 100644 index 0000000..6a5d02f --- /dev/null +++ b/042-osdev-08/build/makefile @@ -0,0 +1,28 @@ +include ../make/macros.mk + +clean: + $(host.rm) ./floppy.bin + +floppy.bin: + python ./build.py + + +QEMU_FLAGS = \ + -m 2048 \ + -cpu Haswell \ + -D qemu.log \ + -d cpu_reset,int,guest_errors \ + -vga std \ + -smp 4 + +QEMU_FLAGS_DEBUG = \ + -serial file:serial.log + +run-qemu: floppy.bin + qemu-system-x86_64 --fda $(<) $(QEMU_FLAGS) $(QEMU_FLAGS_DEBUG) + cat serial.log + +run-bochs: floppy.bin + +.PHONY: run-qemu run-bochs +build: run-qemu \ No newline at end of file diff --git a/042-osdev-08/osdev.bochsrc b/042-osdev-08/build/osdev.bochsrc similarity index 100% rename from 042-osdev-08/osdev.bochsrc rename to 042-osdev-08/build/osdev.bochsrc diff --git a/042-osdev-08/common.h b/042-osdev-08/common.h deleted file mode 100644 index 210b336..0000000 --- a/042-osdev-08/common.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#define UNUSED(a) (void)(a) - -typedef unsigned long long size_t; diff --git a/042-osdev-08/floppy.bin b/042-osdev-08/floppy.bin deleted file mode 100644 index 8b50ced4a521fdce991760ac306f012386825eec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27136 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 Sf)n}eRQ{oK`L^H1@_z&ElzS`y diff --git a/042-osdev-08/hal.c b/042-osdev-08/hal.c deleted file mode 100644 index 47e810e..0000000 --- a/042-osdev-08/hal.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "hal.h" - -void HAL_PortOutByte(int port, unsigned char v) { - __asm("out dx, al\n" : : "a" (v), "d" (port)); -} - -void HAL_PortOutWord(int port, unsigned short v) { - __asm("out dx, ax\n" : : "a" (v), "d" (port)); -} - -void HAL_PortOutDword(int port, unsigned int v) { - __asm("out dx, eax\n" : : "a" (v), "d" (port)); -} - diff --git a/042-osdev-08/int_handlers.c b/042-osdev-08/int_handlers.c deleted file mode 100644 index e1611b4..0000000 --- a/042-osdev-08/int_handlers.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "common.h" -#include "terminal.h" -#include "terminal_backend_b8000.h" - -// Thanks to Karol Grzybowski -typedef struct TrapFrame { - uint64_t r15; - uint64_t r14; - uint64_t r13; - uint64_t r12; - uint64_t r11; - uint64_t r10; - uint64_t r9; - uint64_t r8; - uint64_t rbp; - uint64_t rdi; - uint64_t rsi; - uint64_t rdx; - uint64_t rcx; - uint64_t rbx; - uint64_t rax; - uint64_t rsp; - - /*uint64_t trap_number; - uint64_t error_code;*/ - - uint64_t rip; - uint64_t segment_cs; - /*uint64_t rflags; - uint64_t rsp; - uint64_t segment_ss;*/ - -} TrapFrame; - -void GuruPanicOfDeath(const char *reason, TrapFrame *frame) { - TerminalBackend *con = TerminalBackendB8000(); - T_ClearScreen(con); - T_PutText(con, "Guru Panic Of Death!!!\n\n"); - T_Printf(con, "Reason: %s\n\n", reason); - T_PutText(con, "State:\n\n"); - - T_Printf(con, "RAX: %x\t\t R8: %x\n", frame->rax, frame->r8); - T_Printf(con, "RBX: %x\t\t R9: %x\n", frame->rbx, frame->r9); - T_Printf(con, "RCX: %x\t\t R10: %x\n", frame->rcx, frame->r10); - T_Printf(con, "RDX: %x\t\t R11: %x\n", frame->rdx, frame->r11); - T_Printf(con, "RSI: %x\t\t R12: %x\n", frame->rsi, frame->r12); - T_Printf(con, "RDI: %x\t\t R13: %x\n", frame->rdi, frame->r13); - T_Printf(con, "RBP: %x\t\t R14: %x\n", frame->rbp, frame->r14); - T_Printf(con, "RSP: %x\t\t R15: %x\n", frame->rsp, frame->r15); - - T_Printf(con, "CS:RIP: %x:%x\n\n", frame->segment_cs, frame->rip); - - - T_PutText(con, "System halt."); - - for (;;); -} - - -void Int_DE(TrapFrame *frame) { - GuruPanicOfDeath("DIVISION_ERROR", frame); -} - diff --git a/042-osdev-08/int_handlers.h b/042-osdev-08/int_handlers.h deleted file mode 100644 index 454e282..0000000 --- a/042-osdev-08/int_handlers.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -void Int_DE(void); - diff --git a/042-osdev-08/kernel64 b/042-osdev-08/kernel64 deleted file mode 100644 index f814b1c720bd123ee6ce147ee5f0123cc1a7532c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9480 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 Dff2}k diff --git a/042-osdev-08/make/build.mk b/042-osdev-08/make/build.mk new file mode 100644 index 0000000..db59857 --- /dev/null +++ b/042-osdev-08/make/build.mk @@ -0,0 +1,635 @@ +#--------------------------------------------------------------------------------------------------- +# +# By Karol Grzybowski, 2017 +# +#--------------------------------------------------------------------------------------------------- +# +# Parameters: +# +# $(project.name) : [required] +# +# Provides a name of project in build system. +# +# $(project.uuid) : [optional] +# +# Provides project UUID to identify sub-builds. +# +# $(project.path) : [required] +# +# Provides path in build directory to where build target file. +# +# $(project.configuration) : [optional] +# +# Provides project specific configuration type. +# +# Available configuration types are: +# +# - `debug` +# +# Specifies a build configuration with optimizations disabled and +# assertions enabled. +# +# - `checked` +# +# Specifies a build configuration with both optimizations and +# assertions enabled. +# +# - `release` +# +# Specifies a build configuration with optimizations enabled and +# assertions disabled. +# +# +# $(project.component.major) : [required] +# +# Provides major component ID. +# +# $(project.component.minor) : [required] +# +# Provides minor component ID. +# +# $(project.type) : [required] +# +# Provides a project type. +# +# Available project types are: +# +# - `executable` +# +# Specifies an executable file project type. +# +# - `static` +# +# Specifies a static library project type. +# +# - `shared` +# +# Specifies a shared library project type. +# +# - `module` +# +# Specifies a shared kernel module project type. +# +# $(project.kind) : [required] +# +# Provides a project kind. +# +# - `target` +# +# Specifies that project uses target OS toolchain. +# +# - `native` +# +# Specifies that project uses native OS toolchain. +# +# $(project.sources) : [required] +# +# Provides a list of source files. +# +# $(project.defines) : [optional] +# +# Provides a list of compiler defines. +# +# $(project.includes) : [optional] +# +# Provides a list of additional project-specific include directories. +# +# $(project.libraries.static) : [optional] +# +# Provides a list of static libraries required to link project. +# +# $(project.libraries.shared) : [optional] +# +# Provides a list of shared libraries required to link project. +# +# $(project.flags.cc) +# $(project.flags.cc.{machine}) +# +# Provides a list of additional flags for C compiler. +# +# $(project.flags.cxx) +# $(project.flags.cxx.{machine}) +# +# Provides a list of additional flags for C++ compiler. +# +# $(project.flags.as) +# $(project.flags.as.{machine}) +# +# Provides a list of additional flags for assembler. +# +# $(project.flags.rc) +# $(project.flags.rc.{machine}) +# +# Provides a list of additional flags for resource compiler. +# +# $(project.flags.link) +# +# Provides a list of additional flags for linker. +# +#--------------------------------------------------------------------------------------------------- + +#--------------------------------------------------------------------------------------------------- +# +# Include base toolchain makefiles. +# +#--------------------------------------------------------------------------------------------------- +include $(BASE_DIRECTORY)/make/macros.mk +include $(BASE_DIRECTORY)/make/toolchain.mk + +#--------------------------------------------------------------------------------------------------- +# +# Validate required project parameters. +# +#--------------------------------------------------------------------------------------------------- + +ifndef project.name +$(error Variable project.name is required) +endif + +ifndef project.path +$(error Variable project.path is required) +endif + +ifndef project.component.major +$(error Variable project.component.minor is required) +endif + +ifndef project.component.minor +$(error Variable project.component.minor is required) +endif + +ifndef project.type +$(error Variable project.type is required) +endif + +ifndef project.sources +$(error Variable project.sources is required) +endif + +ifdef project.filename +$(error Project result filename can't be overriden) +endif + +#--------------------------------------------------------------------------------------------------- +# +# Apply defaults for optional project parameters. +# +#--------------------------------------------------------------------------------------------------- + +project.kind ?= target +project.uuid ?= $(project.name) +project.configuration ?= debug + +#--------------------------------------------------------------------------------------------------- +# +# Acquire C compiler flags. +# +#--------------------------------------------------------------------------------------------------- + +build.flags.cc := $(project.flags.cc) +build.flags.cc += $(project.flags.cc.${project.configuration}) +build.flags.cc += $(toolchain.flags.cc) +build.flags.cc += $(toolchain.flags.cc.${project.configuration}) +build.flags.cc += $(toolchain.${project.kind}.flags.cc) + +#--------------------------------------------------------------------------------------------------- +# +# Acquire C++ compiler flags. +# +#--------------------------------------------------------------------------------------------------- + +build.flags.cxx := $(project.flags.cxx) +build.flags.cxx += $(project.flags.cxx.${project.configuration}) +build.flags.cxx += $(toolchain.flags.cxx) +build.flags.cxx += $(toolchain.flags.cxx.${project.configuration}) +build.flags.cxx += $(toolchain.${project.kind}.flags.cxx) + +#--------------------------------------------------------------------------------------------------- +# +# Acquire Assembler flags. +# +#--------------------------------------------------------------------------------------------------- + +build.flags.as := $(project.flags.as) +build.flags.as += $(project.flags.as.${project.configuration}) +build.flags.as += $(toolchain.flags.as) +build.flags.as += $(toolchain.flags.as.${project.configuration}) +build.flags.as += $(toolchain.${project.kind}.flags.as) + +#--------------------------------------------------------------------------------------------------- +# +# Acquire resource compiler flags. +# +#--------------------------------------------------------------------------------------------------- + +build.flags.rc := $(project.flags.rc) +build.flags.rc += $(project.flags.rc.${project.configuration}) +build.flags.rc += $(toolchain.flags.rc) +build.flags.rc += $(toolchain.flags.rc.${project.configuration}) + +#--------------------------------------------------------------------------------------------------- +# +# Acquire link flags. +# +#--------------------------------------------------------------------------------------------------- + +build.flags.link := $(project.flags.link) +build.flags.link += $(project.flags.link.${project.configuration}) +build.flags.link += $(toolchain.flags.link) +build.flags.link += $(toolchain.flags.link.${project.configuration}) + +#--------------------------------------------------------------------------------------------------- +# +# Prepare include paths. +# +#--------------------------------------------------------------------------------------------------- + +build.includes := $(project.includes) +build.includes += $(toolchain.${project.kind}.includes) + +#--------------------------------------------------------------------------------------------------- +# +# Prepare compiler defines. +# +#--------------------------------------------------------------------------------------------------- + +build.defines := $(project.defines) +build.defines += $(toolchain.${project.kind}.defines) + +#--------------------------------------------------------------------------------------------------- +# +# Combine build path. +# +#--------------------------------------------------------------------------------------------------- + +build.path.target := $(global.path.build)/$(project.path) +build.path.object := obj/$(project.uuid) + +#--------------------------------------------------------------------------------------------------- +# +# Validate project type and choose type specific flags. +# +#--------------------------------------------------------------------------------------------------- +ifeq ($(project.type),executable) + +# +# Regular executable. +# + +build.filename := $(project.name).elf + +else ifeq ($(project.type),static) + +# +# Static library or kernel module. +# + +build.filename := lib$(project.name).a +build.flags.link += -static + +else ifeq ($(project.type),shared) + +# +# Shared library. +# + +build.filename := lib$(project.name).so +build.flags.link += -fPIC -shared +build.flags.cc += -fPIC +build.flags.as += -fPIC +build.flags.cxx += -fPIC +build.flags.rc += -fPIC + +else ifeq ($(project.type),module) + +# +# Loadable kernel module. +# + +build.filename := $(project.name).ko +build.flags.link += -r + +else + +$(error Unknown project type: $(project.type)) + +endif + +#--------------------------------------------------------------------------------------------------- +# +# This build system will use feature of compiler on which we specify directly which library we want +# to link instead of passing -l option. +# +# Process list of static link dependencies. +# +#--------------------------------------------------------------------------------------------------- + +build.libraries.static := $(foreach lib,$(project.libraries.static),$(dir $(global.path.build)/$(lib))lib$(notdir $(lib)).a) + +#--------------------------------------------------------------------------------------------------- +# +# Process list of shared link dependencies +# +#--------------------------------------------------------------------------------------------------- + +build.libraries.shared := $(foreach lib,$(project.libraries.shared),$(dir $(global.path.build)/$(lib))lib$(notdir $(lib)).so) + +build.libraries := $(addprefix -l,$(project.libraries)) + +#--------------------------------------------------------------------------------------------------- +# +# Prepare compiler list of include paths and defines. +# +#--------------------------------------------------------------------------------------------------- + +build.includes := $(addprefix -I,$(build.includes)) +build.defines := $(addprefix -D,$(build.defines)) + +#--------------------------------------------------------------------------------------------------- +# +# Clear list of objects. +# +#--------------------------------------------------------------------------------------------------- + +build.objects := + +#--------------------------------------------------------------------------------------------------- +# +# Convenient macro for making object file path from source path. +# +#--------------------------------------------------------------------------------------------------- + +build.make-object-path = $(strip $(subst ../,_/,$(build.path.object)/$(1).o)) + +#--------------------------------------------------------------------------------------------------- +# +# Description: +# +# Define rule for building .c files using toolchain C compiler. +# +# +# Parameters: +# +# $(1) - Provides a source file path. +# +# $(2) - Provides a target file path. +# +#--------------------------------------------------------------------------------------------------- +define rule.build.cc +build.objects += $(2) +$(2): $(1) + $(noecho)$(call make-dir,$(2)) + $(noecho)echo -e "CC: $(call echo.success,$(2))" + $(noecho)$(MAKEDEPEND) + $(noecho)$(toolchain.${project.kind}.cc) \ + -c $(1) \ + -o $(2) \ + $(build.flags.cc) \ + $(build.defines) \ + $(build.includes) \ + -MMD \ + -MP \ + -MT $(2) \ + -MF $(2:%o=%d) +endef + +#--------------------------------------------------------------------------------------------------- +# +# Description: +# +# Define rule for assembling .S files using toolchain assembler. +# +# +# Parameters: +# +# $(1) - Provides a source file path. +# +# $(2) - Provides a target file path. +# +#--------------------------------------------------------------------------------------------------- + +define rule.build.as +build.objects += $(2) +$(2): $(1) + $(noecho)$(call make-dir,$(2)) + $(noecho)echo -e "AS: $(call echo.success,$(2))" + $(noecho)$(MAKEDEPEND) + $(noecho)$(toolchain.${project.kind}.as) \ + -c $(1) \ + -o $(2) \ + $(build.flags.as) \ + $(build.defines) \ + $(build.includes) \ + -MMD \ + -MP \ + -MT $(2) \ + -MF $(2:%o=%d) +endef + +#--------------------------------------------------------------------------------------------------- +# +# Description: +# +# Define rule for assembling .S files using toolchain assembler. +# +# +# Parameters: +# +# $(1) - Provides a source file path. +# +# $(2) - Provides a target file path. +# +#--------------------------------------------------------------------------------------------------- + +define rule.build.asm +build.objects += $(2) +$(2): $(1) + $(noecho)$(call make-dir,$(2)) + $(noecho)echo -e "AS: $(call echo.success,$(2))" + $(noecho)$(MAKEDEPEND) + nasm \ + $(1) \ + -o $(2) \ + -f bin +endef + +#--------------------------------------------------------------------------------------------------- +# +# Description: +# +# Define rule for compiling .cxx files using C++ compiler. +# +# +# Parameters: +# +# $(1) - Provides a source file path. +# +# $(2) - Provides a target file path. +# +#--------------------------------------------------------------------------------------------------- + +define rule.build.cxx +build.objects += $(2) +$(2): $(1) + $(noecho)$(call make-dir,$(2)) + $(noecho)echo -e "CXX: $(call echo.success,$(2))" + $(noecho)$(MAKEDEPEND) + $(noecho)$(toolchain.${project.kind}.cxx) \ + -c $(1) \ + -o $(2) \ + $(build.flags.cxx) \ + $(build.defines) \ + $(build.includes) \ + -MMD \ + -MP \ + -MT $(2) \ + -MF $(2:%o=%d) +endef + +#--------------------------------------------------------------------------------------------------- +# +# TODO: Define rule for compiling .rc files. +# +#--------------------------------------------------------------------------------------------------- + + +#--------------------------------------------------------------------------------------------------- +# +# Filter source files by type. +# +#--------------------------------------------------------------------------------------------------- + +build.sources.cc := $(filter %.c,$(project.sources)) +build.sources.as := $(filter %.S,$(project.sources)) +build.sources.asm := $(filter %.asm,$(project.sources)) +build.sources.cxx := $(filter %.cxx,$(project.sources)) +build.sources.rc := $(filter %.rc,$(project.sources)) + +#--------------------------------------------------------------------------------------------------- +# +# Apply build rules. +# +#--------------------------------------------------------------------------------------------------- + +$(foreach src,$(build.sources.cc),$(eval $(call rule.build.cc,$(src),$(call build.make-object-path,$(src))))) +$(foreach src,$(build.sources.as),$(eval $(call rule.build.as,$(src),$(call build.make-object-path,$(src))))) +$(foreach src,$(build.sources.asm),$(eval $(call rule.build.asm,$(src),$(call build.make-object-path,$(src))))) +$(foreach src,$(build.sources.cxx),$(eval $(call rule.build.cxx,$(src),$(call build.make-object-path,$(src))))) + +#--------------------------------------------------------------------------------------------------- +# +# Combine build target. +# +#--------------------------------------------------------------------------------------------------- + +build.target := $(build.path.target)/$(build.filename) +build.target.hash := $(build.target).hash +build.target.sym := $(build.target).sym +build.target.rde := $(build.target).rde +build.target.lst := $(build.target).lst +build.target.dbg := $(build.target).dbg + +#--------------------------------------------------------------------------------------------------- +# +# Define main target. +# +#--------------------------------------------------------------------------------------------------- + +# +# Include dependencies for this project. +# +build.dependencies = $(build.objects:.o=.d) +-include $(build.dependencies) + + +# +# Use proper linker to build project. +# +ifeq ($(project.type),static) + +$(build.target): $(build.objects) + $(noecho)$(call make-dir,$(@)) + $(noecho)echo -e "LINK: $(call echo.success,$(@))" + $(noecho)$(toolchain.${project.kind}.ar) rcs $(@) $(^) + +else + +$(build.target): $(build.objects) + $(noecho)$(call make-dir,$(@)) + $(noecho)echo -e "LINK: $(call echo.success,$(@))" + $(noecho)$(toolchain.${project.kind}.link) $(^) -o $(@) $(build.libraries.static) $(build.libraries.shared) $(build.flags.link) $(build.libraries) + $(noecho)$(toolchain.${project.kind}.objcopy) --only-keep-debug $(@) $(@).dbg + $(noecho)$(toolchain.${project.kind}.objcopy) --strip-debug $(@) + $(noecho)$(toolchain.${project.kind}.objcopy) --add-gnu-debuglink=$(@).dbg $(@) + +endif + +#--------------------------------------------------------------------------------------------------- +# +# Define list of optional metadata targets. +# +#--------------------------------------------------------------------------------------------------- + +build.metadata-targets := + +ifeq ($(project.emit-metadata),true) + +build.metadata-targets += $(build.target.hash) +build.metadata-targets += $(build.target.sym) +build.metadata-targets += $(build.target.rde) +build.metadata-targets += $(build.target.lst) + +endif + +#--------------------------------------------------------------------------------------------------- +# +# Define other optional metadata targets builders. +# +#--------------------------------------------------------------------------------------------------- + +$(build.target.hash): $(build.target) + $(noecho)echo -e "SHA512: $(call echo.success,$(@))" + $(noecho)$(host.sha512sum) $(<) > $(@) + +$(build.target.sym): $(build.target) + $(noecho)echo -e "Symbols: $(call echo.success,$(@))" + $(noecho)$(toolchain.${project.kind}.nm) -C $(<) | sort > $(@) + +$(build.target.rde): $(build.target) + $(noecho)echo -e "Fileinfo: $(call echo.success,$(@))" + $(noecho)$(toolchain.${project.kind}.readelf) -aW $(<) > $(@) + +$(build.target.lst): $(build.target) + $(noecho)echo -e "Listing: $(call echo.success,$(@))" + $(noecho)$(toolchain.${project.kind}.objdump) --insn-width=14 -d $(<) > $(@) + +#--------------------------------------------------------------------------------------------------- +# +# Cleaning rule definition. +# +#--------------------------------------------------------------------------------------------------- + +clean: + $(noecho)echo -e "Removing: $(call echo.success,$(CURDIR)/obj)" + $(noecho)$(host.rmdir) ./obj + $(noecho)echo -e "Removing: $(call echo.success,$(build.target))" + $(noecho)$(host.rm) $(build.target) + $(noecho)echo -e "Removing: $(call echo.success,$(build.target.dbg))" + $(noecho)$(host.rm) $(build.target.dbg) + $(noecho)$(host.rm) $(build.metadata-targets) + +#--------------------------------------------------------------------------------------------------- +# +# Project configure rule definition. +# +#--------------------------------------------------------------------------------------------------- + +configure: + +#--------------------------------------------------------------------------------------------------- +# +# Build rule definition. +# +#--------------------------------------------------------------------------------------------------- + +build: $(build.target) $(build.metadata-targets) diff --git a/042-osdev-08/make/macros.mk b/042-osdev-08/make/macros.mk new file mode 100644 index 0000000..568e626 --- /dev/null +++ b/042-osdev-08/make/macros.mk @@ -0,0 +1,105 @@ +#--------------------------------------------------------------------------------------------------- +# +# By Karol Grzybowski, 2017 +# +#--------------------------------------------------------------------------------------------------- + +#--------------------------------------------------------------------------------------------------- +# +# Base paths. +# +#--------------------------------------------------------------------------------------------------- + +global.path.base = $(BASE_DIRECTORY) +global.path.make = $(global.path.base)/make +global.path.build = $(global.path.base)/build + +#--------------------------------------------------------------------------------------------------- +# +# Common defintions. +# +#--------------------------------------------------------------------------------------------------- + +empty := +space := $(empty) $(empty) +comma := , +colon := : + +#--------------------------------------------------------------------------------------------------- +# +# Host specific tools. +# +#--------------------------------------------------------------------------------------------------- + +host.path = $(1) +host.rm = rm -f $(1) +host.rmdir = rm -rf $(1) +host.mkdir = mkdir -p $(1) +host.ln = ln -s $(1) $(2) +host.cp = cp -f $(1) $(2) +host.mv = mv -f $(1) $(2) +host.install = cp -f $(1) $(2) +host.echo = echo -e +host.sha512sum = sha512sum + +#--------------------------------------------------------------------------------------------------- +# +# Makefile base tools. +# +#--------------------------------------------------------------------------------------------------- +parent-dir = $(patsubst %/,%,$(dir $(1:%/=%))) +make-dir = if [ ! -d $(1) ]; then mkdir -p $(dir $(1)); fi +link-dir = if [ ! -d $(1) ]; then ln $(1) $(2); fi +current-dir = $(call parent-dir,$(lastword $(MAKEFILE_LIST))) +current-makefile = $(lastword $(MAKEFILE_LIST)) + +#--------------------------------------------------------------------------------------------------- +# +# Host and build system information. +# +#--------------------------------------------------------------------------------------------------- + +host.get-username = $(shell whoami) +host.get-hostname = $(shell hostname) +host.timestamp = $(shell /bin/date "+%Y-%m-%dT%H:%M:%S") + +#--------------------------------------------------------------------------------------------------- +# +# DVCS commands for getting repository metadata. +# +#--------------------------------------------------------------------------------------------------- + +dvcs.command = $(shell which git) +dvcs.revision = $(shell $(dvcs.command) log -1 --format=%H) +dvcs.branch = $(shell $(dvcs.command) rev-parse --abbrev-ref HEAD) + +#--------------------------------------------------------------------------------------------------- +# +# Toggles command verbosity on demand. +# +#--------------------------------------------------------------------------------------------------- +ifeq ($(VERBOSE),true) +noecho = +else +noecho = @ +endif +export noecho + +#--------------------------------------------------------------------------------------------------- +# +# Base ASCII commands for chaning terminal colors. +# +#--------------------------------------------------------------------------------------------------- + +colors.success = \033[32;01m +colors.failure = \033[31;01m +colors.restore = \033[0m + +#--------------------------------------------------------------------------------------------------- +# +# Wrappers for colors. +# +#--------------------------------------------------------------------------------------------------- + +echo.success = $(colors.success)$(1)$(colors.restore) +echo.failure = $(colors.failure)$(1)$(colors.restore) diff --git a/042-osdev-08/make/recurse.mk b/042-osdev-08/make/recurse.mk new file mode 100644 index 0000000..438aa1c --- /dev/null +++ b/042-osdev-08/make/recurse.mk @@ -0,0 +1,43 @@ +#--------------------------------------------------------------------------------------------------- +# +# By Karol Grzybowski, 2017 +# +#--------------------------------------------------------------------------------------------------- + +ifneq ($(directories),) + +# +# Recurse over specified list of subdirectories. +# + +.PHONY: $(directories) recurse + +$(MAKECMDGOALS) recurse: $(directories) + +# +# Specify target for directories. +# +$(directories): + $(noecho)exec $(MAKE) --no-print-directory --directory=$(@) --makefile=dirs.mk $(MAKECMDGOALS) + +endif + +#--------------------------------------------------------------------------------------------------- + +ifneq ($(projects),) + +# +# Recurse over specified list of directories containing project.mk files. +# + +.PHONY: $(projects) recurse + +$(MAKECMDGOALS) recurse: $(projects) + +# +# Specify target for project.mk files. +# +$(projects): + $(noecho)exec $(MAKE) --no-print-directory --directory=$(@) --makefile=project.mk $(MAKECMDGOALS) --jobs $(shell nproc) + +endif \ No newline at end of file diff --git a/042-osdev-08/make/toolchain.mk b/042-osdev-08/make/toolchain.mk new file mode 100644 index 0000000..e39d549 --- /dev/null +++ b/042-osdev-08/make/toolchain.mk @@ -0,0 +1,195 @@ +#--------------------------------------------------------------------------------------------------- +# +# By Karol Grzybowski, 2017 +# +#--------------------------------------------------------------------------------------------------- + +#--------------------------------------------------------------------------------------------------- +# +# Toolchain cross-compiler path. +# +#--------------------------------------------------------------------------------------------------- + +toolchain.target.path := $(BASE_DIRECTORY)/build + + +#--------------------------------------------------------------------------------------------------- +# +# Native toolchain. +# +#--------------------------------------------------------------------------------------------------- + +toolchain.native.ar := ar +toolchain.native.as := gcc +toolchain.native.cc := gcc +toolchain.native.cxx := g++ +toolchain.native.link := g++ +toolchain.native.nm := nm +toolchain.native.objcopy := objcopy +toolchain.native.objdump := objdump +toolchain.native.ranlib := ranlib +toolchain.native.readelf := readelf +toolchain.native.strings := strings +toolchain.native.strip := strip + +toolchain.native.cflags := +toolchain.native.cxxflags := +toolchain.native.defines := + + +#--------------------------------------------------------------------------------------------------- +# +# Select proper target toolchain. +# +#--------------------------------------------------------------------------------------------------- + +#--------------------------------------------------------------------------------------------------- +# +# Crosscompile x86_64 +# +#--------------------------------------------------------------------------------------------------- + +toolchain.target.prefix := +toolchain.target.flags.as := -Wa,--divide +toolchain.target.flags.cc := -m64 -mtune=corei7 +toolchain.target.flags.cxx := -m64 -mtune=corei7 +toolchain.target.defines := + +#--------------------------------------------------------------------------------------------------- +# +# Apply target toolchain. +# +#--------------------------------------------------------------------------------------------------- + +toolchain.target.ar := $(toolchain.target.prefix)ar +toolchain.target.as := $(toolchain.target.prefix)gcc +toolchain.target.cc := $(toolchain.target.prefix)gcc +toolchain.target.cxx := $(toolchain.target.prefix)g++ +toolchain.target.link := $(toolchain.target.prefix)g++ +toolchain.target.nm := $(toolchain.target.prefix)nm +toolchain.target.objcopy := $(toolchain.target.prefix)objcopy +toolchain.target.objdump := $(toolchain.target.prefix)objdump +toolchain.target.ranlib := $(toolchain.target.prefix)ranlib +toolchain.target.readelf := $(toolchain.target.prefix)readelf +toolchain.target.strings := $(toolchain.target.prefix)strings +toolchain.target.strip := $(toolchain.target.prefix)strip + +#--------------------------------------------------------------------------------------------------- +# +# Configuration specific flags. +# +#--------------------------------------------------------------------------------------------------- + +toolchain.flags.cc.debug := -D_DEBUG -O0 -ggdb +toolchain.flags.cc.checked := -D_DEBUG -O3 +toolchain.flags.cc.release := -DNDEBUG -O3 + +toolchain.flags.cxx.debug := -D_DEBUG -O0 -ggdb +toolchain.flags.cxx.checked := -D_DEBUG -O3 +toolchain.flags.cxx.release := -DNDEBUG -O3 + +toolchain.flags.as.debug := +toolchain.flags.as.checked := +toolchain.flags.as.release := + +toolchain.flags.link.debug := +toolchain.flags.link.checked := +toolchain.flags.link.release := + +#--------------------------------------------------------------------------------------------------- +# +# Global toolchain flags. +# +#--------------------------------------------------------------------------------------------------- + +toolchain.flags.cc := \ + -std=c11 \ + -Wall \ + -Wextra \ + -Werror=implicit-function-declaration \ + -Wdouble-promotion \ + -Wbad-function-cast \ + -Wundef \ + -Wconversion \ + -Wwrite-strings \ + -Wno-conversion \ + -fstrict-aliasing \ + -Wstrict-aliasing=1 \ + -Werror=strict-aliasing \ + -Werror=address \ + -Werror \ + -Wmissing-format-attribute \ + -fdiagnostics-color \ + -fmax-errors=20 \ + -Wvla \ + -flto-odr-type-merging \ + -Wparentheses \ + -Wmissing-braces \ + -Wsequence-point \ + -Wlogical-op \ + -Wmissing-field-initializers \ + -Wundef \ + -Wfloat-equal \ + -Wshadow \ + -Wswitch \ + -Wunused \ + -Wuninitialized \ + -Wstrict-overflow=2 \ + -Wpointer-arith \ + -Wcast-align -Wformat=2 \ + -Winit-self \ + -Wunreachable-code \ + -fstack-protector-strong \ + -fvisibility=hidden \ + -Wno-format-zero-length + +# +# -Wno-implicit-fallthrough \ +# -Wno-bool-operation \ + +toolchain.flags.cxx := \ + -std=c++14 \ + -fmax-errors=20 \ + -fdiagnostics-color \ + -Wall \ + -Wextra \ + -Werror \ + -Werror=strict-aliasing \ + -Werror=address \ + -Werror=implicit-function-declaration \ + -Wdouble-promotion \ + -Wundef \ + -Wconversion \ + -Wwrite-strings \ + -Wstrict-aliasing=2 \ + -Wmissing-format-attribute \ + -Wfloat-equal \ + -Wshadow \ + -Wvla \ + -Wdisabled-optimization \ + -Wparentheses \ + -Wmissing-braces \ + -Wsequence-point \ + -Wswitch \ + -Wunused \ + -Wuninitialized \ + -Wstrict-overflow=2 \ + -Wpointer-arith \ + -Wlogical-op \ + -Wmissing-field-initializers \ + -Wcast-align \ + -Wcast-qual \ + -Wformat=2 \ + -Winit-self \ + -Winline \ + -Wunreachable-code \ + -flto-odr-type-merging \ + -fstack-protector-strong \ + -fvisibility=hidden \ + -Wno-format-zero-length + +#--------------------------------------------------------------------------------------------------- +# +# Predefined system includes +# +#--------------------------------------------------------------------------------------------------- diff --git a/042-osdev-08/makefile b/042-osdev-08/makefile new file mode 100644 index 0000000..afdecc7 --- /dev/null +++ b/042-osdev-08/makefile @@ -0,0 +1,15 @@ +BASE_DIRECTORY := $(shell pwd) + +export BASE_DIRECTORY + +include $(BASE_DIRECTORY)/make/macros.mk + +directories := source + +include $(BASE_DIRECTORY)/make/recurse.mk + +clean: + $(noecho)exec $(MAKE) --no-print-directory --directory=build $(MAKECMDGOALS) + +build: + $(noecho)exec $(MAKE) --no-print-directory --directory=build $(MAKECMDGOALS) \ No newline at end of file diff --git a/042-osdev-08/source/bootloader/project.mk b/042-osdev-08/source/bootloader/project.mk new file mode 100644 index 0000000..f5a632a --- /dev/null +++ b/042-osdev-08/source/bootloader/project.mk @@ -0,0 +1,20 @@ +include $(BASE_DIRECTORY)/make/macros.mk + +build.path.stage1 = $(global.path.build)/bootloader/stage1 +build.path.stage2 = $(global.path.build)/bootloader/stage2 + +$(build.path.stage1): source/stage1.asm + $(noecho)$(call make-dir,$(@)) + nasm $(<) -o $(@) + +$(build.path.stage2): source/stage2.asm + $(noecho)$(call make-dir,$(@)) + nasm $(<) -o $(@) + +clean: + $(host.rm) $(build.path.stage1) + $(host.rm) $(build.path.stage2) + + +build: $(build.path.stage1) $(build.path.stage2) + diff --git a/042-osdev-08/stage1.asm b/042-osdev-08/source/bootloader/source/stage1.asm similarity index 100% rename from 042-osdev-08/stage1.asm rename to 042-osdev-08/source/bootloader/source/stage1.asm diff --git a/042-osdev-08/stage2.asm b/042-osdev-08/source/bootloader/source/stage2.asm similarity index 100% rename from 042-osdev-08/stage2.asm rename to 042-osdev-08/source/bootloader/source/stage2.asm diff --git a/042-osdev-08/source/dirs.mk b/042-osdev-08/source/dirs.mk new file mode 100644 index 0000000..535d7c5 --- /dev/null +++ b/042-osdev-08/source/dirs.mk @@ -0,0 +1,2 @@ +projects := bootloader kernel +include $(BASE_DIRECTORY)/make/recurse.mk \ No newline at end of file diff --git a/042-osdev-08/source/kernel/include/common.h b/042-osdev-08/source/kernel/include/common.h new file mode 100644 index 0000000..7fdb99d --- /dev/null +++ b/042-osdev-08/source/kernel/include/common.h @@ -0,0 +1,9 @@ +#pragma once +#define UNUSED(a) (void)(a) + +typedef unsigned long long size_t; +typedef signed long long ptrdiff_t; + +#if !defined(NULL) +#define NULL ((void*)0) +#endif \ No newline at end of file diff --git a/042-osdev-08/crt.h b/042-osdev-08/source/kernel/include/crt.h similarity index 100% rename from 042-osdev-08/crt.h rename to 042-osdev-08/source/kernel/include/crt.h diff --git a/042-osdev-08/hal.h b/042-osdev-08/source/kernel/include/hal.h similarity index 85% rename from 042-osdev-08/hal.h rename to 042-osdev-08/source/kernel/include/hal.h index 9a1ee70..7249dc8 100644 --- a/042-osdev-08/hal.h +++ b/042-osdev-08/source/kernel/include/hal.h @@ -2,4 +2,4 @@ void HAL_PortOutByte(int port, unsigned char v); void HAL_PortOutWord(int port, unsigned short v); void HAL_PortOutDword(int port, unsigned int v); - +void HAL_PauseKernel(); \ No newline at end of file diff --git a/042-osdev-08/idt.h b/042-osdev-08/source/kernel/include/idt.h similarity index 100% rename from 042-osdev-08/idt.h rename to 042-osdev-08/source/kernel/include/idt.h diff --git a/042-osdev-08/source/kernel/include/int_handlers.h b/042-osdev-08/source/kernel/include/int_handlers.h new file mode 100644 index 0000000..d3620b0 --- /dev/null +++ b/042-osdev-08/source/kernel/include/int_handlers.h @@ -0,0 +1,35 @@ +#pragma once + +// Thanks to Karol Grzybowski +typedef struct TrapFrame { + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rbp; + uint64_t rdi; + uint64_t rsi; + uint64_t rdx; + uint64_t rcx; + uint64_t rbx; + uint64_t rax; + uint64_t rsp; + + /*uint64_t trap_number; + uint64_t error_code;*/ + + uint64_t rip; + uint64_t segment_cs; + /*uint64_t rflags; + uint64_t rsp; + uint64_t segment_ss;*/ + +} TrapFrame; + +void Int_DE(TrapFrame *frame); + +void GuruPanicOfDeath(const char *reason, TrapFrame *frame); \ No newline at end of file diff --git a/042-osdev-08/terminal.h b/042-osdev-08/source/kernel/include/terminal.h similarity index 100% rename from 042-osdev-08/terminal.h rename to 042-osdev-08/source/kernel/include/terminal.h diff --git a/042-osdev-08/terminal_backend_b8000.h b/042-osdev-08/source/kernel/include/terminal_backend_b8000.h similarity index 100% rename from 042-osdev-08/terminal_backend_b8000.h rename to 042-osdev-08/source/kernel/include/terminal_backend_b8000.h diff --git a/042-osdev-08/source/kernel/project.mk b/042-osdev-08/source/kernel/project.mk new file mode 100644 index 0000000..b5881bf --- /dev/null +++ b/042-osdev-08/source/kernel/project.mk @@ -0,0 +1,34 @@ + +project.name = kernel64 +project.type = executable +project.kind = target +project.path = kernel +project.component.major = boot +project.component.minor = kernel +project.emit-metadata = true +project.configuration = debug + +project.sources = \ + $(wildcard source/*.S) \ + $(wildcard source/*.c) + +project.flags.cc = -ffreestanding -nostdlib -nostartfiles -masm=intel +project.flags.as = -ffreestanding -nostdlib -nostartfiles -masm=intel +project.flags.cxx = -ffreestanding -nostdlib -nostartfiles -masm=intel + +project.flags.link = \ + -ffreestanding \ + -nostdlib \ + -Wl,-z,max-page-size=0x1000 \ + -Wl,-z,common-page-size=0x1000 + +project.flags.link.x86_64 = -mno-red-zone -mcmodel=kernel +project.flags.cc.x86_64 = -mno-red-zone -mcmodel=kernel +project.flags.cxx.x86_64 = -mno-red-zone -mcmodel=kernel + +project.libraries = gcc + +project.includes = \ + include + +include $(BASE_DIRECTORY)/make/build.mk diff --git a/042-osdev-08/crt.c b/042-osdev-08/source/kernel/source/crt.c similarity index 100% rename from 042-osdev-08/crt.c rename to 042-osdev-08/source/kernel/source/crt.c diff --git a/042-osdev-08/source/kernel/source/hal.c b/042-osdev-08/source/kernel/source/hal.c new file mode 100644 index 0000000..cc9d6e8 --- /dev/null +++ b/042-osdev-08/source/kernel/source/hal.c @@ -0,0 +1,22 @@ +#include "hal.h" + +void HAL_PortOutByte(int port, unsigned char v) { + __asm__("out dx, al\n" : : "a" (v), "d" (port)); +} + +void HAL_PortOutWord(int port, unsigned short v) { + __asm__("out dx, ax\n" : : "a" (v), "d" (port)); +} + +void HAL_PortOutDword(int port, unsigned int v) { + __asm__("out dx, eax\n" : : "a" (v), "d" (port)); +} + +void HAL_PauseKernel() { + // Disable interrupts, park CPU and wait for interrupt. Illogical, but doesn't burn VMs ;) + __asm__ __volatile__( + "cli\n" + "pause\n" + "hlt\n" + ); +} \ No newline at end of file diff --git a/042-osdev-08/idt.c b/042-osdev-08/source/kernel/source/idt.c similarity index 100% rename from 042-osdev-08/idt.c rename to 042-osdev-08/source/kernel/source/idt.c diff --git a/042-osdev-08/source/kernel/source/int_handlers.c b/042-osdev-08/source/kernel/source/int_handlers.c new file mode 100644 index 0000000..d159d63 --- /dev/null +++ b/042-osdev-08/source/kernel/source/int_handlers.c @@ -0,0 +1,36 @@ +#include "common.h" +#include "terminal.h" +#include "terminal_backend_b8000.h" +#include + +void GuruPanicOfDeath(const char *reason, TrapFrame *frame) { + TerminalBackend *con = TerminalBackendB8000(); + T_ClearScreen(con); + T_PutText(con, "Guru Panic Of Death!!!\n\n"); + T_Printf(con, "Reason: %s\n\n", reason); + + if (frame != NULL) { + T_PutText(con, "State:\n\n"); + + T_Printf(con, " RAX: %016llx\tR8: %016llx\n", frame->rax, frame->r8); + T_Printf(con, " RBX: %016llx\tR9: %016llx\n", frame->rbx, frame->r9); + T_Printf(con, " RCX: %016llx\tR10: %016llx\n", frame->rcx, frame->r10); + T_Printf(con, " RDX: %016llx\tR11: %016llx\n", frame->rdx, frame->r11); + T_Printf(con, " RSI: %016llx\tR12: %016llx\n", frame->rsi, frame->r12); + T_Printf(con, " RDI: %016llx\tR13: %016llx\n", frame->rdi, frame->r13); + T_Printf(con, " RBP: %016llx\tR14: %016llx\n", frame->rbp, frame->r14); + T_Printf(con, " RSP: %016llx\tR15: %016llx\n", frame->rsp, frame->r15); + + T_Printf(con, " CS:RIP: %04x:%016llx\n\n", frame->segment_cs, frame->rip); + } + + T_PutText(con, "System halt."); + + for (;;); +} + + +void Int_DE(TrapFrame *frame) { + GuruPanicOfDeath("DIVISION_ERROR", frame); +} + diff --git a/042-osdev-08/int_wrappers.s b/042-osdev-08/source/kernel/source/int_wrappers.S similarity index 100% rename from 042-osdev-08/int_wrappers.s rename to 042-osdev-08/source/kernel/source/int_wrappers.S diff --git a/042-osdev-08/kernel.c b/042-osdev-08/source/kernel/source/kernel.c similarity index 100% rename from 042-osdev-08/kernel.c rename to 042-osdev-08/source/kernel/source/kernel.c diff --git a/042-osdev-08/source/kernel/source/rtl.c b/042-osdev-08/source/kernel/source/rtl.c new file mode 100644 index 0000000..7e413f6 --- /dev/null +++ b/042-osdev-08/source/kernel/source/rtl.c @@ -0,0 +1,1069 @@ +#include "common.h" +#include +#include +#include +#include + +const char rtl_string_digits_lowercase[] = "0123456789abcdefghijklmnopqrstuvwxyz"; +const char rtl_string_digits_uppercase[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +#define RTL_MIN(_X, _Y) (((_X) > (_Y)) ? (_Y) : (_X)) +#define RTL_MAX(_X, _Y) (((_X) > (_Y)) ? (_X) : (_Y)) +#define RTL_MAKE_FLAG(_Index) (1U << (_Index)) +#define RTL_FLAGS_SET(_Value, _Mask) ((_Value) | (_Mask)) +#define RTL_FLAGS_REF_SET(_Reference, _Mask) (((_Reference) |= (_Mask))) +#define RTL_FLAGS_UNSET(_Value, _Mask) ((_Value) & (~(_Mask))) +#define RTL_FLAGS_REF_UNSET(_Reference, _Mask) (((_Reference) &= ~(_Mask))) +#define RTL_FLAGS_HAS(_Value, _Mask) (((_Value) & (_Mask)) == (_Mask)) +#define RTL_FLAGS_ANY(_Value, _Mask) (((_Value) & (_Mask)) != 0) +#define RTL_FLAGS_NONE(_Value, _Mask) (((_Value) & (_Mask)) == 0) + + +#define FORMAT_FLAGS_NONE (0) +#define FORMAT_FLAGS_MINUS (1 << 0) +#define FORMAT_FLAGS_PLUS (1 << 1) +#define FORMAT_FLAGS_ALT (1 << 2) +#define FORMAT_FLAGS_SPACE (1 << 3) +#define FORMAT_FLAGS_ZERO (1 << 4) +#define FORMAT_FLAGS_DONE (1 << 5) +#define FORMAT_FLAGS_LOWERCASE (1 << 6) +#define FORMAT_FLAGS_WIDE (1 << 7) + +// +// Fundamental C integer types. +// + +#define FORMAT_TYPE_INT (0) +#define FORMAT_TYPE_CHAR (1) +#define FORMAT_TYPE_SHORT (2) +#define FORMAT_TYPE_LONG (3) +#define FORMAT_TYPE_LONGLONG (4) + +#define FORMAT_TYPE_LONGDOUBLE (5) + +#define FORMAT_TYPE_UNSIGNED (1U << 7) + +#define FORMAT_TYPE_NONE FORMAT_TYPE_INT + +#if defined(__x86_64__) + +#define FORMAT_TYPE_INTMAX FORMAT_TYPE_LONG +#define FORMAT_TYPE_PTRDIFF FORMAT_TYPE_LONG +#define FORMAT_TYPE_SIZE FORMAT_TYPE_LONG | FORMAT_TYPE_UNSIGNED +#define FORMAT_TYPE_UINTPTR FORMAT_TYPE_LONG | FORMAT_TYPE_UNSIGNED + +#elif defined(__aarch64__) + +#define FORMAT_TYPE_INTMAX FORMAT_TYPE_LONG +#define FORMAT_TYPE_PTRDIFF FORMAT_TYPE_LONG +#define FORMAT_TYPE_SIZE FORMAT_TYPE_LONG | FORMAT_TYPE_UNSIGNED +#define FORMAT_TYPE_UINTPTR FORMAT_TYPE_LONG | FORMAT_TYPE_UNSIGNED + +#else + +#error "Unknown architecture." + +#endif + +// +// Format state. +// +struct format_state { + // + // Integral number base. + // + uint32_t format_base; + + // + // Format flags. + // + uint32_t format_flags; + + // + // Format specifier type. + // + uint32_t format_type; + + // + // Format specifier width. + // + int32_t format_width; + + // + // Format specifier precision. + // + int32_t format_precision; + + // + // Buffer. + // + char* buffer; + + // + // Buffer capacity. + // + size_t buffer_capacity; + + // + // Number of total characters processed. + // + size_t processed; + + // + // Number of characters processed by current handler. + // + size_t current; + + // + // arglist iterator. + // + va_list arglist; +}; + +// Disable call to stdlib function (don't remember which one :D) +__attribute__((__optimize__("-fno-tree-loop-distribute-patterns"))) +int +rtl_string_to_int32( + int32_t* result, + const char* string, + char** end_string, + int base +) +{ + if (result == NULL || string == NULL || end_string == NULL) + { + return -1; + } + + // + // Check integer base range. + // + if (base < 0 || base == 1 || base > 36) + { + (*end_string) = (char*)string; + (*result) = 0; + return -1; + } + + const char* it = string; + int character; + + // + // Skip whitespaces. + // + do + { + character = (int)(unsigned char)(*it++); + } while (character == ' '); + + // + // Check potential sign of value. + // + int is_negative; + if (character == '-') + { + is_negative = 1; + character = (int)(unsigned char)(*it++); + } + else + { + is_negative = 0; + if (character == '+') + { + character = (int)(unsigned char)(*it++); + } + } + + // + // Check string prefix. + // + if ((base == 0 || base == 16) && (character == '0' && (*it == 'x' || *it == 'X'))) + { + // + // This is hex string. + // + character = (int)(unsigned char)it[1]; + it += 2; + base = 16; + } + else if ((base == 0 || base == 2) && (character == '0' && (*it == 'b' || *it == 'B'))) + { + // + // Binary string. + // + character = (int)(unsigned char)it[1]; + it += 2; + base = 2; + } + + // + // Default to decimal or octal strings. + // + if (base == 0) + { + base = (character == '0') ? 8 : 10; + } + + // + // Compute string cutoff bounds. + // + int32_t cutoff = (is_negative ? INT32_MIN : INT32_MAX); + int32_t cutlim = cutoff % base; + cutoff /= base; + + // + // Adjust limits for negative ranges. + // + if (is_negative) + { + if (cutlim > 0) + { + cutlim -= base; + cutoff += 1; + } + cutlim = -cutlim; + } + + int32_t accumulator = 0; + int direction = 0; + + int status = 0; + + // + // Parse string. + // + for (;; character = (int)(unsigned char)(*it++)) + { + if ('0' <= character && character <= '9') + { + character -= '0'; + } + else if ('a' <= character && character <= 'z') + { + character -= 'a' - 10; + } + else if ('A' <= character && character <= 'Z') + { + character -= 'A' - 10; + } + else + { + // + // Invalid string range. + // + break; + } + + if (character >= base) + { + // + // Disallow digits larger than base. + // + break; + } + + if (direction < 0) + { + // + // Skip parsing until end of invalid / out of range number. + // + continue; + } + + if (is_negative) + { + if (accumulator < cutoff || (accumulator == cutoff && character > cutlim)) + { + // + // Value out of valid range. + // + direction = -1; + accumulator = INT32_MIN; + status = -1; + } + else + { + // + // Update accumulator. + // + direction = 1; + accumulator *= base; + accumulator -= character; + } + } + else + { + if (accumulator > cutoff || (accumulator == cutoff && character > cutlim)) + { + // + // Value ot of valid range. + // + direction = -1; + accumulator = INT32_MAX; + status = -1; + } + else + { + // + // Update accumulator. + // + direction = 1; + accumulator *= base; + accumulator += character; + } + } + } + + // + // Set result arguments. + // + (*end_string) = (char*)(direction ? (it - 1) : string); + (*result) = accumulator; + + return status; +} + +// +// Emits single character to format buffer. +// +static inline +void +rtlp_format_emit_char( + struct format_state* state, + int character, + size_t count +) +{ + size_t processed = 0; + + for (size_t i = 0; i < count; ++i) + { + if (state->processed < state->buffer_capacity) + { + ++processed; + state->buffer[state->processed] = (char)character; + } + + ++(state->processed); + } + + state->current += processed; +} + +static inline +void +rtlp_format_emit_string_n( + struct format_state* state, + const char* string, + size_t length +) +{ + size_t processed = 0; + + for (size_t i = 0; i < length; ++i) + { + if (state->processed < state->buffer_capacity) + { + ++processed; + state->buffer[state->processed] = string[i]; + } + + ++(state->processed); + } + + state->current += processed; +} + +static inline +void +format_emit_string( + struct format_state* state, + const char* string +) +{ + size_t processed = 0; + + for (; *string != '\0'; ++string) + { + if (state->processed < state->buffer_capacity) + { + ++processed; + state->buffer[state->processed] = *string; + } + + ++(state->processed); + } + + state->current += processed; +} + +static inline +void +rtlp_format_write_integer( + struct format_state* state, + uintmax_t value +) +{ + char sign = '\0'; + + if (!RTL_FLAGS_HAS(state->format_type, FORMAT_TYPE_UNSIGNED)) + { + const intmax_t svalue = (intmax_t)value; + const bool is_negative = svalue < 0; + + value = (is_negative ? ((uintmax_t)-svalue) : ((uintmax_t)svalue)); + + if (is_negative) + { + sign = '-'; + } + else if (RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_PLUS)) + { + sign = '+'; + } + else if (RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_SPACE)) + { + sign = ' '; + } + } + + enum { MAX_INTEGER_LENGTH = 96 }; + + char output_buffer[MAX_INTEGER_LENGTH]; + char* output_buffer_end = output_buffer + MAX_INTEGER_LENGTH; + + ptrdiff_t written = 0; + + const char* digits = RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_LOWERCASE) + ? rtl_string_digits_lowercase + : rtl_string_digits_uppercase; + + uintmax_t remaining = value; + + if ((state->format_precision != 0) || (remaining != 0)) + { + do + { + uintmax_t digit = remaining % state->format_base; + remaining /= state->format_base; + output_buffer_end[-++written] = digits[digit]; + } while (remaining != 0); + } + + while ((int32_t)written < state->format_precision) + { + output_buffer_end[-++written] = '0'; + } + + size_t padding = 0; + + if (!RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_MINUS) && RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_ZERO)) + { + while (written < (ptrdiff_t)state->format_width) + { + output_buffer_end[-++written] = '0'; + ++padding; + } + } + + if (sign != '\0') + { + if (padding == 0) + { + ++written; + } + + output_buffer_end[-written] = sign; + } + else if (RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_ALT)) + { + switch (state->format_base) + { + case 2: + { + written += (padding < 2) ? (2 - padding) : 0; + output_buffer_end[-written + 0] = '0'; + output_buffer_end[-written + 1] = RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_LOWERCASE) ? 'b' : 'B'; + break; + } + + case 8: + { + if (output_buffer_end[-written] != '0') + { + output_buffer_end[-++written] = '0'; + } + break; + } + + case 16: + { + written += (padding < 2) ? (2 - padding) : 0; + output_buffer_end[-written + 0] = '0'; + output_buffer_end[-written + 1] = RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_LOWERCASE) ? 'x': 'X'; + break; + } + + default: + { + break; + } + } + } + + if (!RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_MINUS)) + { + char leading = (!RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_MINUS) && RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_ZERO)) ? '0' : ' '; + + while (written < (ptrdiff_t)state->format_width) + { + output_buffer_end[-++written] = leading; + } + } + + rtlp_format_emit_string_n(state, output_buffer_end - written, (size_t)written); +} + +static inline +void +rtlp_format_write_char( + struct format_state* state, + int value +) +{ + if (RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_MINUS)) + { + rtlp_format_emit_char(state, value, 1); + + if ((size_t)(uint32_t)state->format_width > state->current) + { + rtlp_format_emit_char(state, ' ', (size_t)(uint32_t)state->format_width - state->current); + } + } + else + { + if (state->format_width != 0) + { + size_t adjust = (size_t)(uint32_t)state->format_width - state->current - 1; + + rtlp_format_emit_char(state, ' ', adjust); + } + + rtlp_format_emit_char(state, value, 1); + } +} + +// Disable call to strlen :) +__attribute__((__optimize__("-fno-tree-loop-distribute-patterns"))) +static size_t (strlen)(const char* _String) +{ + const char* eos = _String; + + while (*eos != '\0') + { + ++eos; + } + + return eos - _String; +} + +static inline +void +rtlp_format_write_string( + struct format_state* state, + const char* string +) +{ + size_t length = strlen(string); + + if (state->format_precision >= 0) + { + size_t precision = (size_t)(uint32_t)state->format_precision; + length = RTL_MIN(length, precision); + } + + if ((state->format_width == 0) || RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_MINUS)) + { + if (state->format_precision > 0) + { + size_t precision = (size_t)(uint32_t)state->format_precision; + length = RTL_MIN(length, precision); + } + + rtlp_format_emit_string_n(state, string, length); + + if ((size_t)(uint32_t)state->format_width > state->current) + { + length = (size_t)(uint32_t)state->format_width - state->current; + + rtlp_format_emit_char(state, ' ', length); + } + } + else + { + if ((size_t)(uint32_t)state->format_width > length) + { + size_t padding = (size_t)(uint32_t)state->format_width - length; + + rtlp_format_emit_char(state, ' ', padding); + } + + rtlp_format_emit_string_n(state, string, length); + } +} + +static inline int +rtlp_format_handle_specifier( + struct format_state* state, + const char* specifier, + size_t* processed +) +{ + int status = 0; + + const char* mark = specifier; + + if (*(++specifier) == '%') + { + rtlp_format_emit_char(state, *specifier, 1); + + ++specifier; + (*processed) = (size_t)(ptrdiff_t)(specifier - mark); + return status; + } + + state->format_flags = 0; + state->format_base = 0; + state->format_type = 0; + state->format_width = 0; + state->format_precision = -1; + state->current = 0; + + do + { + switch (*specifier++) + { + case '-': + { + state->format_flags |= FORMAT_FLAGS_MINUS; + break; + } + case '+': + { + state->format_flags |= FORMAT_FLAGS_PLUS; + break; + } + case '#': + { + state->format_flags |= FORMAT_FLAGS_ALT; + break; + } + case ' ': + { + state->format_flags |= FORMAT_FLAGS_SPACE; + break; + } + case '0': + { + state->format_flags |= FORMAT_FLAGS_ZERO; + break; + } + default: + { + state->format_flags |= FORMAT_FLAGS_DONE; + --specifier; + break; + } + } + } while (!RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_DONE)); + + if (*specifier == '*') + { + int32_t width = (int32_t)va_arg(state->arglist, int); + + if (width < 0) + { + state->format_flags |= FORMAT_FLAGS_MINUS; + width = -width; + } + + state->format_width = width; + ++specifier; + } + else + { + int32_t width = 0; + + status = rtl_string_to_int32(&width, specifier, (char**)&specifier, 10); + if (status != 0) + { + (*processed) = 0; + return status; + } + + state->format_width = width; + } + + if (*specifier == '.') + { + ++specifier; + + if (*specifier == '*') + { + state->format_precision = (int32_t)va_arg(state->arglist, int); + ++specifier; + } + else + { + int32_t precision = 0; + + status = rtl_string_to_int32(&precision, specifier, (char**)&specifier, 10); + if (status != 0) + { + (*processed) = 0; + return status; + } + + state->format_precision = precision; + } + + state->format_flags = RTL_FLAGS_UNSET(state->format_flags, FORMAT_FLAGS_ZERO); + } + + switch (*(specifier++)) + { + case 'h': + { + if (*specifier == 'h') + { + state->format_type = FORMAT_TYPE_CHAR; + ++specifier; + } + else + { + state->format_type = FORMAT_TYPE_SHORT; + } + break; + } + + case 'l': + { + if (*specifier == 'l') + { + state->format_type = FORMAT_TYPE_LONGLONG; + ++specifier; + } + else + { + state->format_type = FORMAT_TYPE_LONG; + } + break; + } + + case 'j': + { + state->format_type = FORMAT_TYPE_INTMAX; + break; + } + + case 'z': + { + state->format_type = FORMAT_TYPE_SIZE; + break; + } + + case 't': + { + state->format_type = FORMAT_TYPE_PTRDIFF; + break; + } + + case 'L': + { + state->format_type = FORMAT_TYPE_LONGDOUBLE; + break; + } + + default: + { + --specifier; + break; + } + } + + switch (*specifier) + { + case 'b': + { + state->format_flags |= FORMAT_FLAGS_LOWERCASE; + } + case 'B': + { + state->format_type |= FORMAT_TYPE_UNSIGNED; + state->format_base = 2; + break; + } + + case 'o': + { + state->format_type |= FORMAT_TYPE_UNSIGNED; + state->format_base = 8; + break; + } + + case 'u': + { + state->format_type |= FORMAT_TYPE_UNSIGNED; + } + case 'd': + case 'i': + { + state->format_base = 10; + break; + } + + case 'x': + { + state->format_flags |= FORMAT_FLAGS_LOWERCASE; + } + case 'X': + { + state->format_type |= FORMAT_TYPE_UNSIGNED; + state->format_base = 16; + break; + } + + case 'p': + { + state->format_flags |= FORMAT_FLAGS_LOWERCASE; + } + case 'P': + { + state->format_flags |= FORMAT_FLAGS_ALT; + state->format_type = FORMAT_TYPE_UINTPTR; + state->format_precision = sizeof(uintptr_t) * 2; + state->format_base = 16; + break; + } + + case 'a': + case 'e': + case 'f': + case 'g': + { + state->format_flags |= FORMAT_FLAGS_LOWERCASE; + } + case 'A': + case 'E': + case 'F': + case 'G': + { + return -1; + } + + case 'c': + { + int value = (int)va_arg(state->arglist, int); + rtlp_format_write_char(state, value); + + ++specifier; + (*processed) = (size_t)(ptrdiff_t)(specifier - mark); + return 0; + } + + case 's': + { + const char* value = (const char*)va_arg(state->arglist, const char*); + + if (value == NULL) + { + value = "(null)"; + } + + rtlp_format_write_string(state, value); + + ++specifier; + (*processed) = (size_t)(ptrdiff_t)(specifier - mark); + return 0; + } + + default: + { + (*processed) = 0; + return -1; + } + } + + // Integral output. + + if (state->format_base != 0) + { + uintmax_t value; + + switch (state->format_type) + { + case FORMAT_TYPE_CHAR: + value = (uintmax_t)(intmax_t)(char)va_arg(state->arglist, int); + break; + case FORMAT_TYPE_SHORT: + value = (uintmax_t)(intmax_t)(short)va_arg(state->arglist, int); + break; + case FORMAT_TYPE_INT: + value = (uintmax_t)(intmax_t)(int)va_arg(state->arglist, int); + break; + case FORMAT_TYPE_LONG: + value = (uintmax_t)(intmax_t)(long)va_arg(state->arglist, long); + break; + case FORMAT_TYPE_LONGLONG: + value = (uintmax_t)(intmax_t)(long long)va_arg(state->arglist, long long); + break; + case FORMAT_TYPE_UNSIGNED | FORMAT_TYPE_CHAR: + value = (uintmax_t)(unsigned char)va_arg(state->arglist, int); + break; + case FORMAT_TYPE_UNSIGNED | FORMAT_TYPE_SHORT: + value = (uintmax_t)(unsigned short)va_arg(state->arglist, int); + break; + case FORMAT_TYPE_UNSIGNED | FORMAT_TYPE_INT: + value = (uintmax_t)(unsigned int)va_arg(state->arglist, unsigned int); + break; + case FORMAT_TYPE_UNSIGNED | FORMAT_TYPE_LONG: + value = (uintmax_t)(unsigned long)va_arg(state->arglist, unsigned long); + break; + case FORMAT_TYPE_UNSIGNED | FORMAT_TYPE_LONGLONG: + value = (uintmax_t)(unsigned long long)va_arg(state->arglist, unsigned long long); + break; + default: + (*processed) = 0; + return -1; + } + + rtlp_format_write_integer(state, value); + + if (RTL_FLAGS_HAS(state->format_flags, FORMAT_FLAGS_MINUS) && (state->current - (size_t)(uint32_t)state->format_width) != 0) // Check: possible overrun + { + rtlp_format_emit_char(state, ' ', (size_t)(uint32_t)state->format_width - state->current); + } + } + + ++specifier; + + (*processed) = (size_t)(ptrdiff_t)(specifier - mark); + return status; +} + +int +rtl_string_format_v( + char* buffer, + size_t buffer_length, + size_t* processed, + const char* format, + va_list arglist +) +{ + if (format == NULL) + { + return -1; + } + + if ((buffer == NULL) && (buffer_length != 0)) + { + return -1; + } + + struct format_state state = { + .format_base = 0, + .format_flags = 0, + .format_type = 0, + .format_width = 0, + .format_precision = 0, + .buffer = buffer, + .buffer_capacity = buffer_length, + .processed = 0, + .current = 0, + }; + va_copy(state.arglist, arglist); + + int status = 0; + + while (*format != '\0') + { + const char* mark = format; + + while (*format != '\0' && *format != '%') + { + ++format; + } + + if (mark != format) + { + rtlp_format_emit_string_n(&state, mark, format - mark); + } + + if (*format == '%') + { + size_t consumed = 0; + status = rtlp_format_handle_specifier(&state, format, &consumed); + + if (status != 0) + { + if (processed != NULL) + { + (*processed) = 0; + } + return status; + } + + format += consumed; + + if (consumed == 0) + { + ++format; + rtlp_format_emit_char(&state, *format, 1); + } + } + } + + if (state.buffer != NULL) + { + if (state.processed < state.buffer_capacity) + { + state.buffer[state.processed] = '\0'; + } + else + { + state.buffer[state.buffer_capacity - 1] = '\0'; + } + } + + va_end(state.arglist); + + if (processed != NULL) + { + (*processed) = state.processed; + } + + return status; +} + +int +rtl_string_format( + char* buffer, + size_t buffer_length, + size_t* processed, + const char* format, + ... +) +{ + va_list arglist; + va_start(arglist, format); + int status = rtl_string_format_v( + buffer, + buffer_length, + processed, + format, + arglist + ); + va_end(arglist); + + return status; +} diff --git a/042-osdev-08/source/kernel/source/ssp.c b/042-osdev-08/source/kernel/source/ssp.c new file mode 100644 index 0000000..63f1021 --- /dev/null +++ b/042-osdev-08/source/kernel/source/ssp.c @@ -0,0 +1,18 @@ +#include "common.h" +#include + +#include + +void* __stack_chk_guard = NULL; + +void +__stack_chk_fail() +{ + GuruPanicOfDeath("STACK_FRAME_SMASHED", NULL); +} + +void +__chk_fail(void) +{ + GuruPanicOfDeath("STACK_FRAME_SMASHED", NULL); +} diff --git a/042-osdev-08/terminal.c b/042-osdev-08/source/kernel/source/terminal.c similarity index 72% rename from 042-osdev-08/terminal.c rename to 042-osdev-08/source/kernel/source/terminal.c index f16c5dd..6986b1d 100644 --- a/042-osdev-08/terminal.c +++ b/042-osdev-08/source/kernel/source/terminal.c @@ -1,6 +1,7 @@ #include #include "common.h" #include "terminal.h" +#include "hal.h" void T_SetCursorPosition( TerminalBackend *tb, uint16_t x, uint16_t y) { @@ -138,62 +139,36 @@ void T_PrintHex(TerminalBackend *tb, size_t n, int width) { } } +extern int +rtl_string_format_v( + char* buffer, + size_t buffer_length, + size_t* processed, + const char* format, + va_list arglist +); + void T_Printf(TerminalBackend *tb, const char *fmt, ...) { va_list args; va_start(args, fmt); - - const char *p = fmt; - - while (*p != '\0') { - if (*p != '%') { - T_PrintChar(tb, *p); - p++; - continue; - } - p++; - - switch(*p) { - case 'p': - T_PrintHex(tb, va_arg(args, size_t), 16); - p++; - continue; - - case 'c': - T_PrintChar(tb, va_arg(args, int)); - p++; - continue; - - case 'i': - case 'd': - T_PrintInt(tb, va_arg(args, int)); - p++; - continue; - - case 'u': - T_PrintUInt(tb, va_arg(args, size_t)); - p++; - continue; - - case 'x': - T_PrintHex(tb, va_arg(args, size_t), 0); - p++; - continue; - - case 's': - T_PutText(tb, va_arg(args, const char*)); - p++; - continue; - - case '%': - T_PrintChar(tb, *p); - p++; - continue; - - default: - break; - } + char buffer[512]; + + size_t processed = 0; + int result_code = rtl_string_format_v(buffer, sizeof(buffer), &processed, fmt, args); + + if (result_code == 0 && processed != 0) + { + T_PutText(tb, buffer); } + else + { + T_PutText(tb, "Internal Terminal Error\n"); + HAL_PauseKernel(); + } + + (void)result_code; + (void)processed; va_end(args); } diff --git a/042-osdev-08/terminal_backend_b8000.c b/042-osdev-08/source/kernel/source/terminal_backend_b8000.c similarity index 100% rename from 042-osdev-08/terminal_backend_b8000.c rename to 042-osdev-08/source/kernel/source/terminal_backend_b8000.c diff --git a/042-osdev-08/stage1 b/042-osdev-08/stage1 deleted file mode 100644 index 4f818b5b3860e6bd69d4f548d4904681c96bffc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 512 wcmaFGTEoDwgF&J1fZ^>eOdCulOxVh>k!c&lS>aa<3=9fDJPL+y2!yTz03+=TUjP6A diff --git a/042-osdev-08/stage2 b/042-osdev-08/stage2 deleted file mode 100644 index d59e5f5de3dea79116c86e242a47b34251b7858f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16896 zcmeI(zi(dE9mnyn9iX%gJb^YTP)eSrq)mU~P<{m3(xVQQBRL&AR%Z%-K$ZOL=+p%kgpnA&Q^e3VVT0`mAqIvD2|<6TQhIG(S=b{*>bbJ~vL4^}_0`9crAP8T z*m&}9CqKA$eDlL=|2c^D)pxJvL7cvN^ZW;^jZ>e-YMqyN-`-fA$;%&|kIlG0E+3qT z!?Uj5JctvUu{!haYCU$}Ua!uKH(Nxmo_-)UB34^V`andqrCn{DTyJc~N5B8V6}I=E zIlKPVW^BK5Jr-7P96x(u@xPbOf3|<$?!Pv!ytK3b>-%^1e{*7I|F`R%{okFt^oP%` z9J{pl_wBt;FYevgIsABUD?j5;xx=I5)~$s<-H0Qv-SBF}=_t2PJv#r3pKhP{dH<^Z z)!Q#m=K^zqxxidtE-)9E3(N)P0&{`6z+7N1a91pFY`u9`+{e6$xxidtE-)9E3(N)P z0&{`6z+7N1Fc+8$%mwb;0>`%I`~N$)?!59`U@kBhmSzS@n#%Er#*;NgG!M=U)HD;qnLgUd4kpZ6@RZ0t-9#xXq$D;qnLgK>|Z zg_Vt+$-%f+&%(;a&g5X+r)ObhV`p+OzNBYiWn*V@aCxR`V^Eqk0xrHg+Zl<1sx8D;qnL zgYiv03o9EtlY{ZNo`sc-oyo!YmY#)`jh)HCctX#@%Er#*;PQytax8y;SXkNEnH-F@ zo`sc-oyo!Yb}Yy8^I2Hg*qI!RGkO+QHg+Zl<2!m5RyKAf2jfXS3o9EtlY? Date: Thu, 1 Jun 2017 23:24:14 +0200 Subject: [PATCH 2/8] Cooler halt in ISR, added linker script to control elf executable content. Strip is done already along with listing. --- 042-osdev-08/source/kernel/project.mk | 9 +++-- .../source/kernel/source/int_handlers.c | 3 +- 042-osdev-08/source/kernel/source/linker.lds | 39 +++++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 042-osdev-08/source/kernel/source/linker.lds diff --git a/042-osdev-08/source/kernel/project.mk b/042-osdev-08/source/kernel/project.mk index b5881bf..ab3bd71 100644 --- a/042-osdev-08/source/kernel/project.mk +++ b/042-osdev-08/source/kernel/project.mk @@ -6,19 +6,20 @@ project.path = kernel project.component.major = boot project.component.minor = kernel project.emit-metadata = true -project.configuration = debug +project.configuration = release project.sources = \ $(wildcard source/*.S) \ $(wildcard source/*.c) -project.flags.cc = -ffreestanding -nostdlib -nostartfiles -masm=intel -project.flags.as = -ffreestanding -nostdlib -nostartfiles -masm=intel -project.flags.cxx = -ffreestanding -nostdlib -nostartfiles -masm=intel +project.flags.cc = -ffreestanding -nostdlib -nostartfiles -masm=intel -mno-sse2 -mno-sse -mno-sse3 -mno-ssse3 -mno-sse4 +project.flags.as = -ffreestanding -nostdlib -nostartfiles -masm=intel -mno-sse2 -mno-sse -mno-sse3 -mno-ssse3 -mno-sse4 +project.flags.cxx = -ffreestanding -nostdlib -nostartfiles -masm=intel -mno-sse2 -mno-sse -mno-sse3 -mno-ssse3 -mno-sse4 project.flags.link = \ -ffreestanding \ -nostdlib \ + -Tsource/linker.lds \ -Wl,-z,max-page-size=0x1000 \ -Wl,-z,common-page-size=0x1000 diff --git a/042-osdev-08/source/kernel/source/int_handlers.c b/042-osdev-08/source/kernel/source/int_handlers.c index d159d63..fdc5aac 100644 --- a/042-osdev-08/source/kernel/source/int_handlers.c +++ b/042-osdev-08/source/kernel/source/int_handlers.c @@ -1,6 +1,7 @@ #include "common.h" #include "terminal.h" #include "terminal_backend_b8000.h" +#include "hal.h" #include void GuruPanicOfDeath(const char *reason, TrapFrame *frame) { @@ -26,7 +27,7 @@ void GuruPanicOfDeath(const char *reason, TrapFrame *frame) { T_PutText(con, "System halt."); - for (;;); + HAL_PauseKernel(); } diff --git a/042-osdev-08/source/kernel/source/linker.lds b/042-osdev-08/source/kernel/source/linker.lds new file mode 100644 index 0000000..180211a --- /dev/null +++ b/042-osdev-08/source/kernel/source/linker.lds @@ -0,0 +1,39 @@ +ENTRY(_start) +OUTPUT_FORMAT(elf64-x86-64) + +SECTIONS +{ + . = 1M; + + .text ALIGN(0x1000): { + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + } + + .rodata ALIGN(0x1000): { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + + .data ALIGN(0x1000): { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + } + + .bss ALIGN(0x1000): { + *(COMMON) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + } + + /DISCARD/ : + { + *(.comment) + *(.eh_frame) /* C++ Exception Handler Frames are not required for kernel */ + } + +} From 4bc4c428c535f5edf4b499a3456201be047aeb42 Mon Sep 17 00:00:00 2001 From: selmentdev Date: Thu, 1 Jun 2017 23:35:13 +0200 Subject: [PATCH 3/8] Added attribute support to terminal backend --- 042-osdev-08/source/kernel/include/terminal.h | 22 +++++++++++++++++++ .../source/kernel/source/int_handlers.c | 1 + 042-osdev-08/source/kernel/source/terminal.c | 4 ++++ .../kernel/source/terminal_backend_b8000.c | 17 +++++++++++--- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/042-osdev-08/source/kernel/include/terminal.h b/042-osdev-08/source/kernel/include/terminal.h index 232d993..13eebb0 100644 --- a/042-osdev-08/source/kernel/include/terminal.h +++ b/042-osdev-08/source/kernel/include/terminal.h @@ -4,6 +4,25 @@ struct TerminalBackend; typedef struct TerminalBackend TerminalBackend; +typedef enum TerminalColor { + TerminalColor_Black = 0, + TerminalColor_Blue = 1, + TerminalColor_Green = 2, + TerminalColor_Cyan = 3, + TerminalColor_Red = 4, + TerminalColor_Magenta = 5, + TerminalColor_Brown = 6, + TerminalColor_LightGray = 7, + TerminalColor_Gray = 8, + TerminalColor_LightBlue = 9, + TerminalColor_LightGreen = 10, + TerminalColor_LightCyan = 11, + TerminalColor_LightRed = 12, + TerminalColor_LightMagenta = 13, + TerminalColor_LightYellow = 14, + TerminalColor_LightWhite = 15 +} TerminalColor; + // XXX on creation limit size to 32000x32000 typedef void (*TBfunc_SetCursorPosition)( @@ -11,6 +30,7 @@ typedef void (*TBfunc_SetCursorPosition)( typedef void (*TBfunc_GetCursorPosition)( TerminalBackend *tb, uint16_t *x, uint16_t *y); typedef void (*TBfunc_ClearScreen)(TerminalBackend *tb); +typedef void (*TBfunc_SetAttribute)(TerminalBackend *tb, TerminalColor bgcolor, TerminalColor fgcolor); typedef void (*TBfunc_PutCharacter)(TerminalBackend *tb, uint32_t ch); typedef void (*TBfunc_GetSize)(TerminalBackend *tb, uint16_t *w, uint16_t *h); @@ -20,6 +40,7 @@ struct TerminalBackend { TBfunc_SetCursorPosition func_set_cursor_position; TBfunc_GetCursorPosition func_get_cursor_position; TBfunc_ClearScreen func_clear_screen; + TBfunc_SetAttribute func_set_attribute; TBfunc_PutCharacter func_put_character; TBfunc_GetSize func_get_size; TBfunc_ScrollLine func_scroll_line; @@ -31,6 +52,7 @@ void T_SetCursorPosition( void T_GetCursorPosition( TerminalBackend *tb, uint16_t *x, uint16_t *y); void T_PutText(TerminalBackend *tb, const char *s); +void T_SetAttribute(TerminalBackend *tb, TerminalColor bgcolor, TerminalColor fgcolor); void T_ClearScreen(TerminalBackend *tb); void T_PutCharacter(TerminalBackend *tb, uint32_t ch); void T_GetSize(TerminalBackend *tb, uint16_t *w, uint16_t *h); diff --git a/042-osdev-08/source/kernel/source/int_handlers.c b/042-osdev-08/source/kernel/source/int_handlers.c index fdc5aac..c076801 100644 --- a/042-osdev-08/source/kernel/source/int_handlers.c +++ b/042-osdev-08/source/kernel/source/int_handlers.c @@ -6,6 +6,7 @@ void GuruPanicOfDeath(const char *reason, TrapFrame *frame) { TerminalBackend *con = TerminalBackendB8000(); + T_SetAttribute(con, TerminalColor_Blue, TerminalColor_LightWhite); T_ClearScreen(con); T_PutText(con, "Guru Panic Of Death!!!\n\n"); T_Printf(con, "Reason: %s\n\n", reason); diff --git a/042-osdev-08/source/kernel/source/terminal.c b/042-osdev-08/source/kernel/source/terminal.c index 6986b1d..5ae4cb4 100644 --- a/042-osdev-08/source/kernel/source/terminal.c +++ b/042-osdev-08/source/kernel/source/terminal.c @@ -58,6 +58,10 @@ void T_ClearScreen(TerminalBackend *tb) { tb->func_clear_screen(tb); } +void T_SetAttribute(TerminalBackend *tb, TerminalColor bgcolor, TerminalColor fgcolor) { + tb->func_set_attribute(tb, bgcolor, fgcolor); +} + void T_PutCharacter(TerminalBackend *tb, uint32_t ch) { tb->func_put_character(tb, ch); } diff --git a/042-osdev-08/source/kernel/source/terminal_backend_b8000.c b/042-osdev-08/source/kernel/source/terminal_backend_b8000.c index 88dee1a..695cb2a 100644 --- a/042-osdev-08/source/kernel/source/terminal_backend_b8000.c +++ b/042-osdev-08/source/kernel/source/terminal_backend_b8000.c @@ -16,6 +16,7 @@ enum { static struct B8000_ContextStruct { unsigned short x; unsigned short y; + unsigned char attribute; } B8000_Context; static void B8000_ScrollLine(TerminalBackend *tb); @@ -48,12 +49,21 @@ static void B8000_ClearScreen(TerminalBackend *tb) { unsigned char *textvram = (unsigned char*)0xB8000; for (int i = 0; i < 80 * 25; i++) { textvram[i * 2 + 0] = ' '; - textvram[i * 2 + 1] = 0x0A; + textvram[i * 2 + 1] = B8000_Context.attribute; } B8000_SetCursorPosition(tb, 0, 0); } +static void B8000_SetAttribute(TerminalBackend *tb, TerminalColor bgcolor, TerminalColor fgcolor) { + UNUSED(tb); + const unsigned char attr_bg = (unsigned char)(bgcolor & 0xF) << 4; + const unsigned char attr_fg = (unsigned char)(fgcolor & 0xF) << 0; + const unsigned char attribute = attr_bg | attr_fg; + + B8000_Context.attribute = attribute; +} + static void B8000_PutCharacter(TerminalBackend *tb, uint32_t ch) { UNUSED(tb); unsigned char *textvram = (unsigned char*)0xB8000; @@ -69,7 +79,7 @@ static void B8000_PutCharacter(TerminalBackend *tb, uint32_t ch) { unsigned int offset = x + y * 80; textvram[offset * 2 + 0] = (unsigned char)ch; - textvram[offset * 2 + 1] = 0x0A; + textvram[offset * 2 + 1] = B8000_Context.attribute; x += 1; if (x == 80) { @@ -100,7 +110,7 @@ static void B8000_ScrollLine(TerminalBackend *tb) { for (size_t i = 80 * (25 - 1) * 2; i < 80 * 25 * 2; i+= 2) { textvram[i + 0] = ' '; - textvram[i + 1] = 0x0A; + textvram[i + 1] = B8000_Context.attribute; } B8000_SetCursorPosition(tb, 0, 25 - 1); @@ -110,6 +120,7 @@ static const TerminalBackend B8000_Functions = { .func_set_cursor_position = B8000_SetCursorPosition, .func_get_cursor_position = B8000_GetCursorPosition, .func_clear_screen = B8000_ClearScreen, + .func_set_attribute = B8000_SetAttribute, .func_put_character = B8000_PutCharacter, .func_get_size = B8000_GetSize, .func_scroll_line = B8000_ScrollLine From fbd1bc422c8777ea2ecd19f9610bfae9c42eb11b Mon Sep 17 00:00:00 2001 From: selmentdev Date: Thu, 1 Jun 2017 23:50:27 +0200 Subject: [PATCH 4/8] Changing VGA mode in stage1 to 80x50, added Homer Meditation :) --- .../source/bootloader/source/stage1.asm | 9 ++++ .../source/kernel/source/int_handlers.c | 43 ++++++++++++++++--- 042-osdev-08/source/kernel/source/rtl.c | 8 +++- .../kernel/source/terminal_backend_b8000.c | 30 ++++++++----- 4 files changed, 72 insertions(+), 18 deletions(-) diff --git a/042-osdev-08/source/bootloader/source/stage1.asm b/042-osdev-08/source/bootloader/source/stage1.asm index 567bee1..8489543 100644 --- a/042-osdev-08/source/bootloader/source/stage1.asm +++ b/042-osdev-08/source/bootloader/source/stage1.asm @@ -16,6 +16,15 @@ start: ;mov word [es:di], 0x4141 ;jmp $ + ; + ; Change VGA mode to 80x50. Terminal_backend_b8000.c now rely on this screen dimensions. + ; + mov ax, 0003h + int 10h ;first set mode 03h + xor bx, bx + mov ax, 1112h + int 10h ;load 8x8 font + ; Load from floppy stage 2. ; DL == already set by BIOS ; AX -- 16 bits, AH AL -- 8 bits diff --git a/042-osdev-08/source/kernel/source/int_handlers.c b/042-osdev-08/source/kernel/source/int_handlers.c index c076801..d8ee85f 100644 --- a/042-osdev-08/source/kernel/source/int_handlers.c +++ b/042-osdev-08/source/kernel/source/int_handlers.c @@ -6,13 +6,45 @@ void GuruPanicOfDeath(const char *reason, TrapFrame *frame) { TerminalBackend *con = TerminalBackendB8000(); - T_SetAttribute(con, TerminalColor_Blue, TerminalColor_LightWhite); + T_SetAttribute(con, TerminalColor_Black, TerminalColor_LightYellow); T_ClearScreen(con); - T_PutText(con, "Guru Panic Of Death!!!\n\n"); - T_Printf(con, "Reason: %s\n\n", reason); + T_PutText(con, "Homer Meditation of Donuts!!!\n\n"); + + T_PutText(con, "(credit: http://www.chris.com/ascii/index.php?art=cartoons/simpsons)\n\n"); + + + T_PutText(con, + " _ _,---._ \n" + " ,-',' `-.___ \n" + " /-;' `._ \n" + " /\\/ ._ _,'o \\ \n" + " ( /\\ _,--'\\,','\"`. ) \n" + " |\\ ,'o \' //\\ \n" + " | \\ / ,--'""`-. \n" + " : \\_ _/ ,-' `-._ \n" + " \\ `--' / ) \n" + " `. \\`._ ,' ________,',' \n" + " .--` ,' ,--` __\\___,;' \n" + " \\`.,-- ,' ,`_)--' /`.,' \n" + " \\( ; | | ) (`-/ \n" + " `--'| |) |-/ \n" + " | | | | | \n" + " | | |,.,-. | |_ \n" + " | `./ / )---` ) \n" + " _| / ,', ,-' \n" + " -hrr- ,'|_( /-<._,' |--, \n" + " | `--'---. \\/ \\ \n" + " | / \\ /\\ \\ \n" + " ,-^---._ | \\ / \\ \\ \n" + " ,-' \\----' \\/ \\--`. \n" + " / \\ \\ \\ \n" + "\n" + ); + + T_Printf(con, "Reason: %s\n", reason); if (frame != NULL) { - T_PutText(con, "State:\n\n"); + T_PutText(con, "State:\n"); T_Printf(con, " RAX: %016llx\tR8: %016llx\n", frame->rax, frame->r8); T_Printf(con, " RBX: %016llx\tR9: %016llx\n", frame->rbx, frame->r9); @@ -22,8 +54,7 @@ void GuruPanicOfDeath(const char *reason, TrapFrame *frame) { T_Printf(con, " RDI: %016llx\tR13: %016llx\n", frame->rdi, frame->r13); T_Printf(con, " RBP: %016llx\tR14: %016llx\n", frame->rbp, frame->r14); T_Printf(con, " RSP: %016llx\tR15: %016llx\n", frame->rsp, frame->r15); - - T_Printf(con, " CS:RIP: %04x:%016llx\n\n", frame->segment_cs, frame->rip); + T_Printf(con, " CS:RIP: %04hx:%016llx\n\n", frame->segment_cs, frame->rip); } T_PutText(con, "System halt."); diff --git a/042-osdev-08/source/kernel/source/rtl.c b/042-osdev-08/source/kernel/source/rtl.c index 7e413f6..c020899 100644 --- a/042-osdev-08/source/kernel/source/rtl.c +++ b/042-osdev-08/source/kernel/source/rtl.c @@ -1,3 +1,9 @@ +//-------------------------------------------------------------------------------------------------- +// +// By Karol Grzybowski, 2017 +// +//-------------------------------------------------------------------------------------------------- + #include "common.h" #include #include @@ -122,7 +128,7 @@ struct format_state { // Disable call to stdlib function (don't remember which one :D) __attribute__((__optimize__("-fno-tree-loop-distribute-patterns"))) -int +static int rtl_string_to_int32( int32_t* result, const char* string, diff --git a/042-osdev-08/source/kernel/source/terminal_backend_b8000.c b/042-osdev-08/source/kernel/source/terminal_backend_b8000.c index 695cb2a..3fdf708 100644 --- a/042-osdev-08/source/kernel/source/terminal_backend_b8000.c +++ b/042-osdev-08/source/kernel/source/terminal_backend_b8000.c @@ -16,15 +16,23 @@ enum { static struct B8000_ContextStruct { unsigned short x; unsigned short y; + unsigned short width; + unsigned short height; unsigned char attribute; -} B8000_Context; +} B8000_Context = { + .x = 0, + .y = 0, + .width = 80, + .height = 50, + .attribute = 0x1F +}; static void B8000_ScrollLine(TerminalBackend *tb); static void B8000_SetCursorPosition( TerminalBackend *tb, uint16_t x, uint16_t y) { UNUSED(tb); - unsigned int offset = y * 80 + x; + unsigned int offset = y * B8000_Context.width + x; // ASSERT(offset <= 0xffff); // ASSERT(offset <= 80 * 25) <--- w * h konsoli @@ -47,7 +55,7 @@ static void B8000_SetCursorPosition( static void B8000_ClearScreen(TerminalBackend *tb) { UNUSED(tb); unsigned char *textvram = (unsigned char*)0xB8000; - for (int i = 0; i < 80 * 25; i++) { + for (int i = 0; i < B8000_Context.width * B8000_Context.height; i++) { textvram[i * 2 + 0] = ' '; textvram[i * 2 + 1] = B8000_Context.attribute; } @@ -71,18 +79,18 @@ static void B8000_PutCharacter(TerminalBackend *tb, uint32_t ch) { unsigned short x = B8000_Context.x; unsigned short y = B8000_Context.y; - if (y == 25) { + if (y == B8000_Context.height) { B8000_ScrollLine(tb); x = B8000_Context.x; y = B8000_Context.y; } - unsigned int offset = x + y * 80; + unsigned int offset = x + y * B8000_Context.width; textvram[offset * 2 + 0] = (unsigned char)ch; textvram[offset * 2 + 1] = B8000_Context.attribute; x += 1; - if (x == 80) { + if (x == B8000_Context.width) { x = 0; y += 1; } @@ -100,20 +108,20 @@ static void B8000_GetCursorPosition( static void B8000_GetSize(TerminalBackend *tb, uint16_t *w, uint16_t *h) { UNUSED(tb); - *w = 80; - *h = 25; + *w = B8000_Context.width; + *h = B8000_Context.height; } static void B8000_ScrollLine(TerminalBackend *tb) { unsigned char *textvram = (unsigned char*)0xB8000; - memmove(textvram, textvram + 80 * 2, 80 * (25 - 1) * 2); + memmove(textvram, textvram + B8000_Context.width * 2, B8000_Context.width * (B8000_Context.height - 1) * 2); - for (size_t i = 80 * (25 - 1) * 2; i < 80 * 25 * 2; i+= 2) { + for (size_t i = B8000_Context.width * (B8000_Context.height - 1) * 2; i < B8000_Context.width * B8000_Context.height * 2; i+= 2) { textvram[i + 0] = ' '; textvram[i + 1] = B8000_Context.attribute; } - B8000_SetCursorPosition(tb, 0, 25 - 1); + B8000_SetCursorPosition(tb, 0, B8000_Context.height - 1); } static const TerminalBackend B8000_Functions = { From acf1e8da442f4bc107bd0d4d0865643d72413e78 Mon Sep 17 00:00:00 2001 From: selmentdev Date: Thu, 1 Jun 2017 23:53:30 +0200 Subject: [PATCH 5/8] Added changes readme --- 042-osdev-08/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 042-osdev-08/README.md diff --git a/042-osdev-08/README.md b/042-osdev-08/README.md new file mode 100644 index 0000000..95fcaee --- /dev/null +++ b/042-osdev-08/README.md @@ -0,0 +1,15 @@ +# Changes + +- added mode changing to 80x50 +- added terminal backend character attribute changing API +- reworked source files to use makefile based build system + +# Building + +Now everything is enclosed in single + +```bash +make clean && make build +``` + +In this configuration it uses qemu instead of bochs (which I find kinda slow anyway...). Adding bochs support is relative easy anyway. \ No newline at end of file From c73015c2dd0c7cc307c515e7f9f48b6e2a7224e7 Mon Sep 17 00:00:00 2001 From: selmentdev Date: Thu, 1 Jun 2017 23:55:07 +0200 Subject: [PATCH 6/8] Final touch --- 042-osdev-08/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/042-osdev-08/README.md b/042-osdev-08/README.md index 95fcaee..d56bc5f 100644 --- a/042-osdev-08/README.md +++ b/042-osdev-08/README.md @@ -2,11 +2,12 @@ - added mode changing to 80x50 - added terminal backend character attribute changing API +- added string formatting API (sorry, no floats) - reworked source files to use makefile based build system # Building -Now everything is enclosed in single +Now building and cleaning everything is as simple as ```bash make clean && make build From 89ab533d1da7d7ee4c9f0226c6be225d1cd6f59f Mon Sep 17 00:00:00 2001 From: selmentdev Date: Thu, 1 Jun 2017 23:55:32 +0200 Subject: [PATCH 7/8] Changes author footnote :) --- 042-osdev-08/README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/042-osdev-08/README.md b/042-osdev-08/README.md index d56bc5f..a77ae8d 100644 --- a/042-osdev-08/README.md +++ b/042-osdev-08/README.md @@ -1,11 +1,14 @@ -# Changes +# Readme + +## Changes - added mode changing to 80x50 - added terminal backend character attribute changing API - added string formatting API (sorry, no floats) - reworked source files to use makefile based build system -# Building + +## Building Now building and cleaning everything is as simple as @@ -13,4 +16,9 @@ Now building and cleaning everything is as simple as make clean && make build ``` -In this configuration it uses qemu instead of bochs (which I find kinda slow anyway...). Adding bochs support is relative easy anyway. \ No newline at end of file +In this configuration it uses qemu instead of bochs (which I find kinda slow anyway...). Adding bochs support is relative easy anyway. + + +## Author + +Karol Grzybowski (2017) \ No newline at end of file From dd7475db66100683938e28f311ab6f2d3a6e3f17 Mon Sep 17 00:00:00 2001 From: selmentdev Date: Thu, 1 Jun 2017 23:58:58 +0200 Subject: [PATCH 8/8] Preview --- 042-osdev-08/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/042-osdev-08/README.md b/042-osdev-08/README.md index a77ae8d..99c3659 100644 --- a/042-osdev-08/README.md +++ b/042-osdev-08/README.md @@ -19,6 +19,11 @@ make clean && make build In this configuration it uses qemu instead of bochs (which I find kinda slow anyway...). Adding bochs support is relative easy anyway. +## Panic Contest + +[![Image](http://i.imgur.com/qDneBv1.png)](http://i.imgur.com/qDneBv1.png "Preview") + + ## Author Karol Grzybowski (2017) \ No newline at end of file