Initial commit
This commit is contained in:
114
.gitignore
vendored
Normal file
114
.gitignore
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/cmake,jetbrains+all
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=cmake,jetbrains+all
|
||||||
|
|
||||||
|
### CMake ###
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
CMakeUserPresets.json
|
||||||
|
|
||||||
|
### CMake Patch ###
|
||||||
|
# External projects
|
||||||
|
*-prefix/
|
||||||
|
|
||||||
|
### JetBrains+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### JetBrains+all Patch ###
|
||||||
|
# Ignores the whole .idea folder and all .iml files
|
||||||
|
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
modules.xml
|
||||||
|
.idea/misc.xml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
.idea/sonarlint
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/cmake,jetbrains+all
|
||||||
|
|
||||||
|
*.old
|
||||||
25
CMakeLists.txt
Normal file
25
CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
project(new_kernel C ASM)
|
||||||
|
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
|
set(CMAKE_C_FLAGS "-g -ffreestanding -Wall -Wextra -fno-exceptions -fno-stack-protector -nostdinc -nostdlib -fno-pie -m32")
|
||||||
|
set(CMAKE_ASM_NASM_OBJECT_FORMAT "elf")
|
||||||
|
set(CMAKE_ASM_FLAGS --32)
|
||||||
|
#set(CMAKE_ASM-ATT_FLAGS --32)
|
||||||
|
SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/linker.ld -lgcc -ffreestanding -nostdlib")
|
||||||
|
set(CMAKE_ASM_COMPILER "/usr/bin/as")
|
||||||
|
#ENABLE_LANGUAGE(ASM_NASM)
|
||||||
|
#enable_language(ASM)
|
||||||
|
|
||||||
|
include_directories(AFTER kernel boot)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
|
FILE(GLOB_RECURSE kernel_src kernel/**.c)
|
||||||
|
FILE(GLOB_RECURSE kernel_asm kernel/**.S)
|
||||||
|
FILE(GLOB_RECURSE boot_asm boot/boot.S)
|
||||||
|
|
||||||
|
add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm})
|
||||||
|
set_source_files_properties(${kernel_src} PROPERTIES LANGUAGE C COMPILE_FLAGS "")
|
||||||
|
set_target_properties(my-kernel.bin PROPERTIES LINKER_LANGUAGE C PREFIX "" SUFFIX "" LINK_FLAGS "")
|
||||||
|
|
||||||
|
|
||||||
130
boot/boot.S
Normal file
130
boot/boot.S
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/* Declare constants for the multiboot header. */
|
||||||
|
.set ALIGN, 1<<0 /* align loaded modules on page boundaries */
|
||||||
|
.set MEMINFO, 1<<1 /* provide memory map */
|
||||||
|
.set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */
|
||||||
|
.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
|
||||||
|
.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Declare a multiboot header that marks the program as a kernel. These are magic
|
||||||
|
values that are documented in the multiboot standard. The bootloader will
|
||||||
|
search for this signature in the first 8 KiB of the kernel file, aligned at a
|
||||||
|
32-bit boundary. The signature is in its own section so the header can be
|
||||||
|
forced to be within the first 8 KiB of the kernel file.
|
||||||
|
*/
|
||||||
|
.section .multiboot
|
||||||
|
.align 4
|
||||||
|
.long MAGIC
|
||||||
|
.long FLAGS
|
||||||
|
.long CHECKSUM
|
||||||
|
|
||||||
|
#.include "gdt.S"
|
||||||
|
.section .data
|
||||||
|
gdt:
|
||||||
|
.quad 0x0000000000000000
|
||||||
|
.quad 0x00CF9A000000FFFF
|
||||||
|
.quad 0x00CF92000000FFFF
|
||||||
|
.quad 0x00CFFA000000FFFF
|
||||||
|
.quad 0x00CFF2000000FFFF
|
||||||
|
|
||||||
|
gdtr:
|
||||||
|
.word 40
|
||||||
|
.long gdt # For base storage
|
||||||
|
/*
|
||||||
|
The multiboot standard does not define the value of the stack pointer register
|
||||||
|
(esp) and it is up to the kernel to provide a stack. This allocates room for a
|
||||||
|
small stack by creating a symbol at the bottom of it, then allocating 16384
|
||||||
|
bytes for it, and finally creating a symbol at the top. The stack grows
|
||||||
|
downwards on x86. The stack is in its own section so it can be marked nobits,
|
||||||
|
which means the kernel file is smaller because it does not contain an
|
||||||
|
uninitialized stack. The stack on x86 must be 16-byte aligned according to the
|
||||||
|
System V ABI standard and de-facto extensions. The compiler will assume the
|
||||||
|
stack is properly aligned and failure to align the stack will result in
|
||||||
|
undefined behavior.
|
||||||
|
*/
|
||||||
|
.section .bss
|
||||||
|
.align 16
|
||||||
|
stack_bottom:
|
||||||
|
.skip 16384 # 16 KiB
|
||||||
|
stack_top:
|
||||||
|
|
||||||
|
/*
|
||||||
|
The linker script specifies _start as the entry point to the kernel and the
|
||||||
|
bootloader will jump to this position once the kernel has been loaded. It
|
||||||
|
doesn't make sense to return from this function as the bootloader is gone.
|
||||||
|
*/
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
/*
|
||||||
|
The bootloader has loaded us into 32-bit protected mode on a x86
|
||||||
|
machine. Interrupts are disabled. Paging is disabled. The processor
|
||||||
|
state is as defined in the multiboot standard. The kernel has full
|
||||||
|
control of the CPU. The kernel can only make use of hardware features
|
||||||
|
and any code it provides as part of itself. There's no printf
|
||||||
|
function, unless the kernel provides its own <stdio.h> header and a
|
||||||
|
printf implementation. There are no security restrictions, no
|
||||||
|
safeguards, no debugging mechanisms, only what the kernel provides
|
||||||
|
itself. It has absolute and complete power over the
|
||||||
|
machine.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
To set up a stack, we set the esp register to point to the top of the
|
||||||
|
stack (as it grows downwards on x86 systems). This is necessarily done
|
||||||
|
in assembly as languages such as C cannot function without a stack.
|
||||||
|
*/
|
||||||
|
mov $stack_top, %esp
|
||||||
|
|
||||||
|
// store multiboot on stack
|
||||||
|
pushl %ebx
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is a good place to initialize crucial processor state before the
|
||||||
|
high-level kernel is entered. It's best to minimize the early
|
||||||
|
environment where crucial features are offline. Note that the
|
||||||
|
processor is not fully initialized yet: Features such as floating
|
||||||
|
point instructions and instruction set extensions are not initialized
|
||||||
|
yet. The GDT should be loaded here. Paging should be enabled here.
|
||||||
|
C++ features such as global constructors and exceptions will require
|
||||||
|
runtime support to work as well.
|
||||||
|
*/
|
||||||
|
cli
|
||||||
|
lgdt (gdtr)
|
||||||
|
ljmp $0x8, $continue_boot
|
||||||
|
|
||||||
|
continue_boot:
|
||||||
|
sti
|
||||||
|
/*
|
||||||
|
Enter the high-level kernel. The ABI requires the stack is 16-byte
|
||||||
|
aligned at the time of the call instruction (which afterwards pushes
|
||||||
|
the return pointer of size 4 bytes). The stack was originally 16-byte
|
||||||
|
aligned above and we've pushed a multiple of 16 bytes to the
|
||||||
|
stack since (pushed 0 bytes so far), so the alignment has thus been
|
||||||
|
preserved and the call is well defined.
|
||||||
|
*/
|
||||||
|
// top of stack is multiboot object
|
||||||
|
call kmain
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the system has nothing more to do, put the computer into an
|
||||||
|
infinite loop. To do that:
|
||||||
|
1) Disable interrupts with cli (clear interrupt enable in eflags).
|
||||||
|
They are already disabled by the bootloader, so this is not needed.
|
||||||
|
Mind that you might later enable interrupts and return from
|
||||||
|
kernel_main (which is sort of nonsensical to do).
|
||||||
|
2) Wait for the next interrupt to arrive with hlt (halt instruction).
|
||||||
|
Since they are disabled, this will lock up the computer.
|
||||||
|
3) Jump to the hlt instruction if it ever wakes up due to a
|
||||||
|
non-maskable interrupt occurring or due to system management mode.
|
||||||
|
*/
|
||||||
|
cli
|
||||||
|
1: #hlt
|
||||||
|
jmp 1b
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set the size of the _start symbol to the current location '.' minus its start.
|
||||||
|
This is useful when debugging or when you implement call tracing.
|
||||||
|
*/
|
||||||
|
.size _start, . - _start
|
||||||
39
boot/gdt.S
Normal file
39
boot/gdt.S
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
.section .data
|
||||||
|
gdt_start: # don't remove the labels, they're needed to compute sizes and jumps
|
||||||
|
# the GDT starts with a null 8-byte
|
||||||
|
.long 0x0 # 4 byte
|
||||||
|
.long 0x0 # 4 byte
|
||||||
|
|
||||||
|
# GDT for code segment. base = 0x00000000, length = 0xfffff
|
||||||
|
# for flags, refer to os-dev.pdf document, page 36
|
||||||
|
gdt_code:
|
||||||
|
.word 0xffff # segment length, bits 0-15
|
||||||
|
.word 0x0 # segment base, bits 0-15
|
||||||
|
.byte 0x0 # segment base, bits 16-23
|
||||||
|
.byte 0b10011010 # flags (8 bits)
|
||||||
|
.byte 0b11001111 # flags (4 bits) + segment length, bits 16-19
|
||||||
|
.byte 0x0 # segment base, bits 24-31
|
||||||
|
|
||||||
|
# GDT for data segment. base and length identical to code segment
|
||||||
|
# some flags changed, again, refer to os-dev.pdf
|
||||||
|
gdt_data:
|
||||||
|
.word 0xffff
|
||||||
|
.word 0x0
|
||||||
|
.byte 0x0
|
||||||
|
.byte 0b10010010
|
||||||
|
.byte 0b11001111
|
||||||
|
.byte 0x0
|
||||||
|
|
||||||
|
gdt_end:
|
||||||
|
|
||||||
|
# GDT descriptor
|
||||||
|
gdt_descriptor:
|
||||||
|
.long gdt_end-gdt_start-1
|
||||||
|
.long gdt_start
|
||||||
|
//MISMATCH: " dw gdt_end - gdt_start - 1 "
|
||||||
|
//MISMATCH: " dd gdt_start "
|
||||||
|
|
||||||
|
# define some constants for later use
|
||||||
|
code_seg: .long gdt_code - gdt_start
|
||||||
|
data_seg: .long gdt_data - gdt_start
|
||||||
|
|
||||||
23
kernel/cpu/idt.c
Normal file
23
kernel/cpu/idt.c
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 8/18/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "idt.h"
|
||||||
|
|
||||||
|
idt_gate_t idt[IDT_REGISTERS];
|
||||||
|
idt_register_t idt_reg;
|
||||||
|
|
||||||
|
void set_idt_gate(int n, u32 handler) {
|
||||||
|
idt[n].low_offset = handler & 0xffff;
|
||||||
|
idt[n].sel = KERNEL_CS;
|
||||||
|
idt[n].always0 = 0;
|
||||||
|
idt[n].flags = 0x8E;
|
||||||
|
idt[n].high_offset = handler >> 16 & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_idt() {
|
||||||
|
idt_reg.base = (u32) &idt;
|
||||||
|
idt_reg.limit = IDT_REGISTERS * sizeof(idt_gate_t) - 1;
|
||||||
|
|
||||||
|
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
|
||||||
|
}
|
||||||
35
kernel/cpu/idt.h
Normal file
35
kernel/cpu/idt.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 8/18/19.
|
||||||
|
//
|
||||||
|
#include "../types.h"
|
||||||
|
|
||||||
|
#ifndef MY_KERNEL_IDT_H
|
||||||
|
#define MY_KERNEL_IDT_H
|
||||||
|
#define KERNEL_CS 0x08
|
||||||
|
|
||||||
|
/* How every interrupt gate (handler) is defined */
|
||||||
|
typedef struct {
|
||||||
|
u16 low_offset; /* Lower 16 bits of handler function address */
|
||||||
|
u16 sel; /* Kernel segment selector */
|
||||||
|
u8 always0;
|
||||||
|
/* First byte
|
||||||
|
* Bit 7: "Interrupt is present"
|
||||||
|
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
|
||||||
|
* Bit 4: Set to 0 for interrupt gates
|
||||||
|
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
|
||||||
|
u8 flags;
|
||||||
|
u16 high_offset; /* Higher 16 bits of handler function address */
|
||||||
|
} __attribute__((packed)) idt_gate_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u16 limit;
|
||||||
|
u32 base;
|
||||||
|
} __attribute__((packed)) idt_register_t;
|
||||||
|
|
||||||
|
#define IDT_REGISTERS 256
|
||||||
|
|
||||||
|
void set_idt_gate(int n, u32 handler);
|
||||||
|
|
||||||
|
void set_idt();
|
||||||
|
|
||||||
|
#endif //MY_KERNEL_IDT_H
|
||||||
426
kernel/cpu/interrupt.S
Normal file
426
kernel/cpu/interrupt.S
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
.code32
|
||||||
|
# Defined in isr.c
|
||||||
|
#MISMATCH: "[extern isr_handler]"
|
||||||
|
#MISMATCH: "[extern irq_handler]"
|
||||||
|
|
||||||
|
# Common ISR code
|
||||||
|
isr_common_stub:
|
||||||
|
# 1. Save CPU state
|
||||||
|
pusha # Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
|
||||||
|
movw %ds,%ax # Lower 16-bits of eax = ds.
|
||||||
|
pushl %eax # save the data segment descriptor
|
||||||
|
movw $0x10,%ax # kernel data segment descriptor
|
||||||
|
movw %ax,%ds
|
||||||
|
movw %ax,%es
|
||||||
|
movw %ax,%fs
|
||||||
|
movw %ax,%gs
|
||||||
|
|
||||||
|
# 2. Call C handler
|
||||||
|
call isr_handler
|
||||||
|
|
||||||
|
# 3. Restore state
|
||||||
|
popl %eax
|
||||||
|
movw %ax,%ds
|
||||||
|
movw %ax,%es
|
||||||
|
movw %ax,%fs
|
||||||
|
movw %ax,%gs
|
||||||
|
popa
|
||||||
|
addl $8,%esp # Cleans up the pushed error code and pushed ISR number
|
||||||
|
sti
|
||||||
|
iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
||||||
|
|
||||||
|
# Common IRQ code. Identical to ISR code except for the 'call'
|
||||||
|
# and the 'pop ebx'
|
||||||
|
irq_common_stub:
|
||||||
|
pusha
|
||||||
|
movw %ds,%ax
|
||||||
|
pushl %eax
|
||||||
|
movw $0x10,%ax
|
||||||
|
movw %ax,%ds
|
||||||
|
movw %ax,%es
|
||||||
|
movw %ax,%fs
|
||||||
|
movw %ax,%gs
|
||||||
|
call irq_handler # Different than the ISR code
|
||||||
|
popl %ebx # Different than the ISR code
|
||||||
|
movw %bx,%ds
|
||||||
|
movw %bx,%es
|
||||||
|
movw %bx,%fs
|
||||||
|
movw %bx,%gs
|
||||||
|
popa
|
||||||
|
addl $8,%esp
|
||||||
|
sti
|
||||||
|
iret
|
||||||
|
|
||||||
|
# We don't get information about which interrupt was caller
|
||||||
|
# when the handler is run, so we will need to have a different handler
|
||||||
|
# for every interrupt.
|
||||||
|
# Furthermore, some interrupts push an error code onto the stack but others
|
||||||
|
# don't, so we will push a dummy error code for those which don't, so that
|
||||||
|
# we have a consistent stack for all of them.
|
||||||
|
|
||||||
|
# First make the ISRs global
|
||||||
|
.global isr0
|
||||||
|
.global isr1
|
||||||
|
.global isr2
|
||||||
|
.global isr3
|
||||||
|
.global isr4
|
||||||
|
.global isr5
|
||||||
|
.global isr6
|
||||||
|
.global isr7
|
||||||
|
.global isr8
|
||||||
|
.global isr9
|
||||||
|
.global isr10
|
||||||
|
.global isr11
|
||||||
|
.global isr12
|
||||||
|
.global isr13
|
||||||
|
.global isr14
|
||||||
|
.global isr15
|
||||||
|
.global isr16
|
||||||
|
.global isr17
|
||||||
|
.global isr18
|
||||||
|
.global isr19
|
||||||
|
.global isr20
|
||||||
|
.global isr21
|
||||||
|
.global isr22
|
||||||
|
.global isr23
|
||||||
|
.global isr24
|
||||||
|
.global isr25
|
||||||
|
.global isr26
|
||||||
|
.global isr27
|
||||||
|
.global isr28
|
||||||
|
.global isr29
|
||||||
|
.global isr30
|
||||||
|
.global isr31
|
||||||
|
|
||||||
|
.global irq0
|
||||||
|
.global irq1
|
||||||
|
.global irq2
|
||||||
|
.global irq3
|
||||||
|
.global irq4
|
||||||
|
.global irq5
|
||||||
|
.global irq6
|
||||||
|
.global irq7
|
||||||
|
.global irq8
|
||||||
|
.global irq9
|
||||||
|
.global irq10
|
||||||
|
.global irq11
|
||||||
|
.global irq12
|
||||||
|
.global irq13
|
||||||
|
.global irq14
|
||||||
|
.global irq15
|
||||||
|
|
||||||
|
# 0: Divide By Zero Exception
|
||||||
|
isr0:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $0
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 1: Debug Exception
|
||||||
|
isr1:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $1
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 2: Non Maskable Interrupt Exception
|
||||||
|
isr2:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $2
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 3: Int 3 Exception
|
||||||
|
isr3:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $3
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 4: INTO Exception
|
||||||
|
isr4:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $4
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 5: Out of Bounds Exception
|
||||||
|
isr5:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $5
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 6: Invalid Opcode Exception
|
||||||
|
isr6:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $6
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 7: Coprocessor Not Available Exception
|
||||||
|
isr7:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $7
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 8: Double Fault Exception (With Error Code!)
|
||||||
|
isr8:
|
||||||
|
cli
|
||||||
|
push $8
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 9: Coprocessor Segment Overrun Exception
|
||||||
|
isr9:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $9
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 10: Bad TSS Exception (With Error Code!)
|
||||||
|
isr10:
|
||||||
|
cli
|
||||||
|
push $10
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 11: Segment Not Present Exception (With Error Code!)
|
||||||
|
isr11:
|
||||||
|
cli
|
||||||
|
push $11
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 12: Stack Fault Exception (With Error Code!)
|
||||||
|
isr12:
|
||||||
|
cli
|
||||||
|
push $12
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 13: General Protection Fault Exception (With Error Code!)
|
||||||
|
isr13:
|
||||||
|
cli
|
||||||
|
push $13
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 14: Page Fault Exception (With Error Code!)
|
||||||
|
isr14:
|
||||||
|
cli
|
||||||
|
push $14
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 15: Reserved Exception
|
||||||
|
isr15:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $15
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 16: Floating Point Exception
|
||||||
|
isr16:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $16
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 17: Alignment Check Exception
|
||||||
|
isr17:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $17
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 18: Machine Check Exception
|
||||||
|
isr18:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $18
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 19: Reserved
|
||||||
|
isr19:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $19
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 20: Reserved
|
||||||
|
isr20:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $20
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 21: Reserved
|
||||||
|
isr21:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $21
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 22: Reserved
|
||||||
|
isr22:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $22
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 23: Reserved
|
||||||
|
isr23:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $23
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 24: Reserved
|
||||||
|
isr24:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $24
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 25: Reserved
|
||||||
|
isr25:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $25
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 26: Reserved
|
||||||
|
isr26:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $26
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 27: Reserved
|
||||||
|
isr27:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $27
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 28: Reserved
|
||||||
|
isr28:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $28
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 29: Reserved
|
||||||
|
isr29:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $29
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 30: Reserved
|
||||||
|
isr30:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $30
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# 31: Reserved
|
||||||
|
isr31:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $31
|
||||||
|
jmp isr_common_stub
|
||||||
|
|
||||||
|
# IRQ handlers
|
||||||
|
irq0:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $32
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq1:
|
||||||
|
cli
|
||||||
|
push $1
|
||||||
|
push $33
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq2:
|
||||||
|
cli
|
||||||
|
push $2
|
||||||
|
push $34
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq3:
|
||||||
|
cli
|
||||||
|
push $3
|
||||||
|
push $35
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq4:
|
||||||
|
cli
|
||||||
|
push $4
|
||||||
|
push $36
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq5:
|
||||||
|
cli
|
||||||
|
push $5
|
||||||
|
push $37
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq6:
|
||||||
|
cli
|
||||||
|
push $6
|
||||||
|
push $38
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq7:
|
||||||
|
cli
|
||||||
|
push $7
|
||||||
|
push $39
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq8:
|
||||||
|
cli
|
||||||
|
push $8
|
||||||
|
push $40
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq9:
|
||||||
|
cli
|
||||||
|
push $9
|
||||||
|
push $41
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq10:
|
||||||
|
cli
|
||||||
|
push $10
|
||||||
|
push $42
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq11:
|
||||||
|
cli
|
||||||
|
push $11
|
||||||
|
push $43
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq12:
|
||||||
|
cli
|
||||||
|
push $12
|
||||||
|
push $44
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq13:
|
||||||
|
cli
|
||||||
|
push $13
|
||||||
|
push $45
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq14:
|
||||||
|
cli
|
||||||
|
push $14
|
||||||
|
push $46
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
irq15:
|
||||||
|
cli
|
||||||
|
push $15
|
||||||
|
push $47
|
||||||
|
jmp irq_common_stub
|
||||||
|
|
||||||
144
kernel/cpu/isr.c
Normal file
144
kernel/cpu/isr.c
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 8/18/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "isr.h"
|
||||||
|
#include <kprint.h>
|
||||||
|
|
||||||
|
#include <cpu/idt.h>
|
||||||
|
#include <libc/libc.h>
|
||||||
|
#include <drivers/ports.h>
|
||||||
|
|
||||||
|
isr_t interrupt_handlers[256];
|
||||||
|
|
||||||
|
void isr_install() {
|
||||||
|
set_idt_gate(0, (u32) isr0);
|
||||||
|
set_idt_gate(1, (u32) isr1);
|
||||||
|
set_idt_gate(2, (u32) isr2);
|
||||||
|
set_idt_gate(3, (u32) isr3);
|
||||||
|
set_idt_gate(4, (u32) isr4);
|
||||||
|
set_idt_gate(5, (u32) isr5);
|
||||||
|
set_idt_gate(6, (u32) isr6);
|
||||||
|
set_idt_gate(7, (u32) isr7);
|
||||||
|
set_idt_gate(8, (u32) isr8);
|
||||||
|
set_idt_gate(9, (u32) isr9);
|
||||||
|
set_idt_gate(10, (u32) isr10);
|
||||||
|
set_idt_gate(11, (u32) isr11);
|
||||||
|
set_idt_gate(12, (u32) isr12);
|
||||||
|
set_idt_gate(13, (u32) isr13);
|
||||||
|
set_idt_gate(14, (u32) isr14);
|
||||||
|
set_idt_gate(15, (u32) isr15);
|
||||||
|
set_idt_gate(16, (u32) isr16);
|
||||||
|
set_idt_gate(17, (u32) isr17);
|
||||||
|
set_idt_gate(18, (u32) isr18);
|
||||||
|
set_idt_gate(19, (u32) isr19);
|
||||||
|
set_idt_gate(20, (u32) isr20);
|
||||||
|
set_idt_gate(21, (u32) isr21);
|
||||||
|
set_idt_gate(22, (u32) isr22);
|
||||||
|
set_idt_gate(23, (u32) isr23);
|
||||||
|
set_idt_gate(24, (u32) isr24);
|
||||||
|
set_idt_gate(25, (u32) isr25);
|
||||||
|
set_idt_gate(26, (u32) isr26);
|
||||||
|
set_idt_gate(27, (u32) isr27);
|
||||||
|
set_idt_gate(28, (u32) isr28);
|
||||||
|
set_idt_gate(29, (u32) isr29);
|
||||||
|
set_idt_gate(30, (u32) isr30);
|
||||||
|
set_idt_gate(31, (u32) isr31);
|
||||||
|
|
||||||
|
// Remap the PIC
|
||||||
|
port_byte_out(0x20, 0x11);
|
||||||
|
port_byte_out(0xA0, 0x11);
|
||||||
|
port_byte_out(0x21, 0x20);
|
||||||
|
port_byte_out(0xA1, 0x28);
|
||||||
|
port_byte_out(0x21, 0x04);
|
||||||
|
port_byte_out(0xA1, 0x02);
|
||||||
|
port_byte_out(0x21, 0x01);
|
||||||
|
port_byte_out(0xA1, 0x01);
|
||||||
|
port_byte_out(0x21, 0x0);
|
||||||
|
port_byte_out(0xA1, 0x0);
|
||||||
|
|
||||||
|
// Install the IRQs
|
||||||
|
set_idt_gate(32, (u32) irq0);
|
||||||
|
set_idt_gate(33, (u32) irq1);
|
||||||
|
set_idt_gate(34, (u32) irq2);
|
||||||
|
set_idt_gate(35, (u32) irq3);
|
||||||
|
set_idt_gate(36, (u32) irq4);
|
||||||
|
set_idt_gate(37, (u32) irq5);
|
||||||
|
set_idt_gate(38, (u32) irq6);
|
||||||
|
set_idt_gate(39, (u32) irq7);
|
||||||
|
set_idt_gate(40, (u32) irq8);
|
||||||
|
set_idt_gate(41, (u32) irq9);
|
||||||
|
set_idt_gate(42, (u32) irq10);
|
||||||
|
set_idt_gate(43, (u32) irq11);
|
||||||
|
set_idt_gate(44, (u32) irq12);
|
||||||
|
set_idt_gate(45, (u32) irq13);
|
||||||
|
set_idt_gate(46, (u32) irq14);
|
||||||
|
set_idt_gate(47, (u32) irq15);
|
||||||
|
|
||||||
|
set_idt(); // Load with ASM
|
||||||
|
}
|
||||||
|
|
||||||
|
char *exception_messages[] = {
|
||||||
|
"Division By Zero",
|
||||||
|
"Debug",
|
||||||
|
"Non Maskable Interrupt",
|
||||||
|
"Breakpoint",
|
||||||
|
"Into Detected Overflow",
|
||||||
|
"Out of Bounds",
|
||||||
|
"Invalid Opcode",
|
||||||
|
"No Coprocessor",
|
||||||
|
|
||||||
|
"Double Fault",
|
||||||
|
"Coprocessor Segment Overrun",
|
||||||
|
"Bad TSS",
|
||||||
|
"Segment Not Present",
|
||||||
|
"Stack Fault",
|
||||||
|
"General Protection Fault",
|
||||||
|
"Page Fault",
|
||||||
|
"Unknown Interrupt",
|
||||||
|
|
||||||
|
"Coprocessor Fault",
|
||||||
|
"Alignment Check",
|
||||||
|
"Machine Check",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved"
|
||||||
|
};
|
||||||
|
|
||||||
|
void isr_handler(registers_t r) {
|
||||||
|
kprint("received interrupt: ");
|
||||||
|
char s[3];
|
||||||
|
itoa(r.int_no, s);
|
||||||
|
kprint(s);
|
||||||
|
kprint("\n");
|
||||||
|
kprint(exception_messages[r.int_no]);
|
||||||
|
kprint("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_interrupt_handler(u8 n, isr_t handler) {
|
||||||
|
interrupt_handlers[n] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void irq_handler(registers_t r) {
|
||||||
|
/* After every interrupt we need to send an EOI to the PICs
|
||||||
|
* or they will not send another interrupt again */
|
||||||
|
if (r.int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */
|
||||||
|
port_byte_out(0x20, 0x20); /* master */
|
||||||
|
|
||||||
|
/* Handle the interrupt in a more modular way */
|
||||||
|
if (interrupt_handlers[r.int_no] != 0) {
|
||||||
|
isr_t handler = interrupt_handlers[r.int_no];
|
||||||
|
handler(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
140
kernel/cpu/isr.h
Normal file
140
kernel/cpu/isr.h
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 8/18/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "../types.h"
|
||||||
|
|
||||||
|
#ifndef MY_KERNEL_ISR_H
|
||||||
|
#define MY_KERNEL_ISR_H
|
||||||
|
|
||||||
|
/* ISRs reserved for CPU exceptions */
|
||||||
|
extern void isr0();
|
||||||
|
|
||||||
|
extern void isr1();
|
||||||
|
|
||||||
|
extern void isr2();
|
||||||
|
|
||||||
|
extern void isr3();
|
||||||
|
|
||||||
|
extern void isr4();
|
||||||
|
|
||||||
|
extern void isr5();
|
||||||
|
|
||||||
|
extern void isr6();
|
||||||
|
|
||||||
|
extern void isr7();
|
||||||
|
|
||||||
|
extern void isr8();
|
||||||
|
|
||||||
|
extern void isr9();
|
||||||
|
|
||||||
|
extern void isr10();
|
||||||
|
|
||||||
|
extern void isr11();
|
||||||
|
|
||||||
|
extern void isr12();
|
||||||
|
|
||||||
|
extern void isr13();
|
||||||
|
|
||||||
|
extern void isr14();
|
||||||
|
|
||||||
|
extern void isr15();
|
||||||
|
|
||||||
|
extern void isr16();
|
||||||
|
|
||||||
|
extern void isr17();
|
||||||
|
|
||||||
|
extern void isr18();
|
||||||
|
|
||||||
|
extern void isr19();
|
||||||
|
|
||||||
|
extern void isr20();
|
||||||
|
|
||||||
|
extern void isr21();
|
||||||
|
|
||||||
|
extern void isr22();
|
||||||
|
|
||||||
|
extern void isr23();
|
||||||
|
|
||||||
|
extern void isr24();
|
||||||
|
|
||||||
|
extern void isr25();
|
||||||
|
|
||||||
|
extern void isr26();
|
||||||
|
|
||||||
|
extern void isr27();
|
||||||
|
|
||||||
|
extern void isr28();
|
||||||
|
|
||||||
|
extern void isr29();
|
||||||
|
|
||||||
|
extern void isr30();
|
||||||
|
|
||||||
|
extern void isr31();
|
||||||
|
|
||||||
|
/* IRQ definitions */
|
||||||
|
extern void irq0();
|
||||||
|
|
||||||
|
extern void irq1();
|
||||||
|
|
||||||
|
extern void irq2();
|
||||||
|
|
||||||
|
extern void irq3();
|
||||||
|
|
||||||
|
extern void irq4();
|
||||||
|
|
||||||
|
extern void irq5();
|
||||||
|
|
||||||
|
extern void irq6();
|
||||||
|
|
||||||
|
extern void irq7();
|
||||||
|
|
||||||
|
extern void irq8();
|
||||||
|
|
||||||
|
extern void irq9();
|
||||||
|
|
||||||
|
extern void irq10();
|
||||||
|
|
||||||
|
extern void irq11();
|
||||||
|
|
||||||
|
extern void irq12();
|
||||||
|
|
||||||
|
extern void irq13();
|
||||||
|
|
||||||
|
extern void irq14();
|
||||||
|
|
||||||
|
extern void irq15();
|
||||||
|
|
||||||
|
#define IRQ0 32
|
||||||
|
#define IRQ1 33
|
||||||
|
#define IRQ2 34
|
||||||
|
#define IRQ3 35
|
||||||
|
#define IRQ4 36
|
||||||
|
#define IRQ5 37
|
||||||
|
#define IRQ6 38
|
||||||
|
#define IRQ7 39
|
||||||
|
#define IRQ8 40
|
||||||
|
#define IRQ9 41
|
||||||
|
#define IRQ10 42
|
||||||
|
#define IRQ11 43
|
||||||
|
#define IRQ12 44
|
||||||
|
#define IRQ13 45
|
||||||
|
#define IRQ14 46
|
||||||
|
#define IRQ15 47
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 ds;
|
||||||
|
u32 edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||||
|
u32 int_no, err_code;
|
||||||
|
u32 eip, cs, eflags, useresp, ss;
|
||||||
|
} registers_t;
|
||||||
|
|
||||||
|
typedef void (*isr_t)(registers_t);
|
||||||
|
|
||||||
|
void register_interrupt_handler(u8 n, isr_t handler);
|
||||||
|
|
||||||
|
void isr_install();
|
||||||
|
|
||||||
|
void isr_handler(registers_t r);
|
||||||
|
|
||||||
|
#endif //MY_KERNEL_ISR_H
|
||||||
26
kernel/cpu/timer.c
Normal file
26
kernel/cpu/timer.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 9/22/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
#include <drivers/ports.h>
|
||||||
|
#include <cpu/isr.h>
|
||||||
|
|
||||||
|
u32 tick = 0;
|
||||||
|
|
||||||
|
static void timer_callback(registers_t regs) {
|
||||||
|
tick++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int init_timer(u32 freq) {
|
||||||
|
register_interrupt_handler(IRQ0, timer_callback);
|
||||||
|
|
||||||
|
u32 divisor = 1193180 / freq;
|
||||||
|
u8 low = (u8) (divisor & 0xFF);
|
||||||
|
u8 high = (u8) ((divisor >> 8) & 0xFF);
|
||||||
|
port_byte_out(PORT_PIT_COMMAND, PIT_MODE_BIN | PIT_MODE_SQUARE_WAVE | PIT_ACCESS_MODE_HL | PIT_CHANNEL_0);
|
||||||
|
port_byte_out(PORT_PIT_DATA_0, low);
|
||||||
|
port_byte_out(PORT_PIT_DATA_0, high);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
12
kernel/cpu/timer.h
Normal file
12
kernel/cpu/timer.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 9/22/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MY_KERNEL_TIMER_H
|
||||||
|
#define MY_KERNEL_TIMER_H
|
||||||
|
|
||||||
|
#include "../types.h"
|
||||||
|
|
||||||
|
int init_timer(u32 freq);
|
||||||
|
|
||||||
|
#endif //MY_KERNEL_TIMER_H
|
||||||
70
kernel/drivers/keyboard.c
Normal file
70
kernel/drivers/keyboard.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 23-03-20.
|
||||||
|
//
|
||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
#include <kprint.h>
|
||||||
|
#include <drivers/ports.h>
|
||||||
|
#include <cpu/isr.h>
|
||||||
|
#include <libc/libc.h>
|
||||||
|
|
||||||
|
char scancodes_ascii[] = {
|
||||||
|
0, 0,
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0,
|
||||||
|
0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0,
|
||||||
|
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
|
||||||
|
0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,
|
||||||
|
'*',
|
||||||
|
0, ' ',
|
||||||
|
0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1-F10
|
||||||
|
0, 0,
|
||||||
|
'7', '8', '9', '-',
|
||||||
|
'4', '5', '6', '+',
|
||||||
|
'1', '2', '3',
|
||||||
|
'0', 0,
|
||||||
|
0, // sysrq
|
||||||
|
0, 0, // weird
|
||||||
|
0, 0, // F11 F12
|
||||||
|
// weid
|
||||||
|
};
|
||||||
|
|
||||||
|
char *MSG_KEY = "Clicked on key 'x'\n";
|
||||||
|
|
||||||
|
void print_scancode(unsigned char scancode);
|
||||||
|
|
||||||
|
static void keyboard_callback(registers_t regs) {
|
||||||
|
unsigned char status = port_byte_in(PORT_PS2_STATUS);
|
||||||
|
// check if data available
|
||||||
|
if ((status & 0b00000001) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned char scancode = port_byte_in(0x60);
|
||||||
|
print_scancode(scancode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_keyboard() {
|
||||||
|
register_interrupt_handler(IRQ1, keyboard_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_scancode(unsigned char scancode) {
|
||||||
|
char msg[256];
|
||||||
|
char release = 0;
|
||||||
|
if (scancode > 0x80) {
|
||||||
|
// release
|
||||||
|
release = 1;
|
||||||
|
scancode -= 0x80;
|
||||||
|
}
|
||||||
|
char code = scancodes_ascii[scancode];
|
||||||
|
if (code == 0) {
|
||||||
|
// special
|
||||||
|
} else {
|
||||||
|
if (release && code > 0x60 && code < 0x7B) {
|
||||||
|
code -= 0x20; // to lowercase
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(msg, MSG_KEY, strlen(MSG_KEY));
|
||||||
|
msg[strlen(msg) - 3] = code;
|
||||||
|
kprint(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
kernel/drivers/keyboard.h
Normal file
10
kernel/drivers/keyboard.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 23-03-20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MY_KERNEL_KEYBOARD_H
|
||||||
|
#define MY_KERNEL_KEYBOARD_H
|
||||||
|
|
||||||
|
void init_keyboard();
|
||||||
|
|
||||||
|
#endif //MY_KERNEL_KEYBOARD_H
|
||||||
33
kernel/drivers/ports.c
Normal file
33
kernel/drivers/ports.c
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* ports.c
|
||||||
|
*
|
||||||
|
* Created on: Aug 18, 2019
|
||||||
|
* Author: rick
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ports.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a byte from the specified port
|
||||||
|
*/
|
||||||
|
unsigned char port_byte_in(unsigned short port) {
|
||||||
|
unsigned char result;
|
||||||
|
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void port_byte_out(unsigned short port, unsigned char data) {
|
||||||
|
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short port_word_in(unsigned short port) {
|
||||||
|
unsigned short result;
|
||||||
|
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_wordt_out(unsigned short port, unsigned short data) {
|
||||||
|
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
|
||||||
|
}
|
||||||
51
kernel/drivers/ports.h
Normal file
51
kernel/drivers/ports.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef MY_KERNEL_DRIVERS_PORT_H
|
||||||
|
#define MY_KERNEL_DRIVERS_PORT_H
|
||||||
|
|
||||||
|
//http://www.osdever.net/FreeVGA/vga/crtcreg.htm#0A
|
||||||
|
#define PORT_REG_SCREEN_CTRL 0x3d4
|
||||||
|
#define PORT_REG_SCREEN_CTRL_CURSOR_H 0x0E
|
||||||
|
#define PORT_REG_SCREEN_CTRL_CURSOR_L 0x0F
|
||||||
|
#define PORT_REG_SCREEN_DATA 0x3d5
|
||||||
|
|
||||||
|
// https://wiki.osdev.org/Serial_Ports
|
||||||
|
#define PORT_SERIAL_0 0x3f8
|
||||||
|
#define PORT_SERIAL_1 0x2f8
|
||||||
|
#define PORT_SERIAL_2 0x3e8
|
||||||
|
#define PORT_SERIAL_3 0x2e8
|
||||||
|
|
||||||
|
#define PORT_SERIAL_DATA 0
|
||||||
|
#define PORT_SERIAL_INTERRUPT 1
|
||||||
|
#define PORT_SERIAL_DLAB_LSB 0
|
||||||
|
#define PORT_SERIAL_DLAB_MSB 1
|
||||||
|
#define PORT_SERIAL_INTERRUPT_ID_FIFO 2
|
||||||
|
#define PORT_SERIAL_LINE_CONTROL 3
|
||||||
|
#define PORT_SERIAL_MODEM_CONTROL 4
|
||||||
|
#define PORT_SERIAL_LINE_STATUS 5
|
||||||
|
#define PORT_SERIAL_MODEM_STATUS 6
|
||||||
|
#define PORT_SERIAL_SCRATCH 6
|
||||||
|
|
||||||
|
// https://wiki.osdev.org/PIT
|
||||||
|
#define PORT_PIT_COMMAND 0x43
|
||||||
|
#define PIT_MODE_BIN 0x0
|
||||||
|
#define PIT_MODE_HW_STROBE 0b0101
|
||||||
|
#define PIT_MODE_SQUARE_WAVE 0b0110
|
||||||
|
#define PIT_ACCESS_MODE_HL 0b000011
|
||||||
|
#define PIT_CHANNEL_0 0b00000000
|
||||||
|
#define PORT_PIT_DATA_0 0x40
|
||||||
|
#define PORT_PIT_DATA_1 0x41
|
||||||
|
#define PORT_PIT_DATA_3 0x42
|
||||||
|
|
||||||
|
// https://wiki.osdev.org/%228042%22_PS/2_Controller
|
||||||
|
#define PORT_PS2_DATA 0x60
|
||||||
|
#define PORT_PS2_STATUS 0x64
|
||||||
|
#define PORT_PS2_COMMAND 0x64
|
||||||
|
|
||||||
|
unsigned char port_byte_in(unsigned short port);
|
||||||
|
|
||||||
|
void port_byte_out(unsigned short port, unsigned char data);
|
||||||
|
|
||||||
|
unsigned short port_word_in(unsigned short port);
|
||||||
|
|
||||||
|
void port_word_out(unsigned short port, unsigned short data);
|
||||||
|
|
||||||
|
#endif
|
||||||
56
kernel/drivers/serial.c
Normal file
56
kernel/drivers/serial.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 28-01-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "serial.h"
|
||||||
|
#include <types.h>
|
||||||
|
#include <drivers/ports.h>
|
||||||
|
|
||||||
|
int serial_init() {
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_INTERRUPT, 0x00); // Disable all interrupts
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL, 0x80); // Enable DLAB (set baud rate divisor)
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DLAB_LSB, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DLAB_MSB, 0x00); // (hi byte)
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL, 0x03); // 8 bits, no parity, one stop bit
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_INTERRUPT_ID_FIFO,
|
||||||
|
0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x0B); // IRQs enabled, RTS/DSR set
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x1E); // Set in loopback mode, test the serial chip
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DATA,
|
||||||
|
0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||||
|
|
||||||
|
// Check if serial is faulty (i.e: not same byte as sent)
|
||||||
|
if (port_byte_in(PORT_SERIAL_0 + PORT_SERIAL_DATA) != 0xAE) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If serial is not faulty set it in normal operation mode
|
||||||
|
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x0F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_transmit_empty() {
|
||||||
|
return port_byte_in(PORT_SERIAL_0 + PORT_SERIAL_LINE_STATUS) & 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_serial(char a) {
|
||||||
|
while (is_transmit_empty() == 0);
|
||||||
|
|
||||||
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DATA, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_kprint(char *msg) {
|
||||||
|
u32 i = 0;
|
||||||
|
while (1) {
|
||||||
|
char c = msg[i];
|
||||||
|
if (c == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == '\n') {
|
||||||
|
write_serial('\r');
|
||||||
|
}
|
||||||
|
write_serial(c);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
kernel/drivers/serial.h
Normal file
12
kernel/drivers/serial.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 28-01-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_SERIAL_H
|
||||||
|
#define NEW_KERNEL_SERIAL_H
|
||||||
|
|
||||||
|
int serial_init();
|
||||||
|
|
||||||
|
void serial_kprint(char *msg);
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_SERIAL_H
|
||||||
122
kernel/drivers/vgascreen.c
Normal file
122
kernel/drivers/vgascreen.c
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 8/18/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "vgascreen.h"
|
||||||
|
|
||||||
|
#include <libc/libc.h>
|
||||||
|
#include <drivers/ports.h>
|
||||||
|
|
||||||
|
char *_vga_character_memory = (char *) VGA_CHARACTER_MEMORY_LOCATION;
|
||||||
|
|
||||||
|
int get_offset(int col, int row);
|
||||||
|
|
||||||
|
int get_cursor_offset();
|
||||||
|
|
||||||
|
void set_cursor_offset(int offset);
|
||||||
|
|
||||||
|
int get_offset_row(int offset);
|
||||||
|
|
||||||
|
int get_offset_col(int offset);
|
||||||
|
|
||||||
|
int print_char(char character, int col, int row, char attributes);
|
||||||
|
|
||||||
|
|
||||||
|
void vga_clear_screen() {
|
||||||
|
int size = VGA_COL_MAX * VGA_ROW_MAX;
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
_vga_character_memory[i * 2] = ' ';
|
||||||
|
_vga_character_memory[i * 2 + 1] = VGA_WHITE | (VGA_BLACK << VGA_SHIFT_BG);
|
||||||
|
}
|
||||||
|
set_cursor_offset(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kprint_at(char *message, int col, int row) {
|
||||||
|
int offset;
|
||||||
|
if (col > 0 && row > 0) {
|
||||||
|
offset = get_offset(col, row);
|
||||||
|
} else {
|
||||||
|
offset = get_cursor_offset();
|
||||||
|
row = get_offset_row(offset);
|
||||||
|
col = get_offset_col(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (message[i] != 0) {
|
||||||
|
offset = print_char(message[i++], col, row, VGA_WHITE | (VGA_BLACK << VGA_SHIFT_BG));
|
||||||
|
row = get_offset_row(offset);
|
||||||
|
col = get_offset_col(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vga_kprint(char *message) {
|
||||||
|
kprint_at(message, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_char(char character, int col, int row, char attributes) {
|
||||||
|
if (!attributes) attributes = VGA_WHITE | (VGA_BLACK < VGA_SHIFT_BG);
|
||||||
|
|
||||||
|
if (col >= VGA_COL_MAX || row > +VGA_ROW_MAX) {
|
||||||
|
_vga_character_memory[2 * (VGA_COL_MAX) * (VGA_ROW_MAX) - 2] = 'E';
|
||||||
|
_vga_character_memory[2 * (VGA_COL_MAX) * (VGA_ROW_MAX) - 1] = VGA_RED | (VGA_WHITE < VGA_SHIFT_BG);
|
||||||
|
return get_offset(col, row);
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset;
|
||||||
|
if (col >= 0 && row >= 0) {
|
||||||
|
offset = get_offset(col, row);
|
||||||
|
} else {
|
||||||
|
offset = get_cursor_offset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character == '\n') {
|
||||||
|
row = get_offset_row(offset);
|
||||||
|
offset = get_offset(0, row + 1);
|
||||||
|
} else {
|
||||||
|
_vga_character_memory[offset] = character;
|
||||||
|
_vga_character_memory[offset + 1] = attributes;
|
||||||
|
offset += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset >= (VGA_COL_MAX * 2 * VGA_ROW_MAX)) {
|
||||||
|
memcpy(_vga_character_memory,
|
||||||
|
_vga_character_memory + (VGA_COL_MAX * 2),
|
||||||
|
(2 * VGA_COL_MAX * VGA_ROW_MAX) - (2 * VGA_COL_MAX));
|
||||||
|
for (int i = 0; i < VGA_COL_MAX; ++i) {
|
||||||
|
_vga_character_memory[get_offset(i, VGA_ROW_MAX - 1)] = ' ';
|
||||||
|
}
|
||||||
|
offset = get_offset(0, VGA_ROW_MAX - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_cursor_offset(offset);
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_cursor_offset() {
|
||||||
|
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_H);
|
||||||
|
int offset = ((int) port_byte_in(PORT_REG_SCREEN_DATA)) << 8;
|
||||||
|
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_L);
|
||||||
|
offset += port_byte_in(PORT_REG_SCREEN_DATA);
|
||||||
|
return offset * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_cursor_offset(int offset) {
|
||||||
|
offset /= 2;
|
||||||
|
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_L);
|
||||||
|
port_byte_out(PORT_REG_SCREEN_DATA, (unsigned char) (offset & 0xFF));
|
||||||
|
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_H);
|
||||||
|
port_byte_out(PORT_REG_SCREEN_DATA, (unsigned char) (offset >> 8) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_offset(int col, int row) {
|
||||||
|
return (row * VGA_COL_MAX + col) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_offset_row(int offset) {
|
||||||
|
return offset / (VGA_COL_MAX * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_offset_col(int offset) {
|
||||||
|
return (offset - (get_offset_row(offset) * 2 * VGA_COL_MAX)) / 2;
|
||||||
|
}
|
||||||
34
kernel/drivers/vgascreen.h
Normal file
34
kernel/drivers/vgascreen.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 8/18/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MY_KERNEL_DRIVERS_VGASCREEN_H
|
||||||
|
#define MY_KERNEL_DRIVERS_VGASCREEN_H
|
||||||
|
#define VGA_CHARACTER_MEMORY_LOCATION 0xb8000
|
||||||
|
|
||||||
|
#define VGA_BLACK 0x0
|
||||||
|
#define VGA_BLUE 0x1
|
||||||
|
#define VGA_GREEN 0x2
|
||||||
|
#define VGA_CIAN 0x3
|
||||||
|
#define VGA_RED 0x4
|
||||||
|
#define VGA_PURPLE 0x5
|
||||||
|
#define VGA_ORANGE 0x6
|
||||||
|
#define VGA_GRAY 0x7
|
||||||
|
#define VGA_DARK_GRAY 0x8
|
||||||
|
#define VGA_LIGHT_BLUE 0x9
|
||||||
|
#define VGA_LIGHT_GREEN 0xA
|
||||||
|
#define VGA_LIGHT_RED 0xB
|
||||||
|
#define VGA_PINK 0xD
|
||||||
|
#define VGA_YELLOW 0xE
|
||||||
|
#define VGA_WHITE 0xF
|
||||||
|
#define VGA_SHIFT_BG 4
|
||||||
|
#define VGA_BLINK 0x80
|
||||||
|
|
||||||
|
#define VGA_COL_MAX 80
|
||||||
|
#define VGA_ROW_MAX 25
|
||||||
|
|
||||||
|
void vga_clear_screen();
|
||||||
|
|
||||||
|
void vga_kprint(char *msg);
|
||||||
|
|
||||||
|
#endif //MY_KERNEL_VGASCREEN_H
|
||||||
46
kernel/kernel.c
Normal file
46
kernel/kernel.c
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include <drivers/ports.h>
|
||||||
|
#include <drivers/vgascreen.h>
|
||||||
|
#include <libc/libc.h>
|
||||||
|
#include <cpu/isr.h>
|
||||||
|
#include <cpu/timer.h>
|
||||||
|
#include <drivers/keyboard.h>
|
||||||
|
#include <mem/mem.h>
|
||||||
|
#include <multiboot.h>
|
||||||
|
#include <drivers/serial.h>
|
||||||
|
#include "kprint.h"
|
||||||
|
|
||||||
|
char *msg_booted = "Booted Successfully!\n";
|
||||||
|
|
||||||
|
|
||||||
|
void kmain(multiboot_info_t *multiboot_info) {
|
||||||
|
isr_install();
|
||||||
|
init_mmap((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
|
||||||
|
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
|
||||||
|
vga_clear_screen();
|
||||||
|
vga_clear_screen(' ', VGA_WHITE | (VGA_GRAY << VGA_SHIFT_BG));
|
||||||
|
kprint_register(vga_kprint);
|
||||||
|
serial_init();
|
||||||
|
kprint_register(serial_kprint);
|
||||||
|
|
||||||
|
// vga_print_string(msg_booted, VGA_WHITE | (VGA_DARK_GRAY << VGA_SHIFT_BG));
|
||||||
|
kprint(msg_booted);
|
||||||
|
kprint((char *) multiboot_info->boot_loader_name);
|
||||||
|
multiboot_memory_map_t *fe = multiboot_info->mmap_addr;
|
||||||
|
|
||||||
|
// port_byte_out(0x3d4, 14);
|
||||||
|
// int pos = port_byte_in(0x3d5);
|
||||||
|
// pos <<= 8;
|
||||||
|
//
|
||||||
|
// port_byte_out(0x3d4, 15);
|
||||||
|
// pos += port_byte_in(0x3d5);
|
||||||
|
|
||||||
|
asm volatile("sti");
|
||||||
|
init_timer(50);
|
||||||
|
init_keyboard();
|
||||||
|
|
||||||
|
print_mmap_info();
|
||||||
|
|
||||||
|
// vga_set_raw(pos * 2, 'X');
|
||||||
|
// vga_set_raw(pos * 2 + 1, 0xf);
|
||||||
|
do {} while (1);
|
||||||
|
}
|
||||||
37
kernel/kprint.c
Normal file
37
kernel/kprint.c
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 28-01-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "kprint.h"
|
||||||
|
|
||||||
|
#define MAX_HANDLERS 8
|
||||||
|
|
||||||
|
kprint_handler handlers[MAX_HANDLERS] = {
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
void kprint_register(kprint_handler handler) {
|
||||||
|
for (int i = 0; i < MAX_HANDLERS; ++i) {
|
||||||
|
if (handlers[i] == NULL) {
|
||||||
|
handlers[i] = handler;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// todo handle
|
||||||
|
}
|
||||||
|
|
||||||
|
void kprint(char *msg) {
|
||||||
|
for (int i = 0; i < MAX_HANDLERS; ++i) {
|
||||||
|
if (handlers[i] == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
handlers[i](msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
kernel/kprint.h
Normal file
16
kernel/kprint.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 28-01-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_KPRINT_H
|
||||||
|
#define NEW_KERNEL_KPRINT_H
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_KPRINT_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef void (*kprint_handler)(char *);
|
||||||
|
|
||||||
|
void kprint_register(kprint_handler);
|
||||||
|
|
||||||
|
void kprint(char *msg);
|
||||||
40
kernel/libc/libc.c
Normal file
40
kernel/libc/libc.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* libc.c
|
||||||
|
*
|
||||||
|
* Created on: Oct 11, 2018
|
||||||
|
* Author: rick
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libc.h"
|
||||||
|
|
||||||
|
int memcpy(char *dst, char *src, int amount) {
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
dst[i] = src[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memset(char *dst, char data, int amount) {
|
||||||
|
for (int i = 0; i < amount; ++i) {
|
||||||
|
dst[i] = data;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int itoa(int i, char *target) {
|
||||||
|
target[0] = (char) (i % 10 + '0');
|
||||||
|
target[1] = '\0';
|
||||||
|
if (i > 9) {
|
||||||
|
itoa(i / 10, target + 1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strlen(char *str) {
|
||||||
|
int length = 0;
|
||||||
|
while (str[length] != 0) {
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
19
kernel/libc/libc.h
Normal file
19
kernel/libc/libc.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* libc.h
|
||||||
|
*
|
||||||
|
* Created on: Oct 11, 2018
|
||||||
|
* Author: rick
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KERNEL_LIBC_LIBC_H_
|
||||||
|
#define KERNEL_LIBC_LIBC_H_
|
||||||
|
|
||||||
|
int memcpy(char *dst, char *src, int amount);
|
||||||
|
|
||||||
|
int memset(char *dst, char data, int amount);
|
||||||
|
|
||||||
|
int itoa(int i, char *target);
|
||||||
|
|
||||||
|
int strlen(char *str);
|
||||||
|
|
||||||
|
#endif /* KERNEL_LIBC_LIBC_H_ */
|
||||||
88
kernel/mem/mem.c
Normal file
88
kernel/mem/mem.c
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 22-04-20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <kprint.h>
|
||||||
|
#include <mem/mem.h>
|
||||||
|
#include <libc/libc.h>
|
||||||
|
|
||||||
|
char *msg_index = "Idx: ";
|
||||||
|
char *msg_addr = "Address: ";
|
||||||
|
char *msg_len = "Length: ";
|
||||||
|
char *msg_type = "Type: ";
|
||||||
|
char *msg_nl = "\n";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u64 address;
|
||||||
|
u64 length;
|
||||||
|
#define MMAP_TYPE_UNDEFINED 0
|
||||||
|
#define MMAP_TYPE_AVAILABLE 1
|
||||||
|
#define MMAP_TYPE_RESERVED 2
|
||||||
|
#define MMAP_TYPE_ACPI_RECLAIMABLE 3
|
||||||
|
#define MMAP_TYPE_NVS 4
|
||||||
|
#define MMAP_TYPE_BADRAM 5
|
||||||
|
u32 type;
|
||||||
|
} __attribute((packed)) mmap_entry;
|
||||||
|
|
||||||
|
char *msg_lu = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
mmap_entry memmap[16] = {
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
void init_mmap(struct multiboot_mmap_entry *entries, u32 count) {
|
||||||
|
for (u32 i = 0; i < count; ++i) {
|
||||||
|
memmap[i].address = entries[i].addr;
|
||||||
|
memmap[i].length = entries[i].len;
|
||||||
|
memmap[i].type = entries[i].type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_hex_u64(u64 input) {
|
||||||
|
char msg[18] = "0x0000000000000000";
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
int val = input >> (4 * i) & 0xF;
|
||||||
|
msg[17 - i] = msg_lu[val];
|
||||||
|
}
|
||||||
|
kprint(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_mmap_info() {
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
if (memmap[i].type == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char *tmp_str = " ";
|
||||||
|
kprint(msg_index);
|
||||||
|
itoa(i, tmp_str);
|
||||||
|
kprint(tmp_str);
|
||||||
|
kprint(msg_nl);
|
||||||
|
kprint(msg_addr);
|
||||||
|
print_hex_u64(memmap[i].address);
|
||||||
|
kprint(msg_nl);
|
||||||
|
kprint(msg_len);
|
||||||
|
print_hex_u64(memmap[i].length);
|
||||||
|
kprint(msg_nl);
|
||||||
|
kprint(msg_type);
|
||||||
|
itoa(memmap[i].type, tmp_str);
|
||||||
|
kprint(tmp_str);
|
||||||
|
kprint(msg_nl);
|
||||||
|
kprint(msg_nl);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
kernel/mem/mem.h
Normal file
14
kernel/mem/mem.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 22-04-20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_MEM_H
|
||||||
|
#define NEW_KERNEL_MEM_H
|
||||||
|
|
||||||
|
#include <multiboot.h>
|
||||||
|
|
||||||
|
void init_mmap(struct multiboot_mmap_entry *entries, u32 count);
|
||||||
|
|
||||||
|
void print_mmap_info();
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_MEM_H
|
||||||
262
kernel/multiboot.h
Normal file
262
kernel/multiboot.h
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
//* multiboot.h - Multiboot header file. */
|
||||||
|
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
|
||||||
|
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||||
|
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MULTIBOOT_HEADER
|
||||||
|
#define MULTIBOOT_HEADER 1
|
||||||
|
|
||||||
|
/* How many bytes from the start of the file we search for the header. */
|
||||||
|
#define MULTIBOOT_SEARCH 8192
|
||||||
|
#define MULTIBOOT_HEADER_ALIGN 4
|
||||||
|
|
||||||
|
/* The magic field should contain this. */
|
||||||
|
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
||||||
|
|
||||||
|
/* This should be in %eax. */
|
||||||
|
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
|
||||||
|
|
||||||
|
/* Alignment of multiboot modules. */
|
||||||
|
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||||
|
|
||||||
|
/* Alignment of the multiboot info structure. */
|
||||||
|
#define MULTIBOOT_INFO_ALIGN 0x00000004
|
||||||
|
|
||||||
|
/* Flags set in the ’flags’ member of the multiboot header. */
|
||||||
|
|
||||||
|
/* Align all boot modules on i386 page (4KB) boundaries. */
|
||||||
|
#define MULTIBOOT_PAGE_ALIGN 0x00000001
|
||||||
|
|
||||||
|
/* Must pass memory information to OS. */
|
||||||
|
#define MULTIBOOT_MEMORY_INFO 0x00000002
|
||||||
|
|
||||||
|
/* Must pass video information to OS. */
|
||||||
|
#define MULTIBOOT_VIDEO_MODE 0x00000004
|
||||||
|
|
||||||
|
/* This flag indicates the use of the address fields in the header. */
|
||||||
|
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
|
||||||
|
|
||||||
|
/* Flags to be set in the ’flags’ member of the multiboot info structure. */
|
||||||
|
|
||||||
|
/* is there basic lower/upper memory information? */
|
||||||
|
#define MULTIBOOT_INFO_MEMORY 0x00000001
|
||||||
|
/* is there a boot device set? */
|
||||||
|
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
|
||||||
|
/* is the command-line defined? */
|
||||||
|
#define MULTIBOOT_INFO_CMDLINE 0x00000004
|
||||||
|
/* are there modules to do something with? */
|
||||||
|
#define MULTIBOOT_INFO_MODS 0x00000008
|
||||||
|
|
||||||
|
/* These next two are mutually exclusive */
|
||||||
|
|
||||||
|
/* is there a symbol table loaded? */
|
||||||
|
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
|
||||||
|
/* is there an ELF section header table? */
|
||||||
|
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
|
||||||
|
|
||||||
|
/* is there a full memory map? */
|
||||||
|
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
|
||||||
|
|
||||||
|
/* Is there drive info? */
|
||||||
|
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
|
||||||
|
|
||||||
|
/* Is there a config table? */
|
||||||
|
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
|
||||||
|
|
||||||
|
/* Is there a boot loader name? */
|
||||||
|
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
|
||||||
|
|
||||||
|
/* Is there a APM table? */
|
||||||
|
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
|
||||||
|
|
||||||
|
/* Is there video information? */
|
||||||
|
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
|
||||||
|
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
|
|
||||||
|
typedef unsigned char multiboot_uint8_t;
|
||||||
|
typedef unsigned short multiboot_uint16_t;
|
||||||
|
typedef unsigned int multiboot_uint32_t;
|
||||||
|
typedef unsigned long long multiboot_uint64_t;
|
||||||
|
|
||||||
|
struct multiboot_header {
|
||||||
|
/* Must be MULTIBOOT_MAGIC - see above. */
|
||||||
|
multiboot_uint32_t magic;
|
||||||
|
|
||||||
|
/* Feature flags. */
|
||||||
|
multiboot_uint32_t flags;
|
||||||
|
|
||||||
|
/* The above fields plus this one must equal 0 mod 2^32. */
|
||||||
|
multiboot_uint32_t checksum;
|
||||||
|
|
||||||
|
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
|
||||||
|
multiboot_uint32_t header_addr;
|
||||||
|
multiboot_uint32_t load_addr;
|
||||||
|
multiboot_uint32_t load_end_addr;
|
||||||
|
multiboot_uint32_t bss_end_addr;
|
||||||
|
multiboot_uint32_t entry_addr;
|
||||||
|
|
||||||
|
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
|
||||||
|
multiboot_uint32_t mode_type;
|
||||||
|
multiboot_uint32_t width;
|
||||||
|
multiboot_uint32_t height;
|
||||||
|
multiboot_uint32_t depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The symbol table for a.out. */
|
||||||
|
struct multiboot_aout_symbol_table {
|
||||||
|
multiboot_uint32_t tabsize;
|
||||||
|
multiboot_uint32_t strsize;
|
||||||
|
multiboot_uint32_t addr;
|
||||||
|
multiboot_uint32_t reserved;
|
||||||
|
};
|
||||||
|
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
|
||||||
|
|
||||||
|
/* The section header table for ELF. */
|
||||||
|
struct multiboot_elf_section_header_table {
|
||||||
|
multiboot_uint32_t num;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t addr;
|
||||||
|
multiboot_uint32_t shndx;
|
||||||
|
};
|
||||||
|
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
|
||||||
|
|
||||||
|
struct multiboot_info {
|
||||||
|
/* Multiboot info version number */
|
||||||
|
multiboot_uint32_t flags;
|
||||||
|
|
||||||
|
/* Available memory from BIOS */
|
||||||
|
multiboot_uint32_t mem_lower;
|
||||||
|
multiboot_uint32_t mem_upper;
|
||||||
|
|
||||||
|
/* "root" partition */
|
||||||
|
multiboot_uint32_t boot_device;
|
||||||
|
|
||||||
|
/* Kernel command line */
|
||||||
|
multiboot_uint32_t cmdline;
|
||||||
|
|
||||||
|
/* Boot-Module list */
|
||||||
|
multiboot_uint32_t mods_count;
|
||||||
|
multiboot_uint32_t mods_addr;
|
||||||
|
|
||||||
|
union {
|
||||||
|
multiboot_aout_symbol_table_t aout_sym;
|
||||||
|
multiboot_elf_section_header_table_t elf_sec;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
/* Memory Mapping buffer */
|
||||||
|
multiboot_uint32_t mmap_length;
|
||||||
|
multiboot_uint32_t mmap_addr;
|
||||||
|
|
||||||
|
/* Drive Info buffer */
|
||||||
|
multiboot_uint32_t drives_length;
|
||||||
|
multiboot_uint32_t drives_addr;
|
||||||
|
|
||||||
|
/* ROM configuration table */
|
||||||
|
multiboot_uint32_t config_table;
|
||||||
|
|
||||||
|
/* Boot Loader Name */
|
||||||
|
multiboot_uint32_t boot_loader_name;
|
||||||
|
|
||||||
|
/* APM table */
|
||||||
|
multiboot_uint32_t apm_table;
|
||||||
|
|
||||||
|
/* Video */
|
||||||
|
multiboot_uint32_t vbe_control_info;
|
||||||
|
multiboot_uint32_t vbe_mode_info;
|
||||||
|
multiboot_uint16_t vbe_mode;
|
||||||
|
multiboot_uint16_t vbe_interface_seg;
|
||||||
|
multiboot_uint16_t vbe_interface_off;
|
||||||
|
multiboot_uint16_t vbe_interface_len;
|
||||||
|
|
||||||
|
multiboot_uint64_t framebuffer_addr;
|
||||||
|
multiboot_uint32_t framebuffer_pitch;
|
||||||
|
multiboot_uint32_t framebuffer_width;
|
||||||
|
multiboot_uint32_t framebuffer_height;
|
||||||
|
multiboot_uint8_t framebuffer_bpp;
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||||
|
multiboot_uint8_t framebuffer_type;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
multiboot_uint32_t framebuffer_palette_addr;
|
||||||
|
multiboot_uint16_t framebuffer_palette_num_colors;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
multiboot_uint8_t framebuffer_red_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_red_mask_size;
|
||||||
|
multiboot_uint8_t framebuffer_green_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_green_mask_size;
|
||||||
|
multiboot_uint8_t framebuffer_blue_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_blue_mask_size;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
typedef struct multiboot_info multiboot_info_t;
|
||||||
|
|
||||||
|
struct multiboot_color {
|
||||||
|
multiboot_uint8_t red;
|
||||||
|
multiboot_uint8_t green;
|
||||||
|
multiboot_uint8_t blue;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_mmap_entry {
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint64_t addr;
|
||||||
|
multiboot_uint64_t len;
|
||||||
|
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||||
|
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||||
|
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||||
|
#define MULTIBOOT_MEMORY_NVS 4
|
||||||
|
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
} __attribute__((packed));
|
||||||
|
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||||
|
|
||||||
|
struct multiboot_mod_list {
|
||||||
|
/* the memory used goes from bytes ’mod_start’ to ’mod_end-1’ inclusive */
|
||||||
|
multiboot_uint32_t mod_start;
|
||||||
|
multiboot_uint32_t mod_end;
|
||||||
|
|
||||||
|
/* Module command line */
|
||||||
|
multiboot_uint32_t cmdline;
|
||||||
|
|
||||||
|
/* padding to take it to 16 bytes (must be zero) */
|
||||||
|
multiboot_uint32_t pad;
|
||||||
|
};
|
||||||
|
typedef struct multiboot_mod_list multiboot_module_t;
|
||||||
|
|
||||||
|
/* APM BIOS info. */
|
||||||
|
struct multiboot_apm_info {
|
||||||
|
multiboot_uint16_t version;
|
||||||
|
multiboot_uint16_t cseg;
|
||||||
|
multiboot_uint32_t offset;
|
||||||
|
multiboot_uint16_t cseg_16;
|
||||||
|
multiboot_uint16_t dseg;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint16_t cseg_len;
|
||||||
|
multiboot_uint16_t cseg_16_len;
|
||||||
|
multiboot_uint16_t dseg_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ! ASM_FILE */
|
||||||
|
|
||||||
|
#endif /* ! MULTIBOOT_HEADER */
|
||||||
22
kernel/types.h
Normal file
22
kernel/types.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* types.h
|
||||||
|
*
|
||||||
|
* Created on: Nov 1, 2018
|
||||||
|
* Author: rick
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KERNEL_LIBC_TYPES_H_
|
||||||
|
#define KERNEL_LIBC_TYPES_H_
|
||||||
|
|
||||||
|
# define NULL (void *)0
|
||||||
|
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
typedef long long s64;
|
||||||
|
typedef unsigned int u32;
|
||||||
|
typedef int s32;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef short s16;
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef char s8;
|
||||||
|
|
||||||
|
#endif /* KERNEL_LIBC_TYPES_H_ */
|
||||||
43
linker.ld
Normal file
43
linker.ld
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/* The bootloader will look at this image and start execution at the symbol
|
||||||
|
designated as the entry point. */
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
/* Tell where the various sections of the object files will be put in the final
|
||||||
|
kernel image. */
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
|
||||||
|
loaded at by the bootloader. */
|
||||||
|
. = 1M;
|
||||||
|
|
||||||
|
/* First put the multiboot header, as it is required to be put very early
|
||||||
|
early in the image or the bootloader won't recognize the file format.
|
||||||
|
Next we'll put the .text section. */
|
||||||
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.multiboot)
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-only data. */
|
||||||
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-write data (initialized) */
|
||||||
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-write data (uninitialized) and stack */
|
||||||
|
.bss BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The compiler may produce other sections, by default it will put them in
|
||||||
|
a segment with the same name. Simply add stuff here as needed. */
|
||||||
|
}
|
||||||
3
qemu-debug.sh
Executable file
3
qemu-debug.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
nohup qemu-system-i386 -S -s -kernel cmake-build-debug/my-kernel.bin -d guest_errors,int -m 1G &
|
||||||
|
disown
|
||||||
Reference in New Issue
Block a user