Initial import from mbr_asm project
This commit is contained in:
commit
2c251fa51c
43
Makefile
Normal file
43
Makefile
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Used to generated .d file that deal with header dependencies
|
||||||
|
CPPFLAGS = -MMD
|
||||||
|
AS=nasm
|
||||||
|
ASFLAGS += -f elf32
|
||||||
|
LDFLAGS += -m32 -nostdlib -static -fno-common -fno-use-cxa-atexit -fno-exceptions -fno-non-call-exceptions -fno-weak -fno-rtti -fno-stack-protector
|
||||||
|
CFLAGS += -m32 -Wall -Wextra -Werror -ffreestanding -fno-exceptions -fno-pie -fno-stack-protector
|
||||||
|
CXXFLAGS += -m32 -Wall -Wextra -Werror -ffreestanding -fno-exceptions -fno-rtti -fno-pie
|
||||||
|
|
||||||
|
SUBDIRS := core drivers
|
||||||
|
|
||||||
|
CPPFLAGS += $(foreach dir, $(SUBDIRS), -I$(dir))
|
||||||
|
|
||||||
|
asmsrc=$(wildcard *.asm)
|
||||||
|
asmobj=$(asmsrc:%.asm=%.o)
|
||||||
|
csrc=$(shell find $(SUBDIRS) -type f -name "*.c")# $(wildcard *.c)
|
||||||
|
cobj=$(csrc:%.c=%.o)
|
||||||
|
deps = $(csrc:%.c=%.d)
|
||||||
|
|
||||||
|
kernel:$(asmobj) $(cobj) linker.ld
|
||||||
|
$(CXX) $(LDFLAGS) $(cobj) $(asmobj) -o $@ -T linker.ld
|
||||||
|
|
||||||
|
fd.img: kernel
|
||||||
|
dd if=/dev/zero of=$@ bs=512 count=2880
|
||||||
|
dd if=$< of=$@ conv=notrunc
|
||||||
|
|
||||||
|
#https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#x86-Function-Attributes
|
||||||
|
core/exception_handler.o:core/exception_handler.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) -mgeneral-regs-only -c $< -o $@
|
||||||
|
core/irq_handler.o:core/irq_handler.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) -mgeneral-regs-only -c $< -o $@
|
||||||
|
|
||||||
|
%.o:%.asm
|
||||||
|
$(AS) $(ASFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
test:kernel
|
||||||
|
qemu-system-x86_64 -fda $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) kernel $(asmobj) $(cobj) $(deps)
|
||||||
|
|
||||||
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
|
-include $(deps)
|
||||||
|
endif
|
24
core/exception.c
Normal file
24
core/exception.c
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "exception.h"
|
||||||
|
#include "idt.h"
|
||||||
|
#include "interrupt.h"
|
||||||
|
#include "irq.h"
|
||||||
|
|
||||||
|
exception_handler exception_handler_array[EXCEPTION_NUM] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
int exceptionSetRoutine(int exception, exception_handler handler)
|
||||||
|
{
|
||||||
|
uint32_t flags;
|
||||||
|
if ((exception < 0) || exception >= EXCEPTION_NUM)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
disable_IRQs(flags);
|
||||||
|
|
||||||
|
exception_handler_array[exception] = handler;
|
||||||
|
|
||||||
|
idt_set_handler(EXCEPTION_INTERRUPT_BASE_ADDRESS + exception, (unsigned int)handler,
|
||||||
|
0);
|
||||||
|
restore_IRQs(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
46
core/exception.h
Normal file
46
core/exception.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "interrupt.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define EXCEPTION_INTERRUPT_BASE_ADDRESS 0
|
||||||
|
|
||||||
|
// list and description https://wiki.osdev.org/Exceptions
|
||||||
|
|
||||||
|
#define EXCEPTION_DIVIDE_ZERO 0
|
||||||
|
#define EXCEPTION_DEBUG 1
|
||||||
|
#define EXCEPTION_NMI 2
|
||||||
|
#define EXCEPTION_BREAKPOINT 3
|
||||||
|
#define EXCEPTION_OVERFLOW 4
|
||||||
|
#define EXCEPTION_BOUND_RANGE_EXCEEDED 5
|
||||||
|
#define EXCEPTION_INVALID_OPCODE 6
|
||||||
|
#define EXCEPTION_DEVICE_NOT_AVAILABLE 7
|
||||||
|
#define EXCEPTION_DOUBLE_FAULT 8
|
||||||
|
#define EXCEPTION_COPRO_OVERRUN 9
|
||||||
|
#define EXCEPTION_INVALID_TSS 10
|
||||||
|
#define EXCEPTION_SEGMENT_NOT_PRESENT 11
|
||||||
|
#define EXCEPTION_STACK_SEGMENT_FAULT 12
|
||||||
|
#define EXCEPTION_GENERAL_PROTECTION_FAULT 13
|
||||||
|
#define EXCEPTION_PAGE_FAULT 14
|
||||||
|
#define EXCEPTION_RESERVED_1 15
|
||||||
|
#define EXCEPTION_X87_FP_EXCEPTION 16
|
||||||
|
#define EXCEPTION_ALIGNMENT_CHECK 17
|
||||||
|
#define EXCEPTION_MACHINE_CHECK 18
|
||||||
|
#define EXCEPTION_SIMD_FP 19
|
||||||
|
#define EXCEPTION_VIRTUALIZATION 20
|
||||||
|
#define EXCEPTION_RESERVED_2 21
|
||||||
|
#define EXCEPTION_RESERVED_3 22
|
||||||
|
#define EXCEPTION_RESERVED_4 23
|
||||||
|
#define EXCEPTION_RESERVED_5 24
|
||||||
|
#define EXCEPTION_RESERVED_6 25
|
||||||
|
#define EXCEPTION_RESERVED_7 26
|
||||||
|
#define EXCEPTION_RESERVED_8 27
|
||||||
|
#define EXCEPTION_RESERVED_9 28
|
||||||
|
#define EXCEPTION_RESERVED_10 29
|
||||||
|
#define EXCEPTION_SECURITY 30
|
||||||
|
#define EXCEPTION_RESERVED_11 31
|
||||||
|
|
||||||
|
#define EXCEPTION_NUM 32
|
||||||
|
|
||||||
|
typedef void (*exception_handler) (struct interrupt_frame *frame, ulong error_code);
|
||||||
|
int exceptionSetRoutine(int exception, exception_handler handler);
|
||||||
|
|
12
core/exception_handler.c
Normal file
12
core/exception_handler.c
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "exception.h"
|
||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
// Need GCC > 6
|
||||||
|
__attribute__((interrupt)) void print_handler(struct interrupt_frame *frame, ulong error_code)
|
||||||
|
{
|
||||||
|
|
||||||
|
printStringDetails("EXCEPTION", RED, BLACK, 0, VGA_HEIGHT - 1);
|
||||||
|
printIntDetails(error_code, RED, BLACK, 11, VGA_HEIGHT - 1);
|
||||||
|
(void)frame;
|
||||||
|
(void)error_code;
|
||||||
|
}
|
147
core/gdt.c
Normal file
147
core/gdt.c
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/* Copyright (C) 2004 David Decotigny
|
||||||
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA.
|
||||||
|
*/
|
||||||
|
#include "segment.h"
|
||||||
|
|
||||||
|
#include "gdt.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sructure of a segment descriptor.
|
||||||
|
*
|
||||||
|
* @see Intel x86 doc, Vol 3, section 3.4.3, figure 3-8. For segment
|
||||||
|
* types, see section 3.5
|
||||||
|
*/
|
||||||
|
struct x86_segment_descriptor {
|
||||||
|
/* Lowest dword */
|
||||||
|
uint16_t limit_15_0; /* Segment limit, bits 15..0 */
|
||||||
|
uint16_t base_paged_addr_15_0; /* Base address, bits 15..0 */
|
||||||
|
|
||||||
|
/* Highest dword */
|
||||||
|
uint8_t base_paged_addr_23_16; /* Base address bits 23..16 */
|
||||||
|
uint8_t segment_type : 4; /* Section 3.4.3.1 (code/data)
|
||||||
|
and 3.5 (system) of Intel x86 vol 3 */
|
||||||
|
uint8_t descriptor_type : 1; /* 0=system, 1=Code/Data */
|
||||||
|
uint8_t dpl : 2;
|
||||||
|
uint8_t present : 1;
|
||||||
|
|
||||||
|
uint8_t limit_19_16 : 4; /* Segment limit, bits 19..16 */
|
||||||
|
uint8_t custom : 1;
|
||||||
|
uint8_t zero : 1;
|
||||||
|
uint8_t op_size : 1; /* 0=16bits instructions, 1=32bits */
|
||||||
|
uint8_t granularity : 1; /* 0=limit in bytes, 1=limit in pages */
|
||||||
|
|
||||||
|
uint8_t base_paged_addr_31_24; /* Base address bits 31..24 */
|
||||||
|
} __attribute__((packed, aligned(8)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GDT register, which stores the address and size of the
|
||||||
|
* GDT.
|
||||||
|
*
|
||||||
|
* @see Intel x86 doc vol 3, section 2.4, figure 2-4; and section
|
||||||
|
* 3.5.1
|
||||||
|
*/
|
||||||
|
struct x86_gdt_register {
|
||||||
|
/* The maximum GDT offset allowed to access an entry in the GDT */
|
||||||
|
uint16_t limit;
|
||||||
|
|
||||||
|
/* This is not exactly a "virtual" address, ie an adddress such as
|
||||||
|
those of instructions and data; this is a "linear" address, ie an
|
||||||
|
address in the paged memory. However, in SOS we configure the
|
||||||
|
segmented memory as a "flat" space: the 0-4GB segment-based (ie
|
||||||
|
"virtual") addresses directly map to the 0-4GB paged memory (ie
|
||||||
|
"linear"), so that the "linear" addresses are numerically equal
|
||||||
|
to the "virtual" addresses: this base_addr will thus be the same
|
||||||
|
as the address of the gdt array */
|
||||||
|
uint32_t base_addr;
|
||||||
|
} __attribute__((packed, aligned(8)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper macro that builds a Segment descriptor for the virtual
|
||||||
|
* 0..4GB addresses to be mapped to the linear 0..4GB linear
|
||||||
|
* addresses.
|
||||||
|
*/
|
||||||
|
#define BUILD_GDTE(descr_privilege_level, is_code) \
|
||||||
|
((struct x86_segment_descriptor){ \
|
||||||
|
.limit_15_0 = 0xffff, \
|
||||||
|
.base_paged_addr_15_0 = 0, \
|
||||||
|
.base_paged_addr_23_16 = 0, \
|
||||||
|
.segment_type = \
|
||||||
|
((is_code) ? 0xb : 0x3), /* With descriptor_type (below) = 1 (code/data), \
|
||||||
|
* see Figure 3-1 of section 3.4.3.1 in Intel \
|
||||||
|
* x86 vol 3: \
|
||||||
|
* - Code (bit 3 = 1): \
|
||||||
|
* bit 0: 1=Accessed \
|
||||||
|
* bit 1: 1=Readable \
|
||||||
|
* bit 2: 0=Non-Conforming \
|
||||||
|
* - Data (bit 3 = 0): \
|
||||||
|
* bit 0: 1=Accessed \
|
||||||
|
* bit 1: 1=Writable \
|
||||||
|
* bit 2: 0=Expand up (stack-related) \
|
||||||
|
* For Conforming/non conforming segments, see \
|
||||||
|
* Intel x86 Vol 3 section 4.8.1.1 \
|
||||||
|
*/ \
|
||||||
|
.descriptor_type = 1, /* 1=Code/Data */ \
|
||||||
|
.dpl = ((descr_privilege_level)&0x3), \
|
||||||
|
.present = 1, \
|
||||||
|
.limit_19_16 = 0xf, \
|
||||||
|
.custom = 0, \
|
||||||
|
.op_size = 1, /* 32 bits instr/data */ \
|
||||||
|
.granularity = 1 /* limit is in 4kB Pages */ \
|
||||||
|
})
|
||||||
|
|
||||||
|
/** The actual GDT */
|
||||||
|
static struct x86_segment_descriptor gdt[] = {
|
||||||
|
[SOS_SEG_NULL] =
|
||||||
|
(struct x86_segment_descriptor){
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
[SOS_SEG_KCODE] = BUILD_GDTE(0, 1),
|
||||||
|
[SOS_SEG_KDATA] = BUILD_GDTE(0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
int gdtSetup(void)
|
||||||
|
{
|
||||||
|
struct x86_gdt_register gdtr;
|
||||||
|
|
||||||
|
/* Address of the GDT */
|
||||||
|
gdtr.base_addr = (uint32_t)gdt;
|
||||||
|
|
||||||
|
/* The limit is the maximum offset in bytes from the base address of
|
||||||
|
the GDT */
|
||||||
|
gdtr.limit = sizeof(gdt) - 1;
|
||||||
|
|
||||||
|
/* Commit the GDT into the CPU, and update the segment
|
||||||
|
registers. The CS register may only be updated with a long jump
|
||||||
|
to an absolute address in the given segment (see Intel x86 doc
|
||||||
|
vol 3, section 4.8.1). */
|
||||||
|
asm volatile("lgdt %0 \n\
|
||||||
|
ljmp %1,$1f \n\
|
||||||
|
1: \n\
|
||||||
|
movw %2, %%ax \n\
|
||||||
|
movw %%ax, %%ss \n\
|
||||||
|
movw %%ax, %%ds \n\
|
||||||
|
movw %%ax, %%es \n\
|
||||||
|
movw %%ax, %%fs \n\
|
||||||
|
movw %%ax, %%gs"
|
||||||
|
:
|
||||||
|
: "m"(gdtr), "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE)),
|
||||||
|
"i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA))
|
||||||
|
: "memory", "eax");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
39
core/gdt.h
Normal file
39
core/gdt.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* Copyright (C) 2004 David Decotigny
|
||||||
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA.
|
||||||
|
*/
|
||||||
|
#ifndef _SOS_GDT_H_
|
||||||
|
#define _SOS_GDT_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file gdt.h
|
||||||
|
*
|
||||||
|
* The routines that manage the GDT, the table that maps the virtual
|
||||||
|
* addresses (data/instructions, segment-relative), to "linear"
|
||||||
|
* addresses (ie paged-memory). In SOS/x86, we use a "flat" virtual
|
||||||
|
* space, ie the virtual and linear spaces are equivalent.
|
||||||
|
*
|
||||||
|
* @see Intel x86 doc vol 3, chapter 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the virtual space as a direct mapping to the linear
|
||||||
|
* address space (ie "flat" virtual space).
|
||||||
|
*/
|
||||||
|
int gdtSetup(void);
|
||||||
|
|
||||||
|
#endif /* _SOS_GDT_H_ */
|
68
core/idt.c
Normal file
68
core/idt.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "idt.h"
|
||||||
|
static struct idtEntry idt[IDT_NUM];
|
||||||
|
|
||||||
|
int idtSetup()
|
||||||
|
{
|
||||||
|
struct idtRegister idtr;
|
||||||
|
|
||||||
|
for (int i = 0; i < IDT_NUM; i++) {
|
||||||
|
struct idtEntry *idte = idt + i;
|
||||||
|
|
||||||
|
/* Setup an empty IDTE interrupt gate, see figure 5-2 in Intel
|
||||||
|
x86 doc, vol 3 */
|
||||||
|
idte->seg_sel = BUILD_SEGMENT_SELECTOR(RING_0, 0, SEGMENT_IDX_CODE);
|
||||||
|
idte->reserved = 0;
|
||||||
|
idte->flags = 0;
|
||||||
|
idte->type = 0x6; /* Interrupt gate (110b) */
|
||||||
|
idte->op_size = 1; /* 32bits instructions */
|
||||||
|
|
||||||
|
/* Disabled it for now */
|
||||||
|
idte->zero = 0;
|
||||||
|
idte->offset_low = 0;
|
||||||
|
idte->offset_high = 0;
|
||||||
|
idte->dpl = 0;
|
||||||
|
idte->present = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the IDT register, see Intel x86 doc vol 3, section 5.8.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Address of the IDT */
|
||||||
|
idtr.base_addr = (uint32_t)idt;
|
||||||
|
|
||||||
|
/* The limit is the maximum offset in bytes from the base address of
|
||||||
|
the IDT */
|
||||||
|
idtr.limit = sizeof(idt) - 1;
|
||||||
|
|
||||||
|
/* Commit the IDT into the CPU */
|
||||||
|
asm volatile("lidt %0\n" ::"m"(idtr) : "memory");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idt_set_handler(int index, unsigned int addr, int priviledge)
|
||||||
|
{
|
||||||
|
struct idtEntry *idte;
|
||||||
|
|
||||||
|
if (index < 0 || index >= IDT_NUM)
|
||||||
|
return -1;
|
||||||
|
if ((priviledge < 0) || priviledge > 3)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
idte = idt + index;
|
||||||
|
|
||||||
|
if (addr != (unsigned int)NULL) {
|
||||||
|
idte->offset_low = addr & 0xffff;
|
||||||
|
idte->offset_high = (addr >> 16) & 0xffff;
|
||||||
|
idte->dpl = priviledge;
|
||||||
|
idte->present = 1;
|
||||||
|
} else {
|
||||||
|
idte->offset_low = 0;
|
||||||
|
idte->offset_high = 0;
|
||||||
|
idte->dpl = 0;
|
||||||
|
idte->present = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
45
core/idt.h
Normal file
45
core/idt.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define IDT_NUM 256
|
||||||
|
|
||||||
|
#define RING_0 0
|
||||||
|
#define RING_1 1
|
||||||
|
#define RING_2 2
|
||||||
|
#define RING_3 3
|
||||||
|
|
||||||
|
#define SEGMENT_IDX_NULL 0
|
||||||
|
#define SEGMENT_IDX_CODE 1
|
||||||
|
#define SEGMENT_IDX_DATA 2
|
||||||
|
|
||||||
|
struct idtEntry {
|
||||||
|
uint16_t offset_low;
|
||||||
|
uint16_t seg_sel;
|
||||||
|
uint8_t reserved : 5;
|
||||||
|
uint8_t flags : 3;
|
||||||
|
uint8_t type : 3;
|
||||||
|
uint8_t op_size : 1;
|
||||||
|
uint8_t zero : 1;
|
||||||
|
uint8_t dpl : 2;
|
||||||
|
uint8_t present : 1;
|
||||||
|
uint16_t offset_high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IDT register, which stores the address and size of the
|
||||||
|
* IDT.
|
||||||
|
*
|
||||||
|
* @see Intel x86 doc vol 3, section 2.4, figure 2-4
|
||||||
|
*/
|
||||||
|
struct idtRegister {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base_addr;
|
||||||
|
} __attribute__((packed, aligned(8)));
|
||||||
|
|
||||||
|
/* Build segment http://wiki.osdev.org/Selector*/
|
||||||
|
#define BUILD_SEGMENT_SELECTOR(desc_privilege, in_ldt, index) \
|
||||||
|
((((desc_privilege)&0x3) << 0) | (((in_ldt) ? 1 : 0) << 2) | \
|
||||||
|
((index) << 3))
|
||||||
|
|
||||||
|
int idtSetup();
|
||||||
|
int idt_set_handler(int index, unsigned int addr, int priviledge);
|
11
core/interrupt.h
Normal file
11
core/interrupt.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
struct interrupt_frame;
|
||||||
|
|
||||||
|
//Exception
|
||||||
|
void print_handler(struct interrupt_frame *frame, ulong error_code);
|
||||||
|
|
||||||
|
//IRQ
|
||||||
|
void keyboard_handler(struct interrupt_frame *frame);
|
||||||
|
void timer_handler(struct interrupt_frame *frame);
|
21
core/io.h
Normal file
21
core/io.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
// NIH http://wiki.osdev.org/Inline_Assembly/Examples#I.2FO_access
|
||||||
|
static inline void outb(uint16_t port, uint8_t val)
|
||||||
|
{
|
||||||
|
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
|
||||||
|
/* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint).
|
||||||
|
* Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint).
|
||||||
|
* The outb %al, %dx encoding is the only option for all other cases.
|
||||||
|
* %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t inb(uint16_t port)
|
||||||
|
{
|
||||||
|
uint8_t ret;
|
||||||
|
asm volatile ( "inb %1, %0"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "Nd"(port) );
|
||||||
|
return ret;
|
||||||
|
}
|
32
core/irq.c
Normal file
32
core/irq.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "irq.h"
|
||||||
|
#include "idt.h"
|
||||||
|
#include "pic.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
int irqSetup()
|
||||||
|
{
|
||||||
|
initPic();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_handler irq_handler_array[IRQ_NUM] = {NULL, };
|
||||||
|
|
||||||
|
int irqSetRoutine(int irq, irq_handler handler)
|
||||||
|
{
|
||||||
|
uint32_t flags;
|
||||||
|
if ((irq < 0) || irq >= IRQ_NUM)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
disable_IRQs(flags);
|
||||||
|
|
||||||
|
irq_handler_array[irq] = handler;
|
||||||
|
|
||||||
|
if (handler != NULL) {
|
||||||
|
int ret =
|
||||||
|
idt_set_handler(IRQ_INTERRUPT_BASE_ADDRESS + irq, (unsigned int)irq_handler_array[irq], 0);
|
||||||
|
if (!ret)
|
||||||
|
enableIrq(irq);
|
||||||
|
}
|
||||||
|
restore_IRQs(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
40
core/irq.h
Normal file
40
core/irq.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "interrupt.h"
|
||||||
|
|
||||||
|
#define save_flags(flags) asm volatile("pushfl ; popl %0" : "=g"(flags)::"memory")
|
||||||
|
#define restore_flags(flags) asm volatile("push %0; popfl" ::"g"(flags) : "memory")
|
||||||
|
|
||||||
|
#define disable_IRQs(flags) \
|
||||||
|
({ \
|
||||||
|
save_flags(flags); \
|
||||||
|
asm("cli\n"); \
|
||||||
|
})
|
||||||
|
#define restore_IRQs(flags) restore_flags(flags)
|
||||||
|
|
||||||
|
|
||||||
|
#define IRQ_TIMER 0 // MASTER IRQ
|
||||||
|
#define IRQ_KEYBOARD 1
|
||||||
|
#define IRQ_SLAVE_PIC 2
|
||||||
|
#define IRQ_COM2 3
|
||||||
|
#define IRQ_COM1 4
|
||||||
|
#define IRQ_LPT2 5
|
||||||
|
#define IRQ_FLOPPY 6
|
||||||
|
#define IRQ_LPT1 7
|
||||||
|
#define IRQ_8_NOT_DEFINED 8 // SLAVE
|
||||||
|
#define IRQ_RESERVED_1 9 // SLAVE IRQ
|
||||||
|
#define IRQ_RESERVED_2 10
|
||||||
|
#define IRQ_RESERVED_3 11
|
||||||
|
#define IRQ_RESERVED_4 12
|
||||||
|
#define IRQ_COPROCESSOR 13
|
||||||
|
#define IRQ_HARDDISK 14
|
||||||
|
#define IRQ_RESERVED_5 15
|
||||||
|
|
||||||
|
#define IRQ_INTERRUPT_BASE_ADDRESS 0x20
|
||||||
|
#define IRQ_NUM 16
|
||||||
|
|
||||||
|
// An handler should finish by the iret opcode -> https://wiki.osdev.org/Interrupt_Service_Routines
|
||||||
|
// That's why we use wrapper around them or the gcc interrupt attribut
|
||||||
|
// __attribute__((interrupt)) void (*irq_handler)(int irq);
|
||||||
|
typedef void (*irq_handler)(struct interrupt_frame *frame);
|
||||||
|
int irqSetup();
|
||||||
|
int irqSetRoutine(int irq, irq_handler handler);
|
22
core/irq_handler.c
Normal file
22
core/irq_handler.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "interrupt.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "irq.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
#include "pic.h"
|
||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
// Need GCC > 6
|
||||||
|
__attribute__((interrupt)) void keyboard_handler(struct interrupt_frame *frame)
|
||||||
|
{
|
||||||
|
EOIIrq(IRQ_KEYBOARD);
|
||||||
|
keyboard_do_irq();
|
||||||
|
(void)frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void timer_handler(struct interrupt_frame *frame)
|
||||||
|
{
|
||||||
|
static int timeCnt = 0;
|
||||||
|
EOIIrq(IRQ_TIMER);
|
||||||
|
printIntDetails(timeCnt++, RED, BLACK, 20, VGA_HEIGHT - 1);
|
||||||
|
(void)frame;
|
||||||
|
}
|
11
core/klibc.c
Normal file
11
core/klibc.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "klibc.h"
|
||||||
|
|
||||||
|
void *memcpy(void *dst, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
char *dstChar = dst;
|
||||||
|
const char *srcChar = src;
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
*(dstChar++) = *(srcChar++);
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
4
core/klibc.h
Normal file
4
core/klibc.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
void *memcpy(void *dest, const void *src, size_t n );
|
37
core/main.c
Normal file
37
core/main.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "exception.h"
|
||||||
|
#include "gdt.h"
|
||||||
|
#include "idt.h"
|
||||||
|
#include "interrupt.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "irq.h"
|
||||||
|
#include "pit.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
void cpuid(int code, uint32_t *a, uint32_t *d)
|
||||||
|
{
|
||||||
|
asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx");
|
||||||
|
}
|
||||||
|
|
||||||
|
void kmain()
|
||||||
|
{
|
||||||
|
initVGA(BLACK, GREEN);
|
||||||
|
printString("Setting up IDT\n");
|
||||||
|
gdtSetup();
|
||||||
|
idtSetup();
|
||||||
|
irqSetup();
|
||||||
|
initPit(100);
|
||||||
|
|
||||||
|
printString("Setting up IRQ handlers\n");
|
||||||
|
irqSetRoutine(IRQ_KEYBOARD, keyboard_handler);
|
||||||
|
irqSetRoutine(IRQ_TIMER, timer_handler);
|
||||||
|
printString("Enabling HW interrupts\n");
|
||||||
|
exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, print_handler);
|
||||||
|
// Enabling the HW interrupts
|
||||||
|
asm volatile("sti\n");
|
||||||
|
int count = 0;
|
||||||
|
while (1) {
|
||||||
|
printIntDetails(count++, GREEN, BLACK, 0, VGA_HEIGHT - 1);
|
||||||
|
}
|
||||||
|
printString("exiting\n");
|
||||||
|
}
|
59
core/segment.h
Normal file
59
core/segment.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* Copyright (C) 2004 The SOS Team
|
||||||
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA.
|
||||||
|
*/
|
||||||
|
#ifndef _SOS_HWSEGS_H_
|
||||||
|
#define _SOS_HWSEGS_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file segments.h
|
||||||
|
*
|
||||||
|
* Global and local (GDT/LDT) segment descriptor definition and
|
||||||
|
* structure. These segments map virtual addresses (ie
|
||||||
|
* data/instruction addresses, relative to these segment descriptors)
|
||||||
|
* to linear addresses (ie addresses in the paged-memory space).
|
||||||
|
*
|
||||||
|
* @see Intel x86 doc, vol 3 chapter 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global segment selectors (GDT) for SOS/x86.
|
||||||
|
*
|
||||||
|
* @see gdt.h
|
||||||
|
*/
|
||||||
|
#define SOS_SEG_NULL 0 /* NULL segment, unused by the procesor */
|
||||||
|
#define SOS_SEG_KCODE 1 /* Kernel code segment */
|
||||||
|
#define SOS_SEG_KDATA 2 /* Kernel data segment */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper macro that builds a segment register's value
|
||||||
|
*/
|
||||||
|
#define SOS_BUILD_SEGMENT_REG_VALUE(desc_privilege,in_ldt,seg_index) \
|
||||||
|
( (((desc_privilege) & 0x3) << 0) \
|
||||||
|
| (((in_ldt)?1:0) << 2) \
|
||||||
|
| ((seg_index) << 3) )
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local segment selectors (LDT) for SOS/x86
|
||||||
|
*/
|
||||||
|
/* None */
|
||||||
|
|
||||||
|
#endif /* _SOS_HWSEGS_H_ */
|
47
core/types.h
Normal file
47
core/types.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef __signed__ char __s8;
|
||||||
|
typedef unsigned char __u8;
|
||||||
|
|
||||||
|
typedef __signed__ short __s16;
|
||||||
|
typedef unsigned short __u16;
|
||||||
|
|
||||||
|
typedef __signed__ int __s32;
|
||||||
|
typedef unsigned int __u32;
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__extension__ typedef __signed__ long long __s64;
|
||||||
|
__extension__ typedef unsigned long long __u64;
|
||||||
|
#else
|
||||||
|
typedef __signed__ long long __s64;
|
||||||
|
typedef unsigned long long __u64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* sysv */
|
||||||
|
typedef unsigned char unchar;
|
||||||
|
typedef unsigned short ushort;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
|
||||||
|
typedef __s8 int8_t;
|
||||||
|
typedef __s16 int16_t;
|
||||||
|
typedef __s32 int32_t;
|
||||||
|
|
||||||
|
typedef __u8 uint8_t;
|
||||||
|
typedef __u16 uint16_t;
|
||||||
|
typedef __u32 uint32_t;
|
||||||
|
|
||||||
|
typedef __u64 uint64_t;
|
||||||
|
typedef __u64 u_int64_t;
|
||||||
|
typedef __s64 int64_t;
|
||||||
|
|
||||||
|
typedef enum { FALSE=0, TRUE } bool_t;
|
||||||
|
#define NULL ((void*)0)
|
||||||
|
|
||||||
|
#if __x86_64__
|
||||||
|
typedef unsigned long size_t;
|
||||||
|
typedef long ssize_t;
|
||||||
|
#else
|
||||||
|
typedef unsigned int size_t;
|
||||||
|
typedef int ssize_t;
|
||||||
|
#endif
|
301
drivers/keyboard.c
Normal file
301
drivers/keyboard.c
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
#include "keyboard.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
const char *scancode[128] = {
|
||||||
|
/* 0 */ 0,
|
||||||
|
/* 1 */ "\e", /* escape */
|
||||||
|
/* 2 */ "&",
|
||||||
|
/* 3 */ "é",
|
||||||
|
/* 4 */ "\"",
|
||||||
|
/* 5 */ "'",
|
||||||
|
/* 6 */ "(",
|
||||||
|
/* 7 */ "-",
|
||||||
|
/* 8 */ "è",
|
||||||
|
/* 9 */ "_",
|
||||||
|
/* 10 */ "ç",
|
||||||
|
/* 11 */ "à",
|
||||||
|
/* 12 */ ")",
|
||||||
|
/* 13 */ "=",
|
||||||
|
/* 14 */ "\b", /* Backspace */
|
||||||
|
/* 15 */ "\t", /* Tab */
|
||||||
|
/* 16 */ "a",
|
||||||
|
/* 17 */ "z",
|
||||||
|
/* 18 */ "e",
|
||||||
|
/* 19 */ "r",
|
||||||
|
/* 20 */ "t",
|
||||||
|
/* 21 */ "y",
|
||||||
|
/* 22 */ "u",
|
||||||
|
/* 23 */ "i",
|
||||||
|
/* 24 */ "o",
|
||||||
|
/* 25 */ "p",
|
||||||
|
/* 26 */ "^",
|
||||||
|
/* 27 */ "$",
|
||||||
|
/* 28 */ "\n",
|
||||||
|
/* 29 */ 0, /* left control */
|
||||||
|
/* 30 */ "q",
|
||||||
|
/* 31 */ "s",
|
||||||
|
/* 32 */ "d",
|
||||||
|
/* 33 */ "f",
|
||||||
|
/* 34 */ "g",
|
||||||
|
/* 35 */ "h",
|
||||||
|
/* 36 */ "j",
|
||||||
|
/* 37 */ "k",
|
||||||
|
/* 38 */ "l",
|
||||||
|
/* 39 */ "m",
|
||||||
|
/* 40 */ "ù",
|
||||||
|
/* 41 */ 0, /*²*/
|
||||||
|
/* 42 */ 0, /* left shift */
|
||||||
|
/* 43 */ "*",
|
||||||
|
/* 44 */ "w",
|
||||||
|
/* 45 */ "x",
|
||||||
|
/* 46 */ "c",
|
||||||
|
/* 47 */ "v",
|
||||||
|
/* 48 */ "b",
|
||||||
|
/* 49 */ "n",
|
||||||
|
/* 50 */ ",",
|
||||||
|
/* 51 */ ";",
|
||||||
|
/* 52 */ ":",
|
||||||
|
/* 53 */ "!",
|
||||||
|
/* 54 */ 0, /* right shift*/
|
||||||
|
/* 55 */ 0,
|
||||||
|
/* 56 */ 0, /* left alt*/
|
||||||
|
/* 57 */ " ",
|
||||||
|
/* 58 */ 0,
|
||||||
|
/* 59 */ "\eOP", /* F1 */
|
||||||
|
/* 60 */ "\eOQ", /* F2 */
|
||||||
|
/* 61 */ "\eOR", /* F3 */
|
||||||
|
/* 62 */ "\eOS", /* F4 */
|
||||||
|
/* 63 */ "\e[15~", /* F5 */
|
||||||
|
/* 64 */ "\e[17~", /* F6 */
|
||||||
|
/* 65 */ "\e[18~", /* F7 */
|
||||||
|
/* 66 */ "\e[19~", /* F8 */
|
||||||
|
/* 67 */ "\e[20~", /* F9 */
|
||||||
|
/* 68 */ "\e[21~", /* F10 */
|
||||||
|
/* 69 */ 0,
|
||||||
|
/* 70 */ 0,
|
||||||
|
/* 71 */ 0,
|
||||||
|
/* 72 */ 0,
|
||||||
|
/* 73 */ 0,
|
||||||
|
/* 74 */ 0,
|
||||||
|
/* 75 */ 0,
|
||||||
|
/* 76 */ 0,
|
||||||
|
/* 77 */ 0,
|
||||||
|
/* 78 */ 0,
|
||||||
|
/* 79 */ 0,
|
||||||
|
/* 80 */ 0,
|
||||||
|
/* 81 */ 0,
|
||||||
|
/* 82 */ 0,
|
||||||
|
/* 83 */ 0,
|
||||||
|
/* 84 */ 0,
|
||||||
|
/* 85 */ 0,
|
||||||
|
/* 86 */ "<",
|
||||||
|
/* 87 */ "\e[23~", /* F11 */
|
||||||
|
/* 88 */ "\e[24~", /* F12 */
|
||||||
|
/* 89 */ 0,
|
||||||
|
/* 90 */ 0,
|
||||||
|
/* 91 */ 0,
|
||||||
|
/* 92 */ 0,
|
||||||
|
/* 93 */ 0,
|
||||||
|
/* 94 */ 0,
|
||||||
|
/* 95 */ 0,
|
||||||
|
/* 96 */ 0,
|
||||||
|
/* 97 */ 0,
|
||||||
|
/* 98 */ 0,
|
||||||
|
/* 99 */ 0,
|
||||||
|
/* 100 */ 0,
|
||||||
|
/* 101 */ 0,
|
||||||
|
/* 102 */ 0,
|
||||||
|
/* 103 */ 0,
|
||||||
|
/* 104 */ 0,
|
||||||
|
/* 105 */ 0,
|
||||||
|
/* 106 */ 0,
|
||||||
|
/* 107 */ 0,
|
||||||
|
/* 108 */ 0,
|
||||||
|
/* 109 */ 0,
|
||||||
|
/* 110 */ 0,
|
||||||
|
/* 111 */ 0,
|
||||||
|
/* 112 */ 0,
|
||||||
|
/* 113 */ 0,
|
||||||
|
/* 114 */ 0,
|
||||||
|
/* 115 */ 0,
|
||||||
|
/* 116 */ 0,
|
||||||
|
/* 117 */ 0,
|
||||||
|
/* 118 */ 0,
|
||||||
|
/* 119 */ 0,
|
||||||
|
/* 120 */ 0,
|
||||||
|
/* 121 */ 0,
|
||||||
|
/* 122 */ 0,
|
||||||
|
/* 123 */ 0,
|
||||||
|
/* 124 */ 0,
|
||||||
|
/* 125 */ 0,
|
||||||
|
/* 126 */ 0,
|
||||||
|
/* 127 */ 0};
|
||||||
|
|
||||||
|
const char *scancode_shift[128] = {
|
||||||
|
/* 0 */ 0,
|
||||||
|
/* 1 */ "\e",
|
||||||
|
/* 2 */ "1",
|
||||||
|
/* 3 */ "2",
|
||||||
|
/* 4 */ "3",
|
||||||
|
/* 5 */ "4",
|
||||||
|
/* 6 */ "5",
|
||||||
|
/* 7 */ "6",
|
||||||
|
/* 8 */ "7",
|
||||||
|
/* 9 */ "8",
|
||||||
|
/* 10 */ "9",
|
||||||
|
/* 11 */ "0",
|
||||||
|
/* 12 */ "°",
|
||||||
|
/* 13 */ "+",
|
||||||
|
/* 14 */ "\b", /* Shift-Backspace */
|
||||||
|
/* 15 */ "\e[Z", /* Shift-Tab */
|
||||||
|
/* 16 */ "A",
|
||||||
|
/* 17 */ "Z",
|
||||||
|
/* 18 */ "E",
|
||||||
|
/* 19 */ "R",
|
||||||
|
/* 20 */ "T",
|
||||||
|
/* 21 */ "Y",
|
||||||
|
/* 22 */ "U",
|
||||||
|
/* 23 */ "I",
|
||||||
|
/* 24 */ "O",
|
||||||
|
/* 25 */ "P",
|
||||||
|
/* 26 */ "\"",
|
||||||
|
/* 27 */ "£",
|
||||||
|
/* 28 */ "\n",
|
||||||
|
/* 29 */ 0, /* left control */
|
||||||
|
/* 30 */ "Q",
|
||||||
|
/* 31 */ "S",
|
||||||
|
/* 32 */ "D",
|
||||||
|
/* 33 */ "F",
|
||||||
|
/* 34 */ "G",
|
||||||
|
/* 35 */ "H",
|
||||||
|
/* 36 */ "J",
|
||||||
|
/* 37 */ "K",
|
||||||
|
/* 38 */ "L",
|
||||||
|
/* 39 */ "M",
|
||||||
|
/* 40 */ "%",
|
||||||
|
/* 41 */ 0,
|
||||||
|
/* 42 */ 0,
|
||||||
|
/* 43 */ "µ",
|
||||||
|
/* 44 */ "W",
|
||||||
|
/* 45 */ "X",
|
||||||
|
/* 46 */ "C",
|
||||||
|
/* 47 */ "V",
|
||||||
|
/* 48 */ "B",
|
||||||
|
/* 49 */ "N",
|
||||||
|
/* 50 */ "?",
|
||||||
|
/* 51 */ ".",
|
||||||
|
/* 52 */ "/",
|
||||||
|
/* 53 */ "§",
|
||||||
|
/* 54 */ 0,
|
||||||
|
/* 55 */ 0,
|
||||||
|
/* 56 */ 0,
|
||||||
|
/* 57 */ 0,
|
||||||
|
/* 58 */ 0,
|
||||||
|
/* 59 */ "\eOP", /* Shift-F1 */
|
||||||
|
/* 60 */ "\eOQ", /* Shift-F2 */
|
||||||
|
/* 61 */ "\eOR", /* Shift-F3 */
|
||||||
|
/* 62 */ "\eOS", /* Shift-F4 */
|
||||||
|
/* 63 */ "\e[15;2~", /* Shift-F5 */
|
||||||
|
/* 64 */ "\e[17;2~", /* Shift-F6 */
|
||||||
|
/* 65 */ "\e[18;2~", /* Shift-F7 */
|
||||||
|
/* 66 */ "\e[19;2~", /* Shift-F8 */
|
||||||
|
/* 67 */ "\e[20:2~", /* Shift-F9 */
|
||||||
|
/* 68 */ "\e[21:2~", /* Shift-F10 */
|
||||||
|
/* 69 */ 0,
|
||||||
|
/* 70 */ 0,
|
||||||
|
/* 71 */ 0,
|
||||||
|
/* 72 */ 0,
|
||||||
|
/* 73 */ 0,
|
||||||
|
/* 74 */ 0,
|
||||||
|
/* 75 */ 0,
|
||||||
|
/* 76 */ 0,
|
||||||
|
/* 77 */ 0,
|
||||||
|
/* 78 */ 0,
|
||||||
|
/* 79 */ 0,
|
||||||
|
/* 80 */ 0,
|
||||||
|
/* 81 */ 0,
|
||||||
|
/* 82 */ 0,
|
||||||
|
/* 83 */ 0,
|
||||||
|
/* 84 */ 0,
|
||||||
|
/* 85 */ 0,
|
||||||
|
/* 86 */ ">",
|
||||||
|
/* 87 */ "\e[23;2~", /* Shift-F11 */
|
||||||
|
/* 88 */ "\e[24;2~", /* Shift-F12 */
|
||||||
|
/* 89 */ 0,
|
||||||
|
/* 90 */ 0,
|
||||||
|
/* 91 */ 0,
|
||||||
|
/* 92 */ 0,
|
||||||
|
/* 93 */ 0,
|
||||||
|
/* 94 */ 0,
|
||||||
|
/* 95 */ 0,
|
||||||
|
/* 96 */ 0,
|
||||||
|
/* 97 */ 0,
|
||||||
|
/* 98 */ 0,
|
||||||
|
/* 99 */ 0,
|
||||||
|
/* 100 */ 0,
|
||||||
|
/* 101 */ 0,
|
||||||
|
/* 102 */ 0,
|
||||||
|
/* 103 */ 0,
|
||||||
|
/* 104 */ 0,
|
||||||
|
/* 105 */ 0,
|
||||||
|
/* 106 */ 0,
|
||||||
|
/* 107 */ 0,
|
||||||
|
/* 108 */ 0,
|
||||||
|
/* 109 */ 0,
|
||||||
|
/* 110 */ 0,
|
||||||
|
/* 111 */ 0,
|
||||||
|
/* 112 */ 0,
|
||||||
|
/* 113 */ 0,
|
||||||
|
/* 114 */ 0,
|
||||||
|
/* 115 */ 0,
|
||||||
|
/* 116 */ 0,
|
||||||
|
/* 117 */ 0,
|
||||||
|
/* 118 */ 0,
|
||||||
|
/* 119 */ 0,
|
||||||
|
/* 120 */ 0,
|
||||||
|
/* 121 */ 0,
|
||||||
|
/* 122 */ 0,
|
||||||
|
/* 123 */ 0,
|
||||||
|
/* 124 */ 0,
|
||||||
|
/* 125 */ 0,
|
||||||
|
/* 126 */ 0,
|
||||||
|
/* 127 */ 0};
|
||||||
|
|
||||||
|
void keyboard_do_irq()
|
||||||
|
{
|
||||||
|
static int lshift = 0;
|
||||||
|
static int rshift = 0;
|
||||||
|
unsigned char c = 0;
|
||||||
|
if (inb(0x60) != c) {
|
||||||
|
c = inb(0x60);
|
||||||
|
if (c > 0) {
|
||||||
|
if (c < BREAK_CODE) {
|
||||||
|
switch (c) {
|
||||||
|
case 42:
|
||||||
|
lshift = 1;
|
||||||
|
break;
|
||||||
|
case 54:
|
||||||
|
rshift = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (lshift || rshift)
|
||||||
|
printString(scancode_shift[(int)c]);
|
||||||
|
else
|
||||||
|
printString(scancode[(int)c]);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
c = c - BREAK_CODE;
|
||||||
|
switch (c) {
|
||||||
|
case 42:
|
||||||
|
lshift = 0;
|
||||||
|
break;
|
||||||
|
case 54:
|
||||||
|
rshift = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
6
drivers/keyboard.h
Normal file
6
drivers/keyboard.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Pushing generate MAKE_CODE (<0x80)
|
||||||
|
// Releasing generate BREAK_CODE (break_code = make_code + 0x80)
|
||||||
|
#define BREAK_CODE 0x80
|
||||||
|
void keyboard_do_irq();
|
73
drivers/pic.c
Normal file
73
drivers/pic.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include "pic.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "irq.h"
|
||||||
|
|
||||||
|
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
||||||
|
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||||
|
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
||||||
|
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
||||||
|
#define ICW1_INIT 0x10 /* Initialization - required! */
|
||||||
|
|
||||||
|
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
||||||
|
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
||||||
|
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
||||||
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||||
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||||
|
|
||||||
|
void initPic(void)
|
||||||
|
{
|
||||||
|
/* Send CMD: Init + sequence in 4 DATA */
|
||||||
|
outb(PIC_MASTER_CMD, ICW1_INIT + ICW1_ICW4);
|
||||||
|
outb(PIC_SLAVE_CMD, ICW1_INIT + ICW1_ICW4);
|
||||||
|
|
||||||
|
/* Send ICW2: ctrl base address. Remap IRQ from interupt range 0x0-0xF to 0x20-0x2F as
|
||||||
|
* intel
|
||||||
|
* reserve interupt 0x0-0x1F in protected mode (e.g. 0-7 are CPU exception) */
|
||||||
|
outb(PIC_MASTER_DATA, IRQ_INTERRUPT_BASE_ADDRESS);
|
||||||
|
outb(PIC_SLAVE_DATA, IRQ_INTERRUPT_BASE_ADDRESS + 8);
|
||||||
|
|
||||||
|
/* Send ICW3 master: mask where slaves are connected */
|
||||||
|
outb(PIC_MASTER_DATA, 0x4);
|
||||||
|
/* Send ICW3 slave: index where the slave is connected on master */
|
||||||
|
outb(PIC_SLAVE_DATA, 0x2);
|
||||||
|
|
||||||
|
/* Send ICW4: 8086 mode, fully nested, not buffered, no implicit EOI */
|
||||||
|
outb(PIC_MASTER_DATA, ICW4_8086);
|
||||||
|
outb(PIC_SLAVE_DATA, ICW4_8086);
|
||||||
|
|
||||||
|
/* Send OCW1:
|
||||||
|
* Closing all IRQs : waiting for a correct handler The only IRQ
|
||||||
|
* enabled is the cascade (that's why we use 0xFB for the master) */
|
||||||
|
outb(PIC_MASTER_DATA, 0xFB);
|
||||||
|
outb(PIC_SLAVE_DATA, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EOIIrq(int irq)
|
||||||
|
{
|
||||||
|
if (irq >= 8)
|
||||||
|
outb(PIC_SLAVE_CMD, PIC_EOI);
|
||||||
|
|
||||||
|
outb(PIC_MASTER_CMD, PIC_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void disableIrq(int irq)
|
||||||
|
{
|
||||||
|
if (irq < 8) {
|
||||||
|
uint8_t status = inb(PIC_MASTER_DATA);
|
||||||
|
outb(PIC_MASTER_DATA, (status | (1 << irq)));
|
||||||
|
} else {
|
||||||
|
uint8_t status = inb(PIC_SLAVE_DATA);
|
||||||
|
outb(PIC_SLAVE_DATA, (status | (1 << (irq - 8))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableIrq(int irq)
|
||||||
|
{
|
||||||
|
if (irq < 8) {
|
||||||
|
uint8_t status = inb(PIC_MASTER_DATA);
|
||||||
|
outb(PIC_MASTER_DATA, (status & ~(1 << irq)));
|
||||||
|
} else {
|
||||||
|
uint8_t status = inb(PIC_SLAVE_DATA);
|
||||||
|
outb(PIC_SLAVE_DATA, (status & ~(1 << (irq - 8))));
|
||||||
|
}
|
||||||
|
}
|
21
drivers/pic.h
Normal file
21
drivers/pic.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
// 2 PIC 8259 are available on x86
|
||||||
|
//
|
||||||
|
// Master - command: 0x20, data: 0x21
|
||||||
|
// Slave - command: 0xA0, data: 0xA1
|
||||||
|
//
|
||||||
|
// http://www.jamesmolloy.co.uk/tutorial_html/5.-IRQs%20and%20the%20PIT.html
|
||||||
|
// SimpleOS art2
|
||||||
|
// http://wiki.osdev.org/PIC
|
||||||
|
|
||||||
|
#define PIC_MASTER_CMD 0x20
|
||||||
|
#define PIC_SLAVE_CMD 0xa0
|
||||||
|
#define PIC_MASTER_DATA 0x21
|
||||||
|
#define PIC_SLAVE_DATA 0xa1
|
||||||
|
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
||||||
|
|
||||||
|
|
||||||
|
void EOIIrq(int irq);
|
||||||
|
void initPic(void);
|
||||||
|
void enableIrq(int irq);
|
||||||
|
void disableIrq(int irq);
|
14
drivers/pit.c
Normal file
14
drivers/pit.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "pit.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
int initPit(unsigned int freq)
|
||||||
|
{
|
||||||
|
unsigned int divisor = PIT_FREQ / freq;
|
||||||
|
if (divisor > 65535)
|
||||||
|
divisor = 0; // Used to represent 35536
|
||||||
|
outb(PIT_CMD, 0x34); // chan 0; low then high; mode 2
|
||||||
|
outb(PIT_CHAN_0, divisor & 0xFF);
|
||||||
|
outb(PIT_CHAN_0, divisor >> 8u);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
16
drivers/pit.h
Normal file
16
drivers/pit.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// C.f https://wiki.osdev.org/PIT
|
||||||
|
|
||||||
|
#define PIT_FREQ 1193182
|
||||||
|
#define PIT_CHAN_0 0x40 // IRQ0
|
||||||
|
#define PIT_CHAN_1 0x41 // Used for DRAM refresh. Not used anymore
|
||||||
|
#define PIT_CHAN_2 0x42 // PC Speaker
|
||||||
|
#define PIT_CMD 0x43
|
||||||
|
// Cmd are
|
||||||
|
// 7-6: select channel. 0 ->chan0, 1 -> chan1, 2 -> chan 2, 3 -> read back
|
||||||
|
// 5-4: access mode. 0 -> latch count; 1 -> low value only; 2 -> high value only;
|
||||||
|
// 3 -> low then high 3-1: mode. See https://wiki.osdev.org/PIT
|
||||||
|
|
||||||
|
int initPit(unsigned int freq);
|
||||||
|
|
142
drivers/vga.c
Normal file
142
drivers/vga.c
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#include "vga.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "klibc.h"
|
||||||
|
|
||||||
|
static uint vgaBgColor;
|
||||||
|
static uint vgaColor;
|
||||||
|
static int line, col;
|
||||||
|
|
||||||
|
int initVGA(uint bgColor, uint color)
|
||||||
|
{
|
||||||
|
vgaBgColor = bgColor;
|
||||||
|
vgaColor = color;
|
||||||
|
clearScreen(bgColor);
|
||||||
|
line = 0;
|
||||||
|
col = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearScreen(uint bgColor)
|
||||||
|
{
|
||||||
|
volatile short *vga = (short *)VGA_ADDR;
|
||||||
|
long int colorAttr = bgColor << 12;
|
||||||
|
for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) {
|
||||||
|
vga[i] = colorAttr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printInt(int integer)
|
||||||
|
{
|
||||||
|
char num[sizeof(int) *
|
||||||
|
3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3) =
|
||||||
|
// 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
|
||||||
|
int i = 0, k = 0;
|
||||||
|
if (integer < 0) {
|
||||||
|
printChar('-');
|
||||||
|
}
|
||||||
|
while (integer != 0) {
|
||||||
|
int digit = integer % 10;
|
||||||
|
num[i++] = (digit > 0) ? digit : -digit;
|
||||||
|
integer = integer / 10;
|
||||||
|
}
|
||||||
|
for (k = i - 1; k >= 0; k--) {
|
||||||
|
printChar(num[k] + '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printIntDetails(int integer, uint color, uint bgColor, int startX, int startY)
|
||||||
|
{
|
||||||
|
char num[sizeof(int) *
|
||||||
|
3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3) =
|
||||||
|
// 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
|
||||||
|
int x = startX;
|
||||||
|
int i = 0, k = 0;
|
||||||
|
if (integer < 0) {
|
||||||
|
printCharDetails('-', color, bgColor, x++, startY);
|
||||||
|
}
|
||||||
|
while (integer != 0) {
|
||||||
|
int digit = integer % 10;
|
||||||
|
num[i++] = (digit > 0) ? digit : -digit;
|
||||||
|
integer = integer / 10;
|
||||||
|
}
|
||||||
|
for (k = i - 1; k >= 0; k--) {
|
||||||
|
printCharDetails(num[k] + '0', color, bgColor, x++, startY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY)
|
||||||
|
{
|
||||||
|
volatile short *vga = (short *)VGA_ADDR;
|
||||||
|
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
|
||||||
|
vga[VGA_WIDTH * startY + startX] = colorAttr | str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vgaScrollUp(void)
|
||||||
|
{
|
||||||
|
long int colorAttr = vgaBgColor << 12;
|
||||||
|
volatile short *vga = (short *)VGA_ADDR;
|
||||||
|
for (int i = 1; i < VGA_HEIGHT - 2;
|
||||||
|
i++) { // last line is status line. Do not scroll it
|
||||||
|
memcpy((void *)&vga[VGA_WIDTH * (i - 1)], (void *)&vga[VGA_WIDTH * i],
|
||||||
|
VGA_WIDTH * sizeof(short));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < VGA_WIDTH; i++) {
|
||||||
|
vga[(VGA_HEIGHT - 2) * VGA_WIDTH + i] = colorAttr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printString(const char *str)
|
||||||
|
{
|
||||||
|
while (*str) {
|
||||||
|
printChar(*(str++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printChar(const char str)
|
||||||
|
{
|
||||||
|
if (str == '\n') {
|
||||||
|
line++;
|
||||||
|
col = 0;
|
||||||
|
if (line >= VGA_HEIGHT - 1) {
|
||||||
|
vgaScrollUp();
|
||||||
|
line--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(str == '\r')
|
||||||
|
{
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
else if(str == '\b')
|
||||||
|
{
|
||||||
|
col--;
|
||||||
|
if (col < 0) {
|
||||||
|
col = VGA_WIDTH - 1;
|
||||||
|
line--;
|
||||||
|
}
|
||||||
|
printCharDetails(' ', vgaColor, vgaBgColor, col, line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printCharDetails(str, vgaColor, vgaBgColor, col++, line);
|
||||||
|
if (col == VGA_WIDTH) {
|
||||||
|
col = 0;
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
if (line >= VGA_HEIGHT - 1) {
|
||||||
|
vgaScrollUp();
|
||||||
|
line--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printStringDetails(const char *str, uint color, uint bgColor, int startX, int startY)
|
||||||
|
{
|
||||||
|
volatile short *vga = (short *)VGA_ADDR;
|
||||||
|
int i = 0;
|
||||||
|
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
|
||||||
|
while (*str) {
|
||||||
|
vga[VGA_WIDTH * startY + startX + i] = colorAttr | *str;
|
||||||
|
str++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
27
drivers/vga.h
Normal file
27
drivers/vga.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
// https://wiki.osdev.org/Text_UI
|
||||||
|
#define BLACK 0x00
|
||||||
|
#define BLUE 0x01
|
||||||
|
#define GREEN 0x02
|
||||||
|
#define CYAN 0x03
|
||||||
|
#define RED 0x04
|
||||||
|
#define MAGENTA 0x05
|
||||||
|
#define BROWN 0x06
|
||||||
|
#define GREY 0x07
|
||||||
|
#define WHITE 0x0F
|
||||||
|
|
||||||
|
#define VGA_ADDR 0xB8000
|
||||||
|
#define VGA_WIDTH 80
|
||||||
|
#define VGA_HEIGHT 25
|
||||||
|
|
||||||
|
int initVGA(uint bgColor, uint color);
|
||||||
|
void clearScreen(uint bgColor);
|
||||||
|
void printInt(int integer);
|
||||||
|
void printIntDetails(int integer, uint color, uint bgColor, int startX, int startY);
|
||||||
|
void printCharDetails(char str, uint color, uint bgColor, int startX, int startY);
|
||||||
|
void printStringDetails(const char *str, uint color, uint bgColor, int startX, int startY);
|
||||||
|
void printString(const char *str);
|
||||||
|
void printChar(const char str);
|
||||||
|
void vgaScrollUp(void);
|
26
linker.ld
Normal file
26
linker.ld
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
ENTRY(boot)
|
||||||
|
OUTPUT_FORMAT("binary")
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x7c00;
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.boot)
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
161
mbr.asm
Normal file
161
mbr.asm
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
section .boot
|
||||||
|
bits 16
|
||||||
|
global boot
|
||||||
|
boot:
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
display_enable:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
mov ah, 0h ; 00h Set Video Mode
|
||||||
|
mov al, 07h ; Txt, monochrome, 80x25
|
||||||
|
|
||||||
|
int 10h
|
||||||
|
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
print:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
mov si, [bp + 4]; put first function arg in si. sp is stask pointer
|
||||||
|
.loop:
|
||||||
|
lodsb ; load si content into al then inc si
|
||||||
|
cmp al, 0;
|
||||||
|
je .end
|
||||||
|
|
||||||
|
mov ah, 0eh
|
||||||
|
mov bx, 0
|
||||||
|
int 10h
|
||||||
|
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
.end:
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
println:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
push word [bp + 4]
|
||||||
|
call print
|
||||||
|
add sp, 2
|
||||||
|
|
||||||
|
mov ah, 03h ; read cursor position
|
||||||
|
int 10h ; row number in dh. Col in dl
|
||||||
|
|
||||||
|
inc dh ; goto next line
|
||||||
|
mov dl, 0
|
||||||
|
|
||||||
|
mov ah, 02h ; Set Cursor Position
|
||||||
|
int 10h
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
hello db 'Booting matOs', 0
|
||||||
|
|
||||||
|
main:
|
||||||
|
sti ; enable virtual interupts
|
||||||
|
mov [disk],dl ; save disk used to boot by bios
|
||||||
|
|
||||||
|
call display_enable
|
||||||
|
|
||||||
|
push hello
|
||||||
|
call println
|
||||||
|
add sp, 2
|
||||||
|
|
||||||
|
; Switch in 32bits Protected mode
|
||||||
|
|
||||||
|
; Activate A20 http://wiki.osdev.org/A20_Line to be able to access more than 1Mb memory
|
||||||
|
mov ah, 0h
|
||||||
|
mov ax, 0x2401
|
||||||
|
int 0x15
|
||||||
|
|
||||||
|
; Change video mode to display VGA
|
||||||
|
mov ax, 0x3
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; http://www.ctyme.com/intr/rb-0607.htm
|
||||||
|
; Bios read first 512 bytes, read next disk sector
|
||||||
|
mov ah, 0x2 ;read sectors
|
||||||
|
mov al, 15 ;sectors to read
|
||||||
|
mov ch, 0 ;cylinder idx
|
||||||
|
mov dh, 0 ;head idx
|
||||||
|
mov cl, 2 ;sector idx
|
||||||
|
mov dl, [disk] ;disk idx
|
||||||
|
mov bx, copy_target;target pointer
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
cli ; disable interruption when setting GDT
|
||||||
|
|
||||||
|
; switch in 32 bits
|
||||||
|
lgdt [gdt_pointer] ; switch in 32bits here
|
||||||
|
mov eax, cr0
|
||||||
|
or eax,0x1; set the protected mode bit on special CPU reg cr0
|
||||||
|
mov cr0, eax
|
||||||
|
jmp CODE_SEG:boot2 ; In protected mode we need to add the segment selector
|
||||||
|
|
||||||
|
; GDT table desciption could be found http://wiki.osdev.org/Global_Descriptor_Table
|
||||||
|
; here we define the 3 64bits segment needed: null segment, code segment and data segment
|
||||||
|
gdt_start: ;null segment
|
||||||
|
dq 0x0
|
||||||
|
gdt_code: ;code segment
|
||||||
|
dw 0xFFFF ; limit [0:15]
|
||||||
|
dw 0x0 ; base [0:15]
|
||||||
|
db 0x0 ; base [16:23]
|
||||||
|
db 10011010b ; access byte: Present(1)| Priv(2) 0 ->kernel 3->userspace | 1 | Executable(1) | Direction/Conformity (1) | RW(1) | Accessed(1)
|
||||||
|
db 11001111b ; Granularity(1) | Size (1) 0-> 16bit mode 1->32protected mode | 0 | 0 | Limit [16:19]
|
||||||
|
db 0x0 ; base [24:31]
|
||||||
|
gdt_data:
|
||||||
|
dw 0xFFFF
|
||||||
|
dw 0x0
|
||||||
|
db 0x0
|
||||||
|
db 10010010b
|
||||||
|
db 11001111b
|
||||||
|
db 0x0
|
||||||
|
gdt_end:
|
||||||
|
gdt_pointer:
|
||||||
|
dw gdt_end - gdt_start
|
||||||
|
dd gdt_start
|
||||||
|
disk:
|
||||||
|
db 0x0
|
||||||
|
CODE_SEG equ gdt_code - gdt_start
|
||||||
|
DATA_SEG equ gdt_data - gdt_start
|
||||||
|
|
||||||
|
times 510 - ($-$$) db 0
|
||||||
|
dw 0xaa55
|
||||||
|
copy_target:
|
||||||
|
bits 32
|
||||||
|
boot2:
|
||||||
|
mov ax, DATA_SEG ; set all segments to point to DATA_SEG https://en.wikipedia.org/wiki/X86_memory_segmentation
|
||||||
|
mov ds, ax ; Data segment
|
||||||
|
mov es, ax ; Extra Segment (for string operation)
|
||||||
|
mov fs, ax ; No Specific use
|
||||||
|
mov gs, ax ; No Specific use
|
||||||
|
mov ss, ax ; stack segment
|
||||||
|
mov esi,hello32
|
||||||
|
mov ebx,0xb8000 ; Cannot use BIOS anymore, use VGA Text buffer instead
|
||||||
|
|
||||||
|
.loop32:
|
||||||
|
lodsb
|
||||||
|
or al,al
|
||||||
|
jz halt
|
||||||
|
or eax,0x0100 ; blue bg
|
||||||
|
mov word [ebx], ax
|
||||||
|
add ebx,2
|
||||||
|
jmp .loop32
|
||||||
|
halt:
|
||||||
|
mov esp,kernel_stack_top
|
||||||
|
extern kmain
|
||||||
|
call kmain
|
||||||
|
cli
|
||||||
|
hlt
|
||||||
|
hello32: db "Hello 32 bits world!",0
|
||||||
|
section .bss
|
||||||
|
align 4
|
||||||
|
kernel_stack_bottom: equ $
|
||||||
|
resb 16384 ; 16 KB
|
||||||
|
kernel_stack_top:
|
Loading…
Reference in New Issue
Block a user