=)
This commit is contained in:
parent
c355d80244
commit
6d5a3c757d
2
Makefile
2
Makefile
@ -10,7 +10,7 @@ KERNEL = deados.bin
|
||||
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
|
||||
SOURCES_ASM = boot.s idt_load.s gdt_flush.s pit_handler.s irq_e.s isr_e.s tss.s
|
||||
SOURCES_ASM = boot.s idt_load.s gdt_flush.s tss_flush.s irq_flush.s isr_flush.s
|
||||
OBJECTS = $(SOURCES_ASM:.s=.o) $(SOURCES_C:.c=.o)
|
||||
|
||||
ISO_DIR = isodir
|
||||
|
12
README.md
12
README.md
@ -1,16 +1,17 @@
|
||||
# Simple OS implementation
|
||||
|
||||
Just a simple OS implementation in C. For educational purposes only.
|
||||
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.
|
||||
|
||||
## Requirements
|
||||
|
||||
- make
|
||||
- GCC Cross-Compiler
|
||||
- QEMU
|
||||
|
||||
## How to run
|
||||
|
||||
- `make`
|
||||
- `qemu-system-i386 -cdrom deados.iso`
|
||||
- `qemu-system-x86_64 -monitor stdio -cdrom deados.iso`
|
||||
|
||||
## Features
|
||||
|
||||
@ -23,11 +24,14 @@ Just a simple OS implementation in C. For educational purposes only.
|
||||
- [x] Timers
|
||||
- [x] Interrupts
|
||||
- [x] Kernel Extensions handling
|
||||
- [ ] Paging
|
||||
- [] Memory Management
|
||||
- [] File System
|
||||
- [] User Space
|
||||
- [] Syscalls
|
||||
- [x] User Space
|
||||
- [x] Syscalls
|
||||
- [ ] Multitasking
|
||||
- [] stdlib
|
||||
|
||||
## Screenshot:
|
||||
|
||||
![image](https://github.com/assada/os/assets/1472664/9b67c053-36e1-4816-ad7f-093b89b03fce)
|
||||
|
28
boot.s
28
boot.s
@ -10,26 +10,20 @@
|
||||
.long FLAGS
|
||||
.long CHECKSUM
|
||||
|
||||
.section .bss
|
||||
.align 16
|
||||
|
||||
.section .stack, "aw", @nobits
|
||||
.global stack_top
|
||||
stack_bottom:
|
||||
.skip 1024 * 32 # 32 KB
|
||||
|
||||
.skip 16384
|
||||
stack_top:
|
||||
.section .text
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
.section .text
|
||||
.global _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
cli
|
||||
mov $stack_top, %esp
|
||||
movl $stack_top, %esp
|
||||
|
||||
call kernel_main
|
||||
push %ebx
|
||||
|
||||
hlt
|
||||
jmp 1
|
||||
call kernel_main
|
||||
1:
|
||||
jmp 1
|
||||
|
||||
|
||||
.size _start, . - _start
|
||||
jmp 1b
|
||||
|
18
build.sh
18
build.sh
@ -1,18 +0,0 @@
|
||||
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
|
20
gdt.c
20
gdt.c
@ -37,29 +37,23 @@ static void tss_install(uint8_t num, uint16_t kernel_ss, uint16_t kernel_esp)
|
||||
tss.ss0 = kernel_ss;
|
||||
tss.esp0 = kernel_esp;
|
||||
|
||||
tss.cs = 0x0B;
|
||||
tss.ss = 0x13;
|
||||
tss.es = 0x13;
|
||||
tss.ds = 0x13;
|
||||
tss.fs = 0x13;
|
||||
tss.gs = 0x13;
|
||||
}
|
||||
|
||||
void set_kernel_stack(uint32_t stack)
|
||||
{
|
||||
tss.esp0 = stack;
|
||||
tss.cs = 0x1B;
|
||||
tss.ss = 0x23;
|
||||
tss.es = 0x23;
|
||||
tss.ds = 0x23;
|
||||
tss.fs = 0x23;
|
||||
tss.gs = 0x23;
|
||||
}
|
||||
|
||||
void gdt_install()
|
||||
{
|
||||
|
||||
gdt_set_gate(0, 0x0, 0x0, 0x0, 0x0); // Null segment
|
||||
gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xCF); // Kernel code segment
|
||||
gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
|
||||
gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xCF); // User code segment
|
||||
gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xCF); // User data segment
|
||||
|
||||
tss_install(5, 0x10, 0x0);
|
||||
tss_install(5, 0x10, stack_top);
|
||||
|
||||
gdtp.limit = (sizeof(Gdt_entry) * GDT_ENTRY) - 1;
|
||||
gdtp.base = (uint32_t)&gdt;
|
||||
|
2
gdt.h
2
gdt.h
@ -3,6 +3,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint32_t stack_top;
|
||||
|
||||
typedef struct gdt_entry_t Gdt_entry;
|
||||
struct gdt_entry_t
|
||||
{
|
||||
|
28
gdt_flush.s
28
gdt_flush.s
@ -1,19 +1,17 @@
|
||||
.global gdt_flush
|
||||
|
||||
gdt_flush:
|
||||
cli
|
||||
/* The pointer 'gdt_ptr' is defined in the C code */
|
||||
lgdt gdtp
|
||||
/* 0x08 is the offset to our code segment: far jump */
|
||||
jmp $0x08, $reload_cs
|
||||
|
||||
mov 4(%esp), %eax
|
||||
lgdt (%eax)
|
||||
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
|
||||
jmp $0x08, $.flush
|
||||
|
||||
.flush:
|
||||
ret
|
||||
reload_cs:
|
||||
/* 0x10 is the offset in the GDT to our data segment */
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
movw %ax, %ss
|
||||
ret
|
||||
|
20
idt.c
20
idt.c
@ -1,24 +1,8 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "idt.h"
|
||||
#include "io.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_ptr idtp;
|
||||
|
17
idt.h
17
idt.h
@ -3,6 +3,23 @@
|
||||
|
||||
#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();
|
||||
|
||||
void idt_install();
|
||||
|
@ -1,5 +1,5 @@
|
||||
.section .text
|
||||
.global idt_load
|
||||
idt_load:
|
||||
lidt [idtp]
|
||||
lidt idtp
|
||||
ret
|
||||
|
@ -6,13 +6,9 @@
|
||||
typedef struct stack_t Stack;
|
||||
struct stack_t
|
||||
{
|
||||
/* Pushed the segs last */
|
||||
uint32_t gs, fs, es, ds;
|
||||
/* Pushed by 'pusha' */
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||
/* Our 'push #' and ecodes do this */
|
||||
uint32_t id, err_code;
|
||||
/* Pushed by the processor automatically */
|
||||
uint32_t eip, cs, eflags, useresp, ss;
|
||||
};
|
||||
|
||||
@ -25,8 +21,8 @@ void isr_install(void);
|
||||
|
||||
#define NB_IRQ_ROUTINES 16
|
||||
|
||||
#define PIC1 0x20 /* master PIC */
|
||||
#define PIC2 0xA0 /* slave PIC */
|
||||
#define PIC1 0x20
|
||||
#define PIC2 0xA0
|
||||
#define PIC1_CMD PIC1
|
||||
#define PIC1_DATA (PIC1 + 1)
|
||||
#define PIC2_CMD PIC2
|
||||
|
18
io.c
18
io.c
@ -1,18 +1,20 @@
|
||||
#include "io.h"
|
||||
|
||||
void outb(uint16_t port, uint8_t val) {
|
||||
asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||
void outb(uint16_t port, uint8_t val)
|
||||
{
|
||||
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
|
||||
uint8_t inb(uint16_t port) {
|
||||
uint8_t inb(uint16_t port)
|
||||
{
|
||||
uint8_t ret;
|
||||
asm volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void io_wait(void)
|
||||
void wait(void)
|
||||
{
|
||||
asm volatile ( "jmp 1f\n\t"
|
||||
"1:jmp 2f\n\t"
|
||||
"2:" );
|
||||
asm volatile("jmp 1f\n\t"
|
||||
"1:jmp 2f\n\t"
|
||||
"2:");
|
||||
}
|
||||
|
36
irq.c
36
irq.c
@ -39,27 +39,23 @@ void irq_call_handler(Stack *registers)
|
||||
void (*handler)(Stack *registers);
|
||||
handler = irq_routines[registers->id - 32];
|
||||
if (handler)
|
||||
{
|
||||
handler(registers);
|
||||
}
|
||||
}
|
||||
|
||||
static void irq_remap(void)
|
||||
{
|
||||
outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
|
||||
io_wait();
|
||||
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
|
||||
io_wait();
|
||||
outb(PIC1_DATA, PIC1_OFFSET);
|
||||
io_wait();
|
||||
outb(PIC2_DATA, PIC2_OFFSET);
|
||||
io_wait();
|
||||
outb(PIC1_DATA, 0x04);
|
||||
io_wait();
|
||||
outb(PIC2_DATA, 0x02);
|
||||
io_wait();
|
||||
outb(PIC1_DATA, ICW4_8086);
|
||||
io_wait();
|
||||
outb(PIC2_DATA, ICW4_8086);
|
||||
io_wait();
|
||||
outb(0x20, 0x11);
|
||||
outb(0xA0, 0x11);
|
||||
outb(0x21, 0x20);
|
||||
outb(0xA1, 0x28);
|
||||
outb(0x21, 0x04);
|
||||
outb(0xA1, 0x02);
|
||||
outb(0x21, 0x01);
|
||||
outb(0xA1, 0x01);
|
||||
outb(0x21, 0x00);
|
||||
outb(0xA1, 0x00);
|
||||
}
|
||||
|
||||
void irq_install(void)
|
||||
@ -91,9 +87,7 @@ void irq_handler(Stack *registers)
|
||||
irq_call_handler(registers);
|
||||
|
||||
if (registers->id >= 40)
|
||||
{
|
||||
outb(PIC2_CMD, PIC_EOI);
|
||||
}
|
||||
outb(0xA0, 0x20);
|
||||
|
||||
outb(PIC1_CMD, PIC_EOI);
|
||||
}
|
||||
outb(0x20, 0x20);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
cli
|
||||
push $0x00
|
||||
push $\entry
|
||||
jmp irq_common_stub
|
||||
jmp irq_flush
|
||||
.endm
|
||||
|
||||
IRQ 0, 32
|
||||
@ -28,7 +28,7 @@ IRQ 13, 45
|
||||
IRQ 14, 46
|
||||
IRQ 15, 47
|
||||
|
||||
irq_common_stub:
|
||||
irq_flush:
|
||||
pusha
|
||||
|
||||
push %ds
|
13
isr.c
13
isr.c
@ -144,18 +144,13 @@ void fault_handler(Stack *registers)
|
||||
|
||||
if (registers->id < 32)
|
||||
{
|
||||
terminal_printc("Exception. System Halted!\n");
|
||||
|
||||
const char *message = exception_messages[registers->id];
|
||||
while (*message)
|
||||
{
|
||||
terminal_putchar(*message);
|
||||
message++;
|
||||
}
|
||||
terminal_printf("Exception. System Halted!\n");
|
||||
terminal_printf("Exception: ");
|
||||
terminal_printf(exception_messages[registers->id]);
|
||||
|
||||
isr_call_handler(registers);
|
||||
|
||||
for (;;)
|
||||
sys_halt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
cli
|
||||
push $0
|
||||
push $\index
|
||||
jmp isr_common_stub
|
||||
jmp isr_flush
|
||||
.endm
|
||||
|
||||
.macro ISR_ERR index
|
||||
@ -15,7 +15,7 @@
|
||||
isr\index:
|
||||
cli
|
||||
push $\index
|
||||
jmp isr_common_stub
|
||||
jmp isr_flush
|
||||
.endm
|
||||
|
||||
|
||||
@ -52,10 +52,10 @@ ISR_NO_ERR 28
|
||||
ISR_NO_ERR 29
|
||||
ISR_NO_ERR 30
|
||||
ISR_NO_ERR 31
|
||||
ISR_NO_ERR 128 # Syscal
|
||||
ISR_NO_ERR 128 # 80h syscall
|
||||
|
||||
|
||||
isr_common_stub:
|
||||
isr_flush:
|
||||
pusha
|
||||
push %ds
|
||||
push %es
|
30
kernel.c
30
kernel.c
@ -1,6 +1,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "tty.h"
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
@ -14,7 +15,6 @@
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
terminal_initialize();
|
||||
gdt_install();
|
||||
|
||||
idt_install();
|
||||
@ -22,21 +22,25 @@ void kernel_main(void)
|
||||
irq_install();
|
||||
|
||||
timer_install();
|
||||
|
||||
keyboard_install();
|
||||
|
||||
terminal_printc("Welcome to &cDeadOS&7.\n");
|
||||
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);
|
||||
}
|
||||
syscall_init();
|
||||
|
||||
enter_user_space();
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
terminal_initialize();
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
terminal_printf("&cTest &7%d\n", i);
|
||||
delay(500);
|
||||
}
|
||||
terminal_clear();
|
||||
|
||||
terminal_printf("Welcome to &cDeadOS&7.\n");
|
||||
terminal_printf("You are now in user space.\n");
|
||||
terminal_printf("Type 'help' for a list of available commands.\n");
|
||||
|
||||
shell_init();
|
||||
}
|
||||
}
|
||||
|
@ -199,4 +199,4 @@ void keyboard_install(void)
|
||||
{
|
||||
keyboard_clear_buffer();
|
||||
irq_install_handler(1, keyboard_handler);
|
||||
}
|
||||
}
|
||||
|
@ -15,4 +15,4 @@ int keyboard_getchar(void);
|
||||
unsigned char keyboard_getscancode(void);
|
||||
void keyboard_install(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
51
linker.ld
51
linker.ld
@ -1,24 +1,43 @@
|
||||
/* The bootloader will look at this image and start execution at the symbol
|
||||
designated at the entry point. */
|
||||
ENTRY(_start)
|
||||
|
||||
/* Tell where the various sections of the object files will be put in the final
|
||||
kernel image. */
|
||||
SECTIONS
|
||||
{
|
||||
. = 1M;
|
||||
/* The kernel is situated at 1 MiB */
|
||||
. = 1M;
|
||||
|
||||
.text ALIGN(4K) :
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
}
|
||||
kernel_start = .;
|
||||
|
||||
.data ALIGN(4K) :
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
/* First put the multiboot header, as it is required to be put very early
|
||||
early in the image or the bootloader won't recognize the file format.
|
||||
Next we'll put the .text section. */
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.bss ALIGN(4K) :
|
||||
{
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
/* Read-only data */
|
||||
.rodata BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
/* Read-write data (initialized) */
|
||||
.data BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
/* Read-write data (uninitialized) and stack */
|
||||
.bss BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.bss)
|
||||
*(.stack)
|
||||
}
|
||||
|
||||
kernel_end = .;
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
.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
|
31
shell.c
31
shell.c
@ -12,8 +12,7 @@ void shell_init(void)
|
||||
|
||||
while (true)
|
||||
{
|
||||
terminal_printc("\n");
|
||||
terminal_printc("&7dead@&croot&7: /> ");
|
||||
terminal_printf("&7dead@&croot&7: /> ");
|
||||
|
||||
i = 0;
|
||||
c = 0;
|
||||
@ -26,7 +25,7 @@ void shell_init(void)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
terminal_printc("\b \b");
|
||||
terminal_printf("\b \b");
|
||||
--i;
|
||||
}
|
||||
}
|
||||
@ -49,17 +48,17 @@ void shell_init(void)
|
||||
|
||||
void shell_help_command(void)
|
||||
{
|
||||
terminal_printc("List of commands:\n");
|
||||
terminal_printc("help - Print out the list of commands.\n");
|
||||
terminal_printc("exit - Exit the shell.\n");
|
||||
terminal_printc("echo - Print out the message. &eWITH colors!&7\n");
|
||||
terminal_printc("clear - Clear the terminal.\n");
|
||||
terminal_printf("List of commands:\n");
|
||||
terminal_printf("help - Print out the list of commands.\n");
|
||||
terminal_printf("exit - Exit the shell.\n");
|
||||
terminal_printf("echo - Print out the message. &eWITH colors!&7\n");
|
||||
terminal_printf("clear - Clear the terminal.\n");
|
||||
}
|
||||
|
||||
void shell_exit_command(void)
|
||||
{
|
||||
terminal_printc("Exiting shell...\n");
|
||||
terminal_printc("Goodbye!\n");
|
||||
terminal_printf("Exiting shell...\n");
|
||||
terminal_printf("Goodbye!\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
@ -73,8 +72,8 @@ void shell_echo_command(char *input)
|
||||
message++;
|
||||
}
|
||||
|
||||
terminal_printc(message);
|
||||
terminal_printc("\n");
|
||||
terminal_printf(message);
|
||||
terminal_printf("\n");
|
||||
}
|
||||
|
||||
void shell_parse_input(char *input)
|
||||
@ -105,9 +104,9 @@ void shell_parse_input(char *input)
|
||||
}
|
||||
else
|
||||
{
|
||||
terminal_printc("Unknown command: '");
|
||||
terminal_writestring(command);
|
||||
terminal_printc("'\n");
|
||||
terminal_printc("Type 'help' to print out the list of commands.\n");
|
||||
terminal_printf("Unknown command: '");
|
||||
terminal_print(command);
|
||||
terminal_printf("'\n");
|
||||
terminal_printf("Type 'help' to print out the list of commands.\n");
|
||||
}
|
||||
}
|
||||
|
2
shell.h
2
shell.h
@ -6,4 +6,4 @@
|
||||
void shell_init(void);
|
||||
void shell_parse_input(char *input);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
29
string.c
29
string.c
@ -94,3 +94,32 @@ char *strtok(char *str, const char *delim)
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
1
string.h
1
string.h
@ -7,6 +7,7 @@ char *strchr(const char *str, int c);
|
||||
char *strtok(char *str, const char *delim);
|
||||
int strcmp(const char *str1, const char *str2);
|
||||
size_t strlen(const char *str);
|
||||
void itoa(int value, char *str, int base);
|
||||
|
||||
void *memset(void *ptr, int value, size_t size);
|
||||
|
||||
|
11
syscall.c
11
syscall.c
@ -5,24 +5,17 @@
|
||||
#include "sys.h"
|
||||
#include "syscall.h"
|
||||
#include "tty.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define NB_SYSCALL 8
|
||||
#define NB_SYSCALL 2
|
||||
|
||||
void *syscalls[NB_SYSCALL] = {
|
||||
terminal_writestring,
|
||||
keyboard_getchar,
|
||||
terminal_printc,
|
||||
terminal_clear,
|
||||
terminal_putchar,
|
||||
terminal_putentryat,
|
||||
keyboard_clear_buffer,
|
||||
|
||||
sys_halt};
|
||||
|
||||
void syscall_handler(Stack *registers)
|
||||
{
|
||||
terminal_writestring("Syscall\n");
|
||||
|
||||
int sys_index = registers->eax;
|
||||
|
||||
if (sys_index >= NB_SYSCALL)
|
||||
|
62
timer.c
62
timer.c
@ -1,61 +1,35 @@
|
||||
#include "timer.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "interrupts.h"
|
||||
#include "io.h"
|
||||
#include "sys.h"
|
||||
#include "idt.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define PIT_FREQUENCY 1193182
|
||||
#define PIT_CHANNEL_0 0x40
|
||||
#define PIT_COMMAND 0x43
|
||||
volatile uint32_t timer_ticks = 0;
|
||||
|
||||
volatile uint32_t tick = 0;
|
||||
|
||||
void pit_handler()
|
||||
void delay(const uint32_t ticks)
|
||||
{
|
||||
tick++;
|
||||
outb(0x20, 0x20);
|
||||
uint32_t total_ticks = timer_ticks + ticks;
|
||||
while (timer_ticks < total_ticks)
|
||||
;
|
||||
}
|
||||
|
||||
void pic_remap(int offset1, int offset2)
|
||||
void timer_handler(Stack *registers)
|
||||
{
|
||||
unsigned char a1, a2;
|
||||
|
||||
a1 = inb(0x21);
|
||||
a2 = inb(0xA1);
|
||||
|
||||
outb(0x20, 0x11);
|
||||
outb(0xA0, 0x11);
|
||||
outb(0x21, offset1);
|
||||
outb(0xA1, offset2);
|
||||
outb(0x21, 0x04);
|
||||
outb(0xA1, 0x02);
|
||||
|
||||
outb(0x21, 0x01);
|
||||
outb(0xA1, 0x01);
|
||||
|
||||
outb(0x21, a1);
|
||||
outb(0xA1, a2);
|
||||
++timer_ticks;
|
||||
}
|
||||
|
||||
void delay(uint32_t milliseconds)
|
||||
static void timer_phase(const uint32_t hz)
|
||||
{
|
||||
uint32_t end = tick + milliseconds;
|
||||
while (tick < end)
|
||||
{
|
||||
sys_halt();
|
||||
}
|
||||
}
|
||||
uint32_t divisor = PIT_FREQUENCY / hz;
|
||||
|
||||
void pit_set_frequency(uint32_t frequency)
|
||||
{
|
||||
uint32_t divisor = PIT_FREQUENCY / frequency;
|
||||
outb(PIT_COMMAND, 0x36);
|
||||
outb(PIT_CHANNEL_0, divisor & 0xFF);
|
||||
outb(PIT_CHANNEL_0, (divisor >> 8) & 0xFF);
|
||||
outb(PIT_CHANNEL_0, divisor >> 8);
|
||||
}
|
||||
|
||||
void timer_install(void)
|
||||
{
|
||||
pic_remap(0x20, 0x28);
|
||||
pit_set_frequency(1000);
|
||||
idt_set_gate(32, (uint32_t)pit_handler_asm, 0x08, 0x8E);
|
||||
}
|
||||
irq_install_handler(0, timer_handler);
|
||||
|
||||
timer_phase(1000);
|
||||
}
|
||||
|
7
timer.h
7
timer.h
@ -3,12 +3,11 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern void pit_handler_asm();
|
||||
#define PIT_FREQUENCY 1193182
|
||||
#define PIT_CHANNEL_0 0x40
|
||||
#define PIT_COMMAND 0x43
|
||||
|
||||
void pit_handler();
|
||||
void delay(uint32_t milliseconds);
|
||||
void pit_set_frequency(uint32_t frequency);
|
||||
void pic_remap(int offset1, int offset2);
|
||||
void timer_install(void);
|
||||
|
||||
#endif
|
111
tty.c
111
tty.c
@ -1,9 +1,11 @@
|
||||
#include "tty.h"
|
||||
#include "vga.h"
|
||||
#include "io.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "tty.h"
|
||||
#include "vga.h"
|
||||
#include "io.h"
|
||||
#include "string.h"
|
||||
|
||||
static const size_t VGA_WIDTH = 80;
|
||||
@ -20,13 +22,9 @@ void terminal_initialize(void)
|
||||
terminal_column = 0;
|
||||
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||
terminal_buffer = (uint16_t *)0xB8000;
|
||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||
for (size_t i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++)
|
||||
{
|
||||
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_buffer[i] = vga_entry(' ', terminal_color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,37 +60,31 @@ void terminal_scroll(void)
|
||||
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)
|
||||
{
|
||||
if (terminal_column == 0)
|
||||
{
|
||||
terminal_column = VGA_WIDTH - 1;
|
||||
if (terminal_row == 0)
|
||||
{
|
||||
terminal_column = 0;
|
||||
}
|
||||
else
|
||||
if (terminal_row > 0)
|
||||
{
|
||||
--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
|
||||
{
|
||||
--terminal_column;
|
||||
}
|
||||
uint16_t index = terminal_pos(terminal_column, terminal_row);
|
||||
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||
terminal_buffer[terminal_pos(terminal_column, terminal_row)] = vga_entry(' ', terminal_color);
|
||||
}
|
||||
|
||||
void terminal_putchar(char c)
|
||||
@ -111,8 +103,7 @@ void terminal_putchar(char c)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t index = terminal_pos(terminal_column, terminal_row);
|
||||
terminal_buffer[index] = vga_entry(c, terminal_color);
|
||||
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
|
||||
if (++terminal_column == VGA_WIDTH)
|
||||
{
|
||||
terminal_column = 0;
|
||||
@ -133,51 +124,61 @@ void terminal_write(const char *data, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_writestring(const char *data)
|
||||
void terminal_print(const char *data)
|
||||
{
|
||||
terminal_write(data, strlen(data));
|
||||
}
|
||||
|
||||
void terminal_printc(const char *data)
|
||||
void terminal_printf(const char *format, ...)
|
||||
{
|
||||
while (*data)
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
const char *p = format;
|
||||
while (*p)
|
||||
{
|
||||
if (*data == '&' && ((*(data + 1) >= '0' && *(data + 1) <= '9') ||
|
||||
(*(data + 1) >= 'a' && *(data + 1) <= 'f')))
|
||||
if (*p == '%' && (*(p + 1) == 's' || *(p + 1) == 'd' || *(p + 1) == 'x'))
|
||||
{
|
||||
terminal_setcolor(vga_entry_color(vga_color_from_char(*(data + 1)), VGA_COLOR_BLACK));
|
||||
data += 2;
|
||||
p++;
|
||||
if (*p == 's')
|
||||
{
|
||||
terminal_print(va_arg(args, const char *));
|
||||
}
|
||||
else if (*p == 'd')
|
||||
{
|
||||
char buffer[12];
|
||||
itoa(va_arg(args, int), buffer, 10);
|
||||
terminal_print(buffer);
|
||||
}
|
||||
else if (*p == 'x')
|
||||
{
|
||||
char buffer[12];
|
||||
itoa(va_arg(args, unsigned int), buffer, 16);
|
||||
terminal_print(buffer);
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
terminal_putchar(*data);
|
||||
data++;
|
||||
terminal_putchar(*p);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void terminal_clear(void)
|
||||
{
|
||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||
for (size_t i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++)
|
||||
{
|
||||
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_buffer[i] = vga_entry(' ', terminal_color);
|
||||
}
|
||||
|
||||
terminal_column = 0;
|
||||
terminal_row = 0;
|
||||
terminal_update_cursor();
|
||||
}
|
||||
}
|
||||
|
10
tty.h
10
tty.h
@ -5,13 +5,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
void terminal_initialize(void);
|
||||
void terminal_setcolor(uint8_t color);
|
||||
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y);
|
||||
void terminal_putchar(char c);
|
||||
void terminal_write(const char *data, size_t size);
|
||||
void terminal_writestring(const char *data);
|
||||
void terminal_printc(const char *data);
|
||||
void terminal_update_cursor(void);
|
||||
void terminal_printf(const char *data, ...);
|
||||
void terminal_print(const char *data);
|
||||
void terminal_clear(void);
|
||||
void terminal_putchar(char c);
|
||||
|
||||
#endif
|
41
user_space.c
41
user_space.c
@ -1,25 +1,22 @@
|
||||
#include "user_space.h"
|
||||
#include "gdt.h"
|
||||
|
||||
void enter_user_space(void)
|
||||
void enter_user_space()
|
||||
{
|
||||
set_kernel_stack(0x110); // 128KB ?? WHY? ??
|
||||
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: \
|
||||
asm volatile("cli; \
|
||||
mov $0x23, %ax; \
|
||||
mov %ax, %ds; \
|
||||
mov %ax, %es; \
|
||||
mov %ax, %fs; \
|
||||
mov %ax, %gs; \
|
||||
mov %esp, %eax; \
|
||||
push $0x23; \
|
||||
push %eax; \
|
||||
pushf; \
|
||||
pop %eax; \
|
||||
or $0x200, %eax; \
|
||||
push %eax; \
|
||||
push $0x1B; \
|
||||
push $user_code_entry; \
|
||||
iret; \
|
||||
user_code_entry: \
|
||||
call main; \
|
||||
");
|
||||
}
|
Loading…
Reference in New Issue
Block a user