Compare commits
No commits in common. "master" and "experimental/user_space" have entirely different histories.
master
...
experiment
4
Makefile
4
Makefile
@ -9,8 +9,8 @@ GRUB_MKRESCUE = grub-mkrescue
|
|||||||
KERNEL = deados.bin
|
KERNEL = deados.bin
|
||||||
ISO = deados.iso
|
ISO = deados.iso
|
||||||
|
|
||||||
SOURCES_C = kernel.c tty.c idt.c timer.c io.c vga.c gdt.c sys.c irq.c isr.c keyboard.c shell.c string.c user_space.c syscall.c rtc.c
|
SOURCES_C = kernel.c tty.c idt.c timer.c io.c vga.c gdt.c sys.c irq.c isr.c keyboard.c shell.c string.c user_space.c syscall.c
|
||||||
SOURCES_ASM = boot.s idt_load.s gdt_flush.s tss_flush.s irq_flush.s isr_flush.s
|
SOURCES_ASM = boot.s idt_load.s gdt_flush.s irq_flush.s isr_flush.s tss_flush.s
|
||||||
OBJECTS = $(SOURCES_ASM:.s=.o) $(SOURCES_C:.c=.o)
|
OBJECTS = $(SOURCES_ASM:.s=.o) $(SOURCES_C:.c=.o)
|
||||||
|
|
||||||
ISO_DIR = isodir
|
ISO_DIR = isodir
|
||||||
|
15
README.md
15
README.md
@ -1,17 +1,16 @@
|
|||||||
# Simple OS implementation
|
# Simple OS implementation
|
||||||
|
|
||||||
DeadOS is a minimalist operating system designed for x86 architecture, created solely for educational purposes. It is an ideal platform for learning and understanding the fundamental concepts of operating system development. While it is not intended to evolve into a fully-fledged OS, DeadOS provides a straightforward and manageable codebase that makes it perfect for experimentation and study.
|
Just a simple OS implementation in C. For educational purposes only.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- make
|
|
||||||
- GCC Cross-Compiler
|
- GCC Cross-Compiler
|
||||||
- QEMU
|
- QEMU
|
||||||
|
|
||||||
## How to run
|
## How to run
|
||||||
|
|
||||||
- `make`
|
- `make`
|
||||||
- `qemu-system-x86_64 -monitor stdio -cdrom deados.iso`
|
- `qemu-system-i386 -cdrom deados.iso`
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@ -24,15 +23,11 @@ DeadOS is a minimalist operating system designed for x86 architecture, created s
|
|||||||
- [x] Timers
|
- [x] Timers
|
||||||
- [x] Interrupts
|
- [x] Interrupts
|
||||||
- [x] Kernel Extensions handling
|
- [x] Kernel Extensions handling
|
||||||
- [ ] Paging
|
|
||||||
- [] Memory Management
|
- [] Memory Management
|
||||||
- [] File System
|
- [] File System
|
||||||
- [x] User Space
|
- [] User Space
|
||||||
- [x] Syscalls
|
- [] Syscalls
|
||||||
- [ ] Multitasking
|
|
||||||
- [] stdlib
|
- [] stdlib
|
||||||
|
|
||||||
## Screenshot:
|
## Screenshot:
|
||||||
|
![image](https://github.com/assada/os/assets/1472664/9b67c053-36e1-4816-ad7f-093b89b03fce)
|
||||||
![image](https://github.com/assada/os/assets/1472664/b4e17d66-cb85-4652-9217-11608ad0753d)
|
|
||||||
|
|
||||||
|
12
boot.s
12
boot.s
@ -10,20 +10,22 @@
|
|||||||
.long FLAGS
|
.long FLAGS
|
||||||
.long CHECKSUM
|
.long CHECKSUM
|
||||||
|
|
||||||
.section .stack, "aw", @nobits
|
.section .bss
|
||||||
.global stack_top
|
.align 16
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
.skip 16384
|
.skip 16384
|
||||||
stack_top:
|
stack_top:
|
||||||
|
|
||||||
|
stack_top:
|
||||||
.section .text
|
.section .text
|
||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
movl $stack_top, %esp
|
mov $stack_top, %esp
|
||||||
|
|
||||||
push %ebx
|
push %ebx
|
||||||
|
|
||||||
call kernel_main
|
call kernel_main
|
||||||
1:
|
1:
|
||||||
jmp 1b
|
jmp 1b
|
||||||
|
|
||||||
|
|
||||||
|
.size _start, . - _start
|
||||||
|
18
build.sh
Executable file
18
build.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
set -ex
|
||||||
|
|
||||||
|
i686-elf-as boot.s -o boot.o
|
||||||
|
i686-elf-as idt_load.s -o idt_load.o
|
||||||
|
i686-elf-gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
|
||||||
|
i686-elf-gcc -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib boot.o kernel.o idt_load.o -lgcc
|
||||||
|
|
||||||
|
if grub-file --is-x86-multiboot myos.bin; then
|
||||||
|
echo multiboot confirmed
|
||||||
|
else
|
||||||
|
echo the file is not multiboot
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p isodir/boot/grub
|
||||||
|
cp myos.bin isodir/boot/myos.bin
|
||||||
|
cp grub.cfg isodir/boot/grub/grub.cfg
|
||||||
|
grub-mkrescue -o myos.iso isodir
|
34
gdt.c
34
gdt.c
@ -4,14 +4,14 @@
|
|||||||
#define GDT_ENTRY 6
|
#define GDT_ENTRY 6
|
||||||
|
|
||||||
Gdt_entry gdt[GDT_ENTRY];
|
Gdt_entry gdt[GDT_ENTRY];
|
||||||
Gdt_ptr gdtp;
|
Gdt_ptr gdt_ptr;
|
||||||
|
|
||||||
extern void gdt_flush(uint32_t);
|
extern void gdt_flush(void);
|
||||||
|
|
||||||
Tss_entry tss;
|
Tss_entry tss;
|
||||||
extern void tss_flush(void);
|
extern void tss_flush(void);
|
||||||
|
|
||||||
static void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity)
|
void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity)
|
||||||
{
|
{
|
||||||
gdt[num].base_low = base & 0xFFFF;
|
gdt[num].base_low = base & 0xFFFF;
|
||||||
gdt[num].base_middle = (base >> 16) & 0xFF;
|
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||||
@ -25,17 +25,14 @@ static void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t acc
|
|||||||
gdt[num].access = access;
|
gdt[num].access = access;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tss_install(uint8_t num, uint16_t kernel_ss, uint16_t kernel_esp)
|
void tss_set_gate(uint32_t num, uint16_t ss0, uint32_t esp0)
|
||||||
{
|
{
|
||||||
uint32_t base = (uint32_t)&tss;
|
uint32_t base = (uint32_t)&tss;
|
||||||
uint32_t limit = base + sizeof(Tss_entry);
|
uint32_t limit = base + sizeof(Tss_entry);
|
||||||
|
|
||||||
gdt_set_gate(num, base, limit, 0xE9, 0x0);
|
gdt_set_gate(num, base, limit, 0xE9, 0x0);
|
||||||
|
memset(&tss, 0x0, sizeof(Tss_entry));
|
||||||
memset(&tss, 0, sizeof(Tss_entry));
|
tss.ss0 = ss0;
|
||||||
|
tss.esp0 = esp0;
|
||||||
tss.ss0 = kernel_ss;
|
|
||||||
tss.esp0 = kernel_esp + 0x1000; // SHIT
|
|
||||||
|
|
||||||
tss.cs = 0x1B;
|
tss.cs = 0x1B;
|
||||||
tss.ss = 0x23;
|
tss.ss = 0x23;
|
||||||
@ -47,17 +44,18 @@ static void tss_install(uint8_t num, uint16_t kernel_ss, uint16_t kernel_esp)
|
|||||||
|
|
||||||
void gdt_install()
|
void gdt_install()
|
||||||
{
|
{
|
||||||
|
|
||||||
gdt_set_gate(0, 0x0, 0x0, 0x0, 0x0); // Null segment
|
gdt_set_gate(0, 0x0, 0x0, 0x0, 0x0); // Null segment
|
||||||
gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xCF); // 0x08 Kernel code segment
|
gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xC0); // 0x08 Kernel code segment
|
||||||
gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xCF); // 0x10 Kernel Data segment
|
gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xC0); // 0x10 Kernel data segment
|
||||||
gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xCF); // 0x18 User code segment
|
gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xC0); // 0x18 User code segment
|
||||||
gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xCF); // 0x20 User data segment
|
gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xC0); // 0x20 User data segment
|
||||||
|
|
||||||
tss_install(5, 0x10, stack_top);
|
tss_set_gate(5, 0x10, 0);
|
||||||
|
|
||||||
gdtp.limit = (sizeof(Gdt_entry) * GDT_ENTRY) - 1;
|
gdt_ptr.limit = (sizeof(Gdt_entry) * GDT_ENTRY) - 1;
|
||||||
gdtp.base = (uint32_t)&gdt;
|
gdt_ptr.base = (uint32_t)&gdt;
|
||||||
|
|
||||||
gdt_flush((uint32_t)&gdtp);
|
gdt_flush();
|
||||||
tss_flush();
|
tss_flush();
|
||||||
}
|
}
|
||||||
|
4
gdt.h
4
gdt.h
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern uint32_t stack_top;
|
|
||||||
|
|
||||||
typedef struct gdt_entry_t Gdt_entry;
|
typedef struct gdt_entry_t Gdt_entry;
|
||||||
struct gdt_entry_t
|
struct gdt_entry_t
|
||||||
{
|
{
|
||||||
@ -23,7 +21,7 @@ struct gdt_ptr_t
|
|||||||
uint32_t base;
|
uint32_t base;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
static void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity);
|
void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity);
|
||||||
void gdt_install();
|
void gdt_install();
|
||||||
|
|
||||||
void set_kernel_stack(uint32_t stack);
|
void set_kernel_stack(uint32_t stack);
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
.global gdt_flush
|
.section .text
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
.global gdt_flush
|
||||||
|
.type gdt_flush, @function
|
||||||
gdt_flush:
|
gdt_flush:
|
||||||
lgdt gdtp
|
lgdt gdt_ptr
|
||||||
jmp $0x08, $reload_cs
|
jmp $0x08, $reload_cs
|
||||||
|
|
||||||
reload_cs:
|
reload_cs:
|
||||||
|
20
idt.c
20
idt.c
@ -1,8 +1,24 @@
|
|||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define IDT_ENTRIES 256
|
||||||
|
|
||||||
|
struct idt_entry
|
||||||
|
{
|
||||||
|
uint16_t base_lo;
|
||||||
|
uint16_t sel;
|
||||||
|
uint8_t always0;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t base_hi;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct idt_ptr
|
||||||
|
{
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct idt_entry idt[IDT_ENTRIES];
|
struct idt_entry idt[IDT_ENTRIES];
|
||||||
struct idt_ptr idtp;
|
struct idt_ptr idtp;
|
||||||
|
17
idt.h
17
idt.h
@ -3,23 +3,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define IDT_ENTRIES 256
|
|
||||||
|
|
||||||
struct idt_entry
|
|
||||||
{
|
|
||||||
uint16_t base_lo;
|
|
||||||
uint16_t sel;
|
|
||||||
uint8_t always0;
|
|
||||||
uint8_t flags;
|
|
||||||
uint16_t base_hi;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct idt_ptr
|
|
||||||
{
|
|
||||||
uint16_t limit;
|
|
||||||
uint32_t base;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
extern void idt_load();
|
extern void idt_load();
|
||||||
|
|
||||||
void idt_install();
|
void idt_install();
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
.section .text
|
.section .text
|
||||||
|
.align 4
|
||||||
|
|
||||||
.global idt_load
|
.global idt_load
|
||||||
|
.type idt_load, @function
|
||||||
idt_load:
|
idt_load:
|
||||||
lidt idtp
|
lidt idtp
|
||||||
ret
|
ret
|
||||||
|
@ -6,9 +6,13 @@
|
|||||||
typedef struct stack_t Stack;
|
typedef struct stack_t Stack;
|
||||||
struct stack_t
|
struct stack_t
|
||||||
{
|
{
|
||||||
|
/* Pushed the segs last */
|
||||||
uint32_t gs, fs, es, ds;
|
uint32_t gs, fs, es, ds;
|
||||||
|
/* Pushed by 'pusha' */
|
||||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||||
|
/* Our 'push #' and ecodes do this */
|
||||||
uint32_t id, err_code;
|
uint32_t id, err_code;
|
||||||
|
/* Pushed by the processor automatically */
|
||||||
uint32_t eip, cs, eflags, useresp, ss;
|
uint32_t eip, cs, eflags, useresp, ss;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
14
io.c
14
io.c
@ -18,17 +18,3 @@ void io_wait(void)
|
|||||||
"1:jmp 2f\n\t"
|
"1:jmp 2f\n\t"
|
||||||
"2:");
|
"2:");
|
||||||
}
|
}
|
||||||
|
|
||||||
void outb_wait(uint16_t port, uint8_t val)
|
|
||||||
{
|
|
||||||
outb(port, val);
|
|
||||||
io_wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t inb_wait(uint16_t port)
|
|
||||||
{
|
|
||||||
uint8_t ret;
|
|
||||||
ret = inb(port);
|
|
||||||
io_wait();
|
|
||||||
return ret;
|
|
||||||
}
|
|
3
io.h
3
io.h
@ -7,7 +7,4 @@ void outb(uint16_t port, uint8_t val);
|
|||||||
uint8_t inb(uint16_t port);
|
uint8_t inb(uint16_t port);
|
||||||
void io_wait(void);
|
void io_wait(void);
|
||||||
|
|
||||||
void outb_wait(uint16_t port, uint8_t val);
|
|
||||||
uint8_t inb_wait(uint16_t port);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
31
irq.c
31
irq.c
@ -4,6 +4,7 @@
|
|||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
|
#include "tty.h"
|
||||||
|
|
||||||
extern void irq0(void);
|
extern void irq0(void);
|
||||||
extern void irq1(void);
|
extern void irq1(void);
|
||||||
@ -39,23 +40,19 @@ void irq_call_handler(Stack *registers)
|
|||||||
void (*handler)(Stack *registers);
|
void (*handler)(Stack *registers);
|
||||||
handler = irq_routines[registers->id - 32];
|
handler = irq_routines[registers->id - 32];
|
||||||
if (handler)
|
if (handler)
|
||||||
{
|
|
||||||
handler(registers);
|
handler(registers);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void irq_remap(void)
|
static void irq_remap(void) // PIC REMAP
|
||||||
{
|
{
|
||||||
outb(0x20, 0x11);
|
outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
|
||||||
outb(0xA0, 0x11);
|
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
|
||||||
outb(0x21, 0x20);
|
outb(PIC1_DATA, PIC1_OFFSET);
|
||||||
outb(0xA1, 0x28);
|
outb(PIC2_DATA, PIC2_OFFSET);
|
||||||
outb(0x21, 0x04);
|
outb(PIC1_DATA, 0x04);
|
||||||
outb(0xA1, 0x02);
|
outb(PIC2_DATA, 0x02);
|
||||||
outb(0x21, 0x01);
|
outb(PIC1_DATA, ICW4_8086);
|
||||||
outb(0xA1, 0x01);
|
outb(PIC2_DATA, ICW4_8086);
|
||||||
outb(0x21, 0x00);
|
|
||||||
outb(0xA1, 0x00);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_install(void)
|
void irq_install(void)
|
||||||
@ -87,7 +84,9 @@ void irq_handler(Stack *registers)
|
|||||||
irq_call_handler(registers);
|
irq_call_handler(registers);
|
||||||
|
|
||||||
if (registers->id >= 40)
|
if (registers->id >= 40)
|
||||||
outb(0xA0, 0x20);
|
{
|
||||||
|
outb(PIC2_CMD, PIC_EOI);
|
||||||
outb(0x20, 0x20);
|
}
|
||||||
|
|
||||||
|
outb(PIC1_CMD, PIC_EOI);
|
||||||
}
|
}
|
@ -8,7 +8,7 @@
|
|||||||
cli
|
cli
|
||||||
push $0x00
|
push $0x00
|
||||||
push $\entry
|
push $\entry
|
||||||
jmp irq_flush
|
jmp irq_common_stub
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
IRQ 0, 32
|
IRQ 0, 32
|
||||||
@ -28,9 +28,8 @@ IRQ 13, 45
|
|||||||
IRQ 14, 46
|
IRQ 14, 46
|
||||||
IRQ 15, 47
|
IRQ 15, 47
|
||||||
|
|
||||||
irq_flush:
|
irq_common_stub:
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
push %ds
|
push %ds
|
||||||
push %es
|
push %es
|
||||||
push %fs
|
push %fs
|
||||||
|
10
isr.c
10
isr.c
@ -55,10 +55,8 @@ void isr_call_handler(Stack *registers)
|
|||||||
void (*handler)(Stack *registers);
|
void (*handler)(Stack *registers);
|
||||||
handler = isr_routines[registers->id];
|
handler = isr_routines[registers->id];
|
||||||
if (handler)
|
if (handler)
|
||||||
{
|
|
||||||
handler(registers);
|
handler(registers);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void isr_install(void)
|
void isr_install(void)
|
||||||
{
|
{
|
||||||
@ -141,18 +139,20 @@ static const char *exception_messages[] =
|
|||||||
|
|
||||||
void fault_handler(Stack *registers)
|
void fault_handler(Stack *registers)
|
||||||
{
|
{
|
||||||
|
// check this
|
||||||
if (registers->id == 128)
|
if (registers->id == 128)
|
||||||
|
{
|
||||||
isr_call_handler(registers);
|
isr_call_handler(registers);
|
||||||
|
}
|
||||||
|
|
||||||
if (registers->id < 32)
|
if (registers->id < 32)
|
||||||
{
|
{
|
||||||
terminal_printf("Exception. System Halted!\n");
|
|
||||||
terminal_printf("Exception: ");
|
|
||||||
terminal_printf(exception_messages[registers->id]);
|
|
||||||
|
|
||||||
isr_call_handler(registers);
|
isr_call_handler(registers);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
{
|
||||||
sys_halt();
|
sys_halt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
75
isr_flush.s
75
isr_flush.s
@ -1,13 +1,14 @@
|
|||||||
.section .text
|
.section .text
|
||||||
.align 4
|
.align 4
|
||||||
|
|
||||||
|
|
||||||
.macro ISR_NO_ERR index
|
.macro ISR_NO_ERR index
|
||||||
.global isr\index
|
.global isr\index
|
||||||
isr\index:
|
isr\index:
|
||||||
cli
|
cli
|
||||||
push $0
|
push $0
|
||||||
push $\index
|
push $\index
|
||||||
jmp isr_flush
|
jmp isr_common_stub
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro ISR_ERR index
|
.macro ISR_ERR index
|
||||||
@ -15,31 +16,49 @@
|
|||||||
isr\index:
|
isr\index:
|
||||||
cli
|
cli
|
||||||
push $\index
|
push $\index
|
||||||
jmp isr_flush
|
jmp isr_common_stub
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
/* Division By Zero Exception */
|
||||||
ISR_NO_ERR 0 # Division By Zero Exception
|
ISR_NO_ERR 0
|
||||||
ISR_NO_ERR 1 # Debug Exception
|
/* Debug Exception */
|
||||||
ISR_NO_ERR 2 # Non Maskable Interrupt Exception
|
ISR_NO_ERR 1
|
||||||
ISR_NO_ERR 3 # Breakpoint Exception
|
/* Non Maskable Interrupt Exception */
|
||||||
ISR_NO_ERR 4 # Into Detected Overflow Exception
|
ISR_NO_ERR 2
|
||||||
ISR_NO_ERR 5 # Out of Bounds Exception
|
/* Breakpoint Exception */
|
||||||
ISR_NO_ERR 6 # Invalid Opcode Exception
|
ISR_NO_ERR 3
|
||||||
ISR_NO_ERR 7 # No Coprocessor Exception
|
/* Into Detected Overflow Exception */
|
||||||
ISR_ERR 8 # Double Fault Exception
|
ISR_NO_ERR 4
|
||||||
ISR_NO_ERR 9 # Coprocessor Segment Overrun Exception
|
/* Out of Bounds Exception */
|
||||||
ISR_ERR 10 # Bad TSS Exception
|
ISR_NO_ERR 5
|
||||||
ISR_ERR 11 # Segment Not Present Exception
|
/* Invalid Opcode Exception */
|
||||||
ISR_ERR 12 # Stack Fault Exception
|
ISR_NO_ERR 6
|
||||||
ISR_ERR 13 # General Protection Fault Exception
|
/* No Coprocessor Exception */
|
||||||
ISR_ERR 14 # Page Fault Exception
|
ISR_NO_ERR 7
|
||||||
ISR_NO_ERR 15 # Unknown Interrupt Exception
|
/* Double Fault Exception */
|
||||||
ISR_NO_ERR 16 # Coprocessor Fault Exception
|
ISR_ERR 8
|
||||||
ISR_NO_ERR 17 # Alignment Check Exception
|
/* Coprocessor Segment Overrun Exception */
|
||||||
ISR_NO_ERR 18 # Machine Check Exception
|
ISR_NO_ERR 9
|
||||||
|
/* Bad TSS Exception */
|
||||||
ISR_NO_ERR 19 # Other
|
ISR_ERR 10
|
||||||
|
/* Segment Not Present Exception */
|
||||||
|
ISR_ERR 11
|
||||||
|
/* Stack Fault Exception */
|
||||||
|
ISR_ERR 12
|
||||||
|
/* General Protection Fault Exception */
|
||||||
|
ISR_ERR 13
|
||||||
|
/* Page Fault Exception */
|
||||||
|
ISR_ERR 14
|
||||||
|
/* Unknown Interrupt Exception */
|
||||||
|
ISR_NO_ERR 15
|
||||||
|
/* Coprocessor Fault Exception */
|
||||||
|
ISR_NO_ERR 16
|
||||||
|
/* Alignment Check Exception */
|
||||||
|
ISR_NO_ERR 17
|
||||||
|
/* Machine Check Exception */
|
||||||
|
ISR_NO_ERR 18
|
||||||
|
/* All the others are reserved */
|
||||||
|
ISR_NO_ERR 19
|
||||||
ISR_NO_ERR 20
|
ISR_NO_ERR 20
|
||||||
ISR_NO_ERR 21
|
ISR_NO_ERR 21
|
||||||
ISR_NO_ERR 22
|
ISR_NO_ERR 22
|
||||||
@ -52,10 +71,10 @@ ISR_NO_ERR 28
|
|||||||
ISR_NO_ERR 29
|
ISR_NO_ERR 29
|
||||||
ISR_NO_ERR 30
|
ISR_NO_ERR 30
|
||||||
ISR_NO_ERR 31
|
ISR_NO_ERR 31
|
||||||
ISR_NO_ERR 128 # 80h syscall
|
/* Syscall */
|
||||||
|
ISR_NO_ERR 128
|
||||||
|
|
||||||
|
isr_common_stub:
|
||||||
isr_flush:
|
|
||||||
pusha
|
pusha
|
||||||
push %ds
|
push %ds
|
||||||
push %es
|
push %es
|
||||||
@ -67,11 +86,9 @@ isr_flush:
|
|||||||
mov %ax, %es
|
mov %ax, %es
|
||||||
mov %ax, %fs
|
mov %ax, %fs
|
||||||
mov %ax, %gs
|
mov %ax, %gs
|
||||||
|
|
||||||
mov %esp, %eax
|
mov %esp, %eax
|
||||||
push %eax
|
push %eax
|
||||||
mov $fault_handler, %eax
|
mov $fault_handler, %eax
|
||||||
|
|
||||||
call *%eax
|
call *%eax
|
||||||
pop %eax
|
pop %eax
|
||||||
|
|
||||||
|
35
kernel.c
35
kernel.c
@ -1,7 +1,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
@ -12,7 +11,6 @@
|
|||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "user_space.h"
|
#include "user_space.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "rtc.h"
|
|
||||||
|
|
||||||
void kernel_main(void)
|
void kernel_main(void)
|
||||||
{
|
{
|
||||||
@ -26,24 +24,31 @@ void kernel_main(void)
|
|||||||
timer_install();
|
timer_install();
|
||||||
keyboard_install();
|
keyboard_install();
|
||||||
|
|
||||||
rtc_init();
|
|
||||||
|
|
||||||
syscall_init();
|
syscall_init();
|
||||||
enter_user_space();
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
terminal_printc("&cDead &7");
|
||||||
|
terminal_putchar('0' + (i / 10));
|
||||||
|
terminal_putchar('0' + (i % 10));
|
||||||
|
terminal_printc("\n");
|
||||||
|
delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
enter_user_space_v2();
|
||||||
{
|
|
||||||
for (int i = 1; i < 4; i++)
|
|
||||||
{
|
|
||||||
terminal_printf("&cTest &7%d\n", i);
|
|
||||||
delay(200);
|
|
||||||
}
|
}
|
||||||
terminal_clear();
|
|
||||||
|
|
||||||
terminal_printf("Welcome to &cDeadOS&7.\n");
|
void user_main(void)
|
||||||
terminal_printf("You are now in user space.\n");
|
{
|
||||||
terminal_printf("Type 'help' for a list of available commands.\n");
|
terminal_printc("Welcome to &cDeadOS&7.\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
terminal_printc("&cDead2 &7");
|
||||||
|
terminal_putchar('0' + (i / 10));
|
||||||
|
terminal_putchar('0' + (i % 10));
|
||||||
|
terminal_printc("\n");
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
shell_init();
|
shell_init();
|
||||||
}
|
}
|
11
linker.ld
11
linker.ld
@ -1,27 +1,38 @@
|
|||||||
|
/* The bootloader will look at this image and start execution at the symbol
|
||||||
|
designated at the entry point. */
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
|
/* Tell where the various sections of the object files will be put in the final
|
||||||
|
kernel image. */
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
|
/* The kernel is situated at 1 MiB */
|
||||||
. = 1M;
|
. = 1M;
|
||||||
|
|
||||||
kernel_start = .;
|
kernel_start = .;
|
||||||
|
|
||||||
|
/* 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)
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(.multiboot)
|
*(.multiboot)
|
||||||
*(.text)
|
*(.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read-only data */
|
||||||
.rodata BLOCK(4K) : ALIGN(4K)
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read-write data (initialized) */
|
||||||
.data BLOCK(4K) : ALIGN(4K)
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(.data)
|
*(.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read-write data (uninitialized) and stack */
|
||||||
.bss BLOCK(4K) : ALIGN(4K)
|
.bss BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(.bss)
|
*(.bss)
|
||||||
|
12
pit_handler.s
Normal file
12
pit_handler.s
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.section .text
|
||||||
|
.global pit_handler_asm
|
||||||
|
|
||||||
|
pit_handler_asm:
|
||||||
|
push %eax # Save the registers used by the C handler
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
call pit_handler # Call the C handler
|
||||||
|
pop %edx # Restore the registers in reverse order
|
||||||
|
pop %ecx
|
||||||
|
pop %eax
|
||||||
|
iret # Return from interrupt
|
79
rtc.c
79
rtc.c
@ -1,79 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include "io.h"
|
|
||||||
#include "interrupts.h"
|
|
||||||
#include "rtc.h"
|
|
||||||
|
|
||||||
uint8_t read_cmos(uint16_t reg)
|
|
||||||
{
|
|
||||||
outb_wait(CMOS_ADDRESS, reg);
|
|
||||||
return inb_wait(CMOS_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t get_update_in_progress_flag()
|
|
||||||
{
|
|
||||||
outb_wait(CMOS_ADDRESS, 0x0A);
|
|
||||||
return inb_wait(CMOS_DATA) & 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_handler()
|
|
||||||
{
|
|
||||||
outb_wait(CMOS_ADDRESS, 0x0C);
|
|
||||||
inb_wait(CMOS_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t bcd_to_bin(uint8_t val)
|
|
||||||
{
|
|
||||||
return ((val / 16) * 10) + (val & 0x0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Rtc_time get_rtc_time()
|
|
||||||
{
|
|
||||||
struct Rtc_time time;
|
|
||||||
|
|
||||||
while (get_update_in_progress_flag())
|
|
||||||
;
|
|
||||||
|
|
||||||
time.sec = read_cmos(REG_SECONDS);
|
|
||||||
|
|
||||||
time.min = read_cmos(REG_MINUTES);
|
|
||||||
time.hour = read_cmos(REG_HOURS);
|
|
||||||
|
|
||||||
time.mday = read_cmos(REG_DAY);
|
|
||||||
time.mon = read_cmos(REG_MONTH);
|
|
||||||
time.year = read_cmos(REG_YEAR);
|
|
||||||
|
|
||||||
uint8_t registerB = read_cmos(0x0B);
|
|
||||||
|
|
||||||
if (!(registerB & 0x04))
|
|
||||||
{
|
|
||||||
time.sec = bcd_to_bin(time.sec);
|
|
||||||
time.min = bcd_to_bin(time.min);
|
|
||||||
time.hour = bcd_to_bin(time.hour);
|
|
||||||
time.mday = bcd_to_bin(time.mday);
|
|
||||||
time.mon = bcd_to_bin(time.mon);
|
|
||||||
time.year = bcd_to_bin(time.year);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time.year < 70)
|
|
||||||
{
|
|
||||||
time.year += 100;
|
|
||||||
}
|
|
||||||
else if (time.year >= 100)
|
|
||||||
{
|
|
||||||
time.year -= 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
time.year += 1900;
|
|
||||||
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_init()
|
|
||||||
{
|
|
||||||
outb_wait(CMOS_ADDRESS, 0x8A);
|
|
||||||
uint8_t prev = inb_wait(CMOS_DATA);
|
|
||||||
outb_wait(CMOS_ADDRESS, 0x8A);
|
|
||||||
outb_wait(CMOS_DATA, (prev & 0xF0) | 0x0F);
|
|
||||||
|
|
||||||
irq_install_handler(8, rtc_handler);
|
|
||||||
}
|
|
29
rtc.h
29
rtc.h
@ -1,29 +0,0 @@
|
|||||||
#ifndef RTC_H
|
|
||||||
#define RTC_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define CMOS_ADDRESS 0x70
|
|
||||||
#define CMOS_DATA 0x71
|
|
||||||
|
|
||||||
#define REG_SECONDS 0x00
|
|
||||||
#define REG_MINUTES 0x02
|
|
||||||
#define REG_HOURS 0x04
|
|
||||||
#define REG_DAY 0x07
|
|
||||||
#define REG_MONTH 0x08
|
|
||||||
#define REG_YEAR 0x09
|
|
||||||
|
|
||||||
struct Rtc_time
|
|
||||||
{
|
|
||||||
uint8_t sec;
|
|
||||||
uint8_t min;
|
|
||||||
uint8_t hour;
|
|
||||||
uint8_t mday;
|
|
||||||
uint8_t mon;
|
|
||||||
uint16_t year;
|
|
||||||
};
|
|
||||||
|
|
||||||
void rtc_init();
|
|
||||||
struct Rtc_time get_rtc_time();
|
|
||||||
|
|
||||||
#endif
|
|
45
shell.c
45
shell.c
@ -3,7 +3,6 @@
|
|||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "rtc.h"
|
|
||||||
|
|
||||||
void shell_init(void)
|
void shell_init(void)
|
||||||
{
|
{
|
||||||
@ -13,7 +12,8 @@ void shell_init(void)
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
terminal_printf("&7dead@&croot&7: /> ");
|
terminal_printc("\n");
|
||||||
|
terminal_printc("&7dead@&croot&7: /> ");
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
c = 0;
|
c = 0;
|
||||||
@ -26,7 +26,7 @@ void shell_init(void)
|
|||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
terminal_printf("\b \b");
|
terminal_printc("\b \b");
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,30 +49,21 @@ void shell_init(void)
|
|||||||
|
|
||||||
void shell_help_command(void)
|
void shell_help_command(void)
|
||||||
{
|
{
|
||||||
terminal_printf("List of commands:\n");
|
terminal_printc("List of commands:\n");
|
||||||
terminal_printf("help - Print out the list of commands.\n");
|
terminal_printc("help - Print out the list of commands.\n");
|
||||||
terminal_printf("exit - Exit the shell.\n");
|
terminal_printc("exit - Exit the shell.\n");
|
||||||
terminal_printf("echo - Print out the message. &eWITH colors!&7\n");
|
terminal_printc("echo - Print out the message. &eWITH colors!&7\n");
|
||||||
terminal_printf("clear - Clear the terminal.\n");
|
terminal_printc("clear - Clear the terminal.\n");
|
||||||
terminal_printf("time - Print out the current time. (UTC)\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void shell_exit_command(void)
|
void shell_exit_command(void)
|
||||||
{
|
{
|
||||||
terminal_printf("Exiting shell...\n");
|
terminal_printc("Exiting shell...\n");
|
||||||
terminal_printf("Goodbye!\n");
|
terminal_printc("Goodbye!\n");
|
||||||
while (1)
|
while (1)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shell_time_command(void)
|
|
||||||
{
|
|
||||||
struct Rtc_time current_time = get_rtc_time();
|
|
||||||
terminal_printf("Current time: %02d:%02d:%02d %02d.%02d.%d\n",
|
|
||||||
current_time.hour, current_time.min, current_time.sec,
|
|
||||||
current_time.mday, current_time.mon, current_time.year);
|
|
||||||
}
|
|
||||||
|
|
||||||
void shell_echo_command(char *input)
|
void shell_echo_command(char *input)
|
||||||
{
|
{
|
||||||
char *message = input;
|
char *message = input;
|
||||||
@ -82,8 +73,8 @@ void shell_echo_command(char *input)
|
|||||||
message++;
|
message++;
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal_printf(message);
|
terminal_printc(message);
|
||||||
terminal_printf("\n");
|
terminal_printc("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void shell_parse_input(char *input)
|
void shell_parse_input(char *input)
|
||||||
@ -112,15 +103,11 @@ void shell_parse_input(char *input)
|
|||||||
{
|
{
|
||||||
terminal_clear();
|
terminal_clear();
|
||||||
}
|
}
|
||||||
else if (strcmp(command, "time") == 0)
|
|
||||||
{
|
|
||||||
shell_time_command();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
terminal_printf("Unknown command: '");
|
terminal_printc("Unknown command: '");
|
||||||
terminal_print(command);
|
terminal_writestring(command);
|
||||||
terminal_printf("'\n");
|
terminal_printc("'\n");
|
||||||
terminal_printf("Type 'help' to print out the list of commands.\n");
|
terminal_printc("Type 'help' to print out the list of commands.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
42
string.c
42
string.c
@ -21,19 +21,6 @@ void *memset(void *ptr, int value, size_t size)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void memcpy(void *vd, const void *vs, unsigned length)
|
|
||||||
{
|
|
||||||
char *d = vd;
|
|
||||||
const char *s = vs;
|
|
||||||
while (length)
|
|
||||||
{
|
|
||||||
*d = *s;
|
|
||||||
d++;
|
|
||||||
s++;
|
|
||||||
length--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int strcmp(const char *str1, const char *str2)
|
int strcmp(const char *str1, const char *str2)
|
||||||
{
|
{
|
||||||
while (*str1 && (*str1 == *str2))
|
while (*str1 && (*str1 == *str2))
|
||||||
@ -107,32 +94,3 @@ char *strtok(char *str, const char *delim)
|
|||||||
|
|
||||||
return token_start;
|
return token_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void itoa(int value, char *str, int base)
|
|
||||||
{
|
|
||||||
char *rc;
|
|
||||||
char *ptr;
|
|
||||||
char *low;
|
|
||||||
|
|
||||||
if (value < 0 && base == 10)
|
|
||||||
{
|
|
||||||
*str++ = '-';
|
|
||||||
value = -value;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ptr = str;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
*ptr++ = "0123456789abcdef"[value % base];
|
|
||||||
value /= base;
|
|
||||||
} while (value);
|
|
||||||
|
|
||||||
*ptr-- = '\0';
|
|
||||||
|
|
||||||
for (low = rc; low < ptr; low++, ptr--)
|
|
||||||
{
|
|
||||||
char tmp = *low;
|
|
||||||
*low = *ptr;
|
|
||||||
*ptr = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
2
string.h
2
string.h
@ -7,9 +7,7 @@ char *strchr(const char *str, int c);
|
|||||||
char *strtok(char *str, const char *delim);
|
char *strtok(char *str, const char *delim);
|
||||||
int strcmp(const char *str1, const char *str2);
|
int strcmp(const char *str1, const char *str2);
|
||||||
size_t strlen(const char *str);
|
size_t strlen(const char *str);
|
||||||
void itoa(int value, char *str, int base);
|
|
||||||
|
|
||||||
void *memset(void *ptr, int value, size_t size);
|
void *memset(void *ptr, int value, size_t size);
|
||||||
void memcpy(void *vd, const void *vs, unsigned length);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
11
syscall.c
11
syscall.c
@ -5,14 +5,17 @@
|
|||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
#include "timer.h"
|
|
||||||
#include "rtc.h"
|
|
||||||
|
|
||||||
#define NB_SYSCALL 3
|
#define NB_SYSCALL 8
|
||||||
|
|
||||||
void *syscalls[NB_SYSCALL] = {
|
void *syscalls[NB_SYSCALL] = {
|
||||||
|
terminal_writestring,
|
||||||
keyboard_getchar,
|
keyboard_getchar,
|
||||||
get_rtc_time,
|
terminal_printc,
|
||||||
|
terminal_clear,
|
||||||
|
terminal_putchar,
|
||||||
|
terminal_putentryat,
|
||||||
|
keyboard_clear_buffer,
|
||||||
|
|
||||||
sys_halt};
|
sys_halt};
|
||||||
|
|
||||||
|
35
timer.c
35
timer.c
@ -1,27 +1,25 @@
|
|||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "interrupts.h"
|
|
||||||
#include "io.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
|
||||||
volatile uint32_t timer_ticks = 0;
|
volatile uint32_t tick = 0;
|
||||||
|
|
||||||
void delay(const uint32_t ticks)
|
void pit_handler(Stack *registers)
|
||||||
{
|
{
|
||||||
uint32_t total_ticks = timer_ticks + ticks;
|
++tick;
|
||||||
while (timer_ticks < total_ticks)
|
}
|
||||||
|
|
||||||
|
void delay(uint32_t milliseconds)
|
||||||
|
{
|
||||||
|
uint32_t end = tick + milliseconds;
|
||||||
|
while (tick < end)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer_handler(Stack *registers)
|
void pit_set_frequency(uint32_t frequency)
|
||||||
{
|
{
|
||||||
++timer_ticks;
|
uint32_t divisor = PIT_FREQUENCY / frequency;
|
||||||
}
|
|
||||||
|
|
||||||
static void timer_phase(const uint32_t hz)
|
|
||||||
{
|
|
||||||
uint32_t divisor = PIT_FREQUENCY / hz;
|
|
||||||
|
|
||||||
outb(PIT_COMMAND, 0x36);
|
outb(PIT_COMMAND, 0x36);
|
||||||
outb(PIT_CHANNEL_0, divisor & 0xFF);
|
outb(PIT_CHANNEL_0, divisor & 0xFF);
|
||||||
outb(PIT_CHANNEL_0, divisor >> 8);
|
outb(PIT_CHANNEL_0, divisor >> 8);
|
||||||
@ -29,7 +27,6 @@ static void timer_phase(const uint32_t hz)
|
|||||||
|
|
||||||
void timer_install(void)
|
void timer_install(void)
|
||||||
{
|
{
|
||||||
irq_install_handler(0, timer_handler);
|
irq_install_handler(0, pit_handler);
|
||||||
|
pit_set_frequency(1000);
|
||||||
timer_phase(1000);
|
|
||||||
}
|
}
|
||||||
|
5
timer.h
5
timer.h
@ -7,7 +7,12 @@
|
|||||||
#define PIT_CHANNEL_0 0x40
|
#define PIT_CHANNEL_0 0x40
|
||||||
#define PIT_COMMAND 0x43
|
#define PIT_COMMAND 0x43
|
||||||
|
|
||||||
|
extern void pit_handler_asm(); // defined in pit_handler.s remove this
|
||||||
|
|
||||||
|
void pit_handler();
|
||||||
void delay(uint32_t milliseconds);
|
void delay(uint32_t milliseconds);
|
||||||
|
void pit_set_frequency(uint32_t frequency);
|
||||||
|
void pic_remap(int offset1, int offset2); // moved to irq_remap
|
||||||
void timer_install(void);
|
void timer_install(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
159
tty.c
159
tty.c
@ -1,11 +1,10 @@
|
|||||||
|
#include "tty.h"
|
||||||
|
#include "vga.h"
|
||||||
|
#include "io.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "tty.h"
|
|
||||||
#include "vga.h"
|
|
||||||
#include "io.h"
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
static const size_t VGA_WIDTH = 80;
|
static const size_t VGA_WIDTH = 80;
|
||||||
@ -22,9 +21,13 @@ void terminal_initialize(void)
|
|||||||
terminal_column = 0;
|
terminal_column = 0;
|
||||||
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||||
terminal_buffer = (uint16_t *)0xB8000;
|
terminal_buffer = (uint16_t *)0xB8000;
|
||||||
for (size_t i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++)
|
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||||
{
|
{
|
||||||
terminal_buffer[i] = vga_entry(' ', terminal_color);
|
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||||
|
{
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,31 +63,37 @@ void terminal_scroll(void)
|
|||||||
terminal_row = VGA_HEIGHT - 1;
|
terminal_row = VGA_HEIGHT - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_update_cursor(void)
|
|
||||||
{
|
|
||||||
uint16_t pos = terminal_row * VGA_WIDTH + terminal_column;
|
|
||||||
|
|
||||||
outb(0x3D4, 14);
|
|
||||||
outb(0x3D5, pos >> 8);
|
|
||||||
outb(0x3D4, 15);
|
|
||||||
outb(0x3D5, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void terminal_backspace(void)
|
static void terminal_backspace(void)
|
||||||
{
|
{
|
||||||
if (terminal_column == 0)
|
if (terminal_column == 0)
|
||||||
{
|
{
|
||||||
terminal_column = VGA_WIDTH - 1;
|
terminal_column = VGA_WIDTH - 1;
|
||||||
if (terminal_row > 0)
|
if (terminal_row == 0)
|
||||||
|
{
|
||||||
|
terminal_column = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
--terminal_row;
|
--terminal_row;
|
||||||
}
|
}
|
||||||
|
uint16_t empty = vga_entry(' ', terminal_color);
|
||||||
|
uint16_t index = terminal_pos(terminal_column, terminal_row);
|
||||||
|
while (terminal_column > 0 && terminal_buffer[index] == empty)
|
||||||
|
{
|
||||||
|
--terminal_column;
|
||||||
|
index = terminal_pos(terminal_column, terminal_row);
|
||||||
|
}
|
||||||
|
if (terminal_buffer[index] != empty && terminal_column + 1 < VGA_WIDTH)
|
||||||
|
{
|
||||||
|
++terminal_column;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
--terminal_column;
|
--terminal_column;
|
||||||
}
|
}
|
||||||
terminal_buffer[terminal_pos(terminal_column, terminal_row)] = vga_entry(' ', terminal_color);
|
uint16_t index = terminal_pos(terminal_column, terminal_row);
|
||||||
|
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_putchar(char c)
|
void terminal_putchar(char c)
|
||||||
@ -103,7 +112,8 @@ void terminal_putchar(char c)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
|
uint16_t index = terminal_pos(terminal_column, terminal_row);
|
||||||
|
terminal_buffer[index] = vga_entry(c, terminal_color);
|
||||||
if (++terminal_column == VGA_WIDTH)
|
if (++terminal_column == VGA_WIDTH)
|
||||||
{
|
{
|
||||||
terminal_column = 0;
|
terminal_column = 0;
|
||||||
@ -124,24 +134,71 @@ void terminal_write(const char *data, size_t size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_print(const char *data)
|
void terminal_writestring(const char *data)
|
||||||
{
|
{
|
||||||
terminal_write(data, strlen(data));
|
terminal_write(data, strlen(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_number(int value, int base, int padding)
|
// Існуюча функція для виводу одного рядка
|
||||||
|
void terminal_printc(const char *data)
|
||||||
{
|
{
|
||||||
char buffer[32];
|
while (*data)
|
||||||
itoa(value, buffer, base);
|
|
||||||
int len = strlen(buffer);
|
|
||||||
|
|
||||||
while (padding > len)
|
|
||||||
{
|
{
|
||||||
terminal_putchar('0');
|
if (*data == '&' && ((*(data + 1) >= '0' && *(data + 1) <= '9') ||
|
||||||
padding--;
|
(*(data + 1) >= 'a' && *(data + 1) <= 'f')))
|
||||||
|
{
|
||||||
|
terminal_setcolor(vga_entry_color(vga_color_from_char(*(data + 1)), VGA_COLOR_BLACK));
|
||||||
|
data += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal_putchar(*data);
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal_print(buffer);
|
void itoa(int value, char *str, int base)
|
||||||
|
{
|
||||||
|
char *rc;
|
||||||
|
char *ptr;
|
||||||
|
char *low;
|
||||||
|
|
||||||
|
if (value < 0 && base == 10)
|
||||||
|
{
|
||||||
|
*str++ = '-';
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ptr = str;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*ptr++ = "0123456789abcdef"[value % base];
|
||||||
|
value /= base;
|
||||||
|
} while (value);
|
||||||
|
|
||||||
|
*ptr-- = '\0';
|
||||||
|
|
||||||
|
for (low = rc; low < ptr; low++, ptr--)
|
||||||
|
{
|
||||||
|
char tmp = *low;
|
||||||
|
*low = *ptr;
|
||||||
|
*ptr = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_printf_int(int value)
|
||||||
|
{
|
||||||
|
char buffer[12];
|
||||||
|
itoa(value, buffer, 10);
|
||||||
|
terminal_printf(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_printf_hex(unsigned int value)
|
||||||
|
{
|
||||||
|
char buffer[12];
|
||||||
|
itoa(value, buffer, 16);
|
||||||
|
terminal_printf(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_printf(const char *format, ...)
|
void terminal_printf(const char *format, ...)
|
||||||
@ -152,36 +209,25 @@ void terminal_printf(const char *format, ...)
|
|||||||
const char *p = format;
|
const char *p = format;
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
if (*p == '%' && (*(p + 1) == 's' || *(p + 1) == 'd' || *(p + 1) == 'x' || *(p + 1) == '0'))
|
if (*p == '%' && (*(p + 1) == 's' || *(p + 1) == 'd' || *(p + 1) == 'x'))
|
||||||
{
|
{
|
||||||
p++;
|
p++;
|
||||||
int padding = 0;
|
|
||||||
|
|
||||||
if (*p == '0')
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
padding = *p - '0';
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p == 's')
|
if (*p == 's')
|
||||||
{
|
{
|
||||||
terminal_print(va_arg(args, const char *));
|
const char *str = va_arg(args, const char *);
|
||||||
|
terminal_printc(str);
|
||||||
}
|
}
|
||||||
else if (*p == 'd')
|
else if (*p == 'd')
|
||||||
{
|
{
|
||||||
print_number(va_arg(args, int), 10, padding);
|
int value = va_arg(args, int);
|
||||||
|
terminal_printf_int(value);
|
||||||
}
|
}
|
||||||
else if (*p == 'x')
|
else if (*p == 'x')
|
||||||
{
|
{
|
||||||
print_number(va_arg(args, unsigned int), 16, padding);
|
unsigned int value = va_arg(args, unsigned int);
|
||||||
|
terminal_printf_hex(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (*p == '&' && ((*(p + 1) >= '0' && *(p + 1) <= '9') || (*(p + 1) >= 'a' && *(p + 1) <= 'f')))
|
|
||||||
{
|
|
||||||
terminal_setcolor(vga_entry_color(vga_color_from_char(*(p + 1)), VGA_COLOR_BLACK));
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
terminal_putchar(*p);
|
terminal_putchar(*p);
|
||||||
@ -192,12 +238,27 @@ void terminal_printf(const char *format, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void terminal_update_cursor(void)
|
||||||
|
{
|
||||||
|
uint16_t pos = terminal_row * VGA_WIDTH + terminal_column;
|
||||||
|
|
||||||
|
outb(0x3D4, 14);
|
||||||
|
outb(0x3D5, pos >> 8);
|
||||||
|
outb(0x3D4, 15);
|
||||||
|
outb(0x3D5, pos);
|
||||||
|
}
|
||||||
|
|
||||||
void terminal_clear(void)
|
void terminal_clear(void)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++)
|
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||||
{
|
{
|
||||||
terminal_buffer[i] = vga_entry(' ', terminal_color);
|
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||||
|
{
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
terminal_column = 0;
|
terminal_column = 0;
|
||||||
terminal_row = 0;
|
terminal_row = 0;
|
||||||
terminal_update_cursor();
|
terminal_update_cursor();
|
||||||
|
11
tty.h
11
tty.h
@ -5,9 +5,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void terminal_initialize(void);
|
void terminal_initialize(void);
|
||||||
void terminal_printf(const char *data, ...);
|
void terminal_setcolor(uint8_t color);
|
||||||
void terminal_print(const char *data);
|
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y);
|
||||||
void terminal_clear(void);
|
|
||||||
void terminal_putchar(char c);
|
void terminal_putchar(char c);
|
||||||
|
void terminal_write(const char *data, size_t size);
|
||||||
|
void terminal_writestring(const char *data);
|
||||||
|
void terminal_printf(const char *data, ...);
|
||||||
|
void terminal_printc(const char *data);
|
||||||
|
void terminal_update_cursor(void);
|
||||||
|
void terminal_clear(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
26
user_space.c
26
user_space.c
@ -1,4 +1,26 @@
|
|||||||
void enter_user_space()
|
void enter_user_space(void)
|
||||||
|
{
|
||||||
|
asm volatile("cli; \
|
||||||
|
mov $0x23, %ax; \
|
||||||
|
mov %ax, %ds; \
|
||||||
|
mov %ax, %es; \
|
||||||
|
mov %ax, %fs; \
|
||||||
|
mov %ax, %gs; \
|
||||||
|
mov %esp, %eax; \
|
||||||
|
pushl $0x23; \
|
||||||
|
pushl %eax; \
|
||||||
|
pushf; \
|
||||||
|
popl %eax; \
|
||||||
|
orl $0x200, %eax; \
|
||||||
|
pushl %eax; \
|
||||||
|
pushl $0x1B; \
|
||||||
|
push $1f; \
|
||||||
|
iret; \
|
||||||
|
1: \
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
void enter_user_space_v2()
|
||||||
{
|
{
|
||||||
asm volatile("cli; \
|
asm volatile("cli; \
|
||||||
mov $0x23, %ax; \
|
mov $0x23, %ax; \
|
||||||
@ -17,6 +39,6 @@ void enter_user_space()
|
|||||||
push $user_code_entry; \
|
push $user_code_entry; \
|
||||||
iret; \
|
iret; \
|
||||||
user_code_entry: \
|
user_code_entry: \
|
||||||
call main; \
|
call user_main; \
|
||||||
");
|
");
|
||||||
}
|
}
|
@ -2,5 +2,6 @@
|
|||||||
#define _USER_SPACE_H
|
#define _USER_SPACE_H
|
||||||
|
|
||||||
void enter_user_space(void);
|
void enter_user_space(void);
|
||||||
|
void enter_user_space_v2(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user