From ee8bcb7336e86bfe3a97102ef87e4e23409cbffc Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 13:46:16 -0700 Subject: [PATCH 01/67] Move interrupt handler to C and break logging into its own file. --- Makefile | 5 +++-- asm_interrupts.h | 0 asm_interrupts.s | 1 + drivers/frame_buffer.c | 3 ++- drivers/frame_buffer.h | 2 +- drivers/serial_port.c | 3 ++- drivers/serial_port.h | 2 +- interrupts.c | 7 +++++++ interrupts.h | 7 ++++++- interrupts.s | 4 ---- kmain.c | 7 +------ stdio.c | 18 ++++++++++++++++++ stdio.h | 9 +++++++++ 13 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 asm_interrupts.h create mode 100644 asm_interrupts.s create mode 100644 interrupts.c delete mode 100644 interrupts.s create mode 100644 stdio.c create mode 100644 stdio.h diff --git a/Makefile b/Makefile index 2cb825d..c5a552f 100644 --- a/Makefile +++ b/Makefile @@ -19,11 +19,12 @@ CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \ ASFLAGS = -f elf OBJECTS = loader.o \ +assembly_interface.o \ drivers/frame_buffer.o \ drivers/serial_port.o \ -assembly_interface.o \ interrupts.o \ -kmain.o +kmain.o \ +stdio.o all: os.iso diff --git a/asm_interrupts.h b/asm_interrupts.h new file mode 100644 index 0000000..e69de29 diff --git a/asm_interrupts.s b/asm_interrupts.s new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/asm_interrupts.s @@ -0,0 +1 @@ + diff --git a/drivers/frame_buffer.c b/drivers/frame_buffer.c index c23bc53..2f9d233 100644 --- a/drivers/frame_buffer.c +++ b/drivers/frame_buffer.c @@ -38,12 +38,13 @@ void clear_screen() } } -void fb_write(char * s) { +int fb_write(const char * s) { int i = 0; while (s[i]) { fb_write_cell(i, s[i], FB_WHITE, FB_BLACK); i++; } + return i; } /** move_cursor: diff --git a/drivers/frame_buffer.h b/drivers/frame_buffer.h index c98f5d9..61d73f8 100644 --- a/drivers/frame_buffer.h +++ b/drivers/frame_buffer.h @@ -23,7 +23,7 @@ #define FB_WHITE 15 void clear_screen(); -void fb_write(char * s); +int fb_write(const char * s); void move_cursor(unsigned short row, unsigned short col); #endif /* INCLUDE_FRAME_BUFFER_H */ \ No newline at end of file diff --git a/drivers/serial_port.c b/drivers/serial_port.c index 036436c..5621d72 100644 --- a/drivers/serial_port.c +++ b/drivers/serial_port.c @@ -98,12 +98,13 @@ int serial_is_transmit_fifo_empty(int16 com) return inb(SERIAL_LINE_STATUS_PORT(com)) & 0x20; } -void serial_write(int16 com, char * s) { +int serial_write(int16 com, const char * s) { int i = 0; while (s[i]) { serial_write_byte(com, s[i]); i++; } + return i; } void serial_write_byte(int16 com, char c) { diff --git a/drivers/serial_port.h b/drivers/serial_port.h index 09a6ede..96175e0 100644 --- a/drivers/serial_port.h +++ b/drivers/serial_port.h @@ -1,6 +1,6 @@ #define SERIAL_COM1_BASE 0x3F8 /* COM1 base port */ void serial_init(unsigned short com); -void serial_write(unsigned short com, char * s); +int serial_write(unsigned short com, const char * s); void serial_write_byte(unsigned short com, char c); void serial_write_bytes(unsigned short com, char * c, int n); \ No newline at end of file diff --git a/interrupts.c b/interrupts.c new file mode 100644 index 0000000..57f5021 --- /dev/null +++ b/interrupts.c @@ -0,0 +1,7 @@ +#include "interrupts.h" +#include "stdio.h" + +void interrupt_handler() { + log("interrupt_handler()\n"); + while(1){} +} \ No newline at end of file diff --git a/interrupts.h b/interrupts.h index 5afe96f..f9b90c7 100644 --- a/interrupts.h +++ b/interrupts.h @@ -1 +1,6 @@ -void interrupt_handler(); \ No newline at end of file +#ifndef INCLUDE_INTERRUPTS_H +#define INCLUDE_INTERRUPTS_H + +void interrupt_handler(); + +#endif /* INCLUDE_INTERRUPTS_H */ \ No newline at end of file diff --git a/interrupts.s b/interrupts.s deleted file mode 100644 index c6926dc..0000000 --- a/interrupts.s +++ /dev/null @@ -1,4 +0,0 @@ -global interrupt_handler -interrupt_handler: - mov eax, 0xDEADBEEF - jmp $ diff --git a/kmain.c b/kmain.c index 4bcd44a..1074bfd 100644 --- a/kmain.c +++ b/kmain.c @@ -2,10 +2,9 @@ #include "drivers/frame_buffer.h" #include "drivers/serial_port.h" #include "interrupts.h" +#include "stdio.h" #include "types.h" -enum output_t {SCREEN, LOG}; - // a pointer to the global descriptor table // passed by reference to the LGDT instruction struct gdt_description_structure_t { @@ -112,10 +111,6 @@ void printf(char * s) { write(SCREEN, s); } -void log(char * s) { - write(LOG, s); -} - static char *welcome_string = "" " " " " diff --git a/stdio.c b/stdio.c new file mode 100644 index 0000000..75d0f4b --- /dev/null +++ b/stdio.c @@ -0,0 +1,18 @@ +#include "stdio.h" +#include "drivers/frame_buffer.h" +#include "drivers/serial_port.h" + +int fprintf (FILE stream, const char * format, ...) { + switch (stream) { + case (SCREEN): + return fb_write(format); + break; + case (LOG): + return serial_write(SERIAL_COM1_BASE, format); + break; + } +} + +int log(char * format, ...) { + return serial_write(SERIAL_COM1_BASE, format); +} \ No newline at end of file diff --git a/stdio.h b/stdio.h new file mode 100644 index 0000000..dd6e691 --- /dev/null +++ b/stdio.h @@ -0,0 +1,9 @@ +#ifndef STDIO_H +#define STDIO_H + +typedef enum output_t {SCREEN, LOG} FILE; + +int fprintf (FILE stream, const char * format, ...); +int log(char * format, ...); + +#endif /* STDIO_H */ \ No newline at end of file From 0f8fca9660b049703d8027f40dbf5fc12eac2ce1 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 13:51:16 -0700 Subject: [PATCH 02/67] Move a few more things out of kmain --- drivers/serial_port.h | 4 +--- kmain.c | 15 --------------- stdio.c | 4 ++++ stdio.h | 1 + 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/serial_port.h b/drivers/serial_port.h index 96175e0..5c1d4ca 100644 --- a/drivers/serial_port.h +++ b/drivers/serial_port.h @@ -1,6 +1,4 @@ #define SERIAL_COM1_BASE 0x3F8 /* COM1 base port */ void serial_init(unsigned short com); -int serial_write(unsigned short com, const char * s); -void serial_write_byte(unsigned short com, char c); -void serial_write_bytes(unsigned short com, char * c, int n); \ No newline at end of file +int serial_write(unsigned short com, const char * s); \ No newline at end of file diff --git a/kmain.c b/kmain.c index 1074bfd..5604285 100644 --- a/kmain.c +++ b/kmain.c @@ -96,21 +96,6 @@ void initialize_idt() { load_idt(&idt_description_structure); } -void write(enum output_t output_device, char * s) { - switch (output_device) { - case (SCREEN): - fb_write(s); - break; - case (LOG): - serial_write(SERIAL_COM1_BASE, s); - break; - } -} - -void printf(char * s) { - write(SCREEN, s); -} - static char *welcome_string = "" " " " " diff --git a/stdio.c b/stdio.c index 75d0f4b..88a1ec4 100644 --- a/stdio.c +++ b/stdio.c @@ -13,6 +13,10 @@ int fprintf (FILE stream, const char * format, ...) { } } +int printf (const char * format, ...) { + return fprintf(SCREEN, format); +} + int log(char * format, ...) { return serial_write(SERIAL_COM1_BASE, format); } \ No newline at end of file diff --git a/stdio.h b/stdio.h index dd6e691..907ed8e 100644 --- a/stdio.h +++ b/stdio.h @@ -5,5 +5,6 @@ typedef enum output_t {SCREEN, LOG} FILE; int fprintf (FILE stream, const char * format, ...); int log(char * format, ...); +int printf (const char * format, ...); #endif /* STDIO_H */ \ No newline at end of file From 6229c1bddc8d272ffef9e69b668edaf497a0d220 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 14:02:11 -0700 Subject: [PATCH 03/67] Return from interrupt handler. --- Makefile | 1 + asm_interrupts.h | 1 + asm_interrupts.s | 36 ++++++++++++++++++++++++++++++++++++ interrupts.c | 2 +- kmain.c | 4 +++- 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c5a552f..b2e18c1 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \ ASFLAGS = -f elf OBJECTS = loader.o \ +asm_interrupts.o \ assembly_interface.o \ drivers/frame_buffer.o \ drivers/serial_port.o \ diff --git a/asm_interrupts.h b/asm_interrupts.h index e69de29..260b3d2 100644 --- a/asm_interrupts.h +++ b/asm_interrupts.h @@ -0,0 +1 @@ +void interrupt_handler_49(); \ No newline at end of file diff --git a/asm_interrupts.s b/asm_interrupts.s index 8b13789..37a8ff8 100644 --- a/asm_interrupts.s +++ b/asm_interrupts.s @@ -1 +1,37 @@ +extern interrupt_handler ; the C interrupt handler +global interrupt_handler_49 +interrupt_handler_49: + push dword 0 ; push 0 as error code + push dword 49 ; push the interrupt number + jmp common_interrupt_handler ; jump to the common handler + +common_interrupt_handler: ; the common parts of the generic interrupt handler + ; save the registers + push eax + push ebx + push ecx + push edx + push esi + push edi + push esp + push ebp + + ; call the C function + call interrupt_handler + + ; restore the registers + pop ebp + pop esp + pop edi + pop esi + pop edx + pop ecx + pop ebx + pop eax + + ; restore the esp + add esp, 8 + + ; return to the code that got interrupted + iret diff --git a/interrupts.c b/interrupts.c index 57f5021..91d2c2b 100644 --- a/interrupts.c +++ b/interrupts.c @@ -3,5 +3,5 @@ void interrupt_handler() { log("interrupt_handler()\n"); - while(1){} + return; } \ No newline at end of file diff --git a/kmain.c b/kmain.c index 5604285..ebbfbe5 100644 --- a/kmain.c +++ b/kmain.c @@ -1,3 +1,4 @@ +#include "asm_interrupts.h" #include "assembly_interface.h" #include "drivers/frame_buffer.h" #include "drivers/serial_port.h" @@ -78,7 +79,7 @@ void initialize_idt() { idt_description_structure.size = sizeof(idt) - 1; idt_description_structure.offset = (uint32_t) idt; - uint32_t interrupt_handler_address = (uint32_t) &interrupt_handler; + uint32_t interrupt_handler_address = (uint32_t) &interrupt_handler_49; uint16_t offset_0_15 = interrupt_handler_address & 0x0000FFFF; uint16_t offset_16_31 = interrupt_handler_address >> 16; uint16_t selector = KERNAL_CODE_SEGMENT_SELECTOR; @@ -141,6 +142,7 @@ void kmain() { move_cursor(17, 0); interrupt(49); + log("Returned from interrupt()\n"); // Loop forever // TODO: accept user input From 88ca6f02b7c0692520d54c02e29cb14037327048 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 14:34:30 -0700 Subject: [PATCH 04/67] Standardize the way writing to output streams works. --- drivers/frame_buffer.c | 24 ++++++++++++------------ drivers/frame_buffer.h | 5 +++-- drivers/serial_port.c | 31 ++++++++++++------------------- drivers/serial_port.h | 11 ++++++++--- kmain.c | 4 +--- stdio.c | 14 +++++++++++--- 6 files changed, 47 insertions(+), 42 deletions(-) diff --git a/drivers/frame_buffer.c b/drivers/frame_buffer.c index 2f9d233..0d5dadf 100644 --- a/drivers/frame_buffer.c +++ b/drivers/frame_buffer.c @@ -15,6 +15,8 @@ // Start of memory that maps to the frame buffer char *fb = (char *) 0x000B8000; +uint16_t cursor_pos = 0; + /** fb_write_cell: * Writes a character with the given foreground and background to position i * in the framebuffer. @@ -38,15 +40,6 @@ void clear_screen() } } -int fb_write(const char * s) { - int i = 0; - while (s[i]) { - fb_write_cell(i, s[i], FB_WHITE, FB_BLACK); - i++; - } - return i; -} - /** move_cursor: * Moves the cursor of the framebuffer to the given position * @@ -60,6 +53,13 @@ void move_cursor_to_pos(unsigned short pos) outb(FB_DATA_PORT, pos & 0x00FF); } -void move_cursor(unsigned short row, unsigned short col) { - move_cursor_to_pos(row*FB_COLS + col); -} \ No newline at end of file +void fb_write_byte(uint8_t b) { + fb_write_cell(cursor_pos, b, FB_WHITE, FB_BLACK); + cursor_pos++; + + // Stop the cursor from going off the screen + // TODO: advance the screen + if (cursor_pos < FB_CELLS) { + move_cursor_to_pos(cursor_pos); + } +} diff --git a/drivers/frame_buffer.h b/drivers/frame_buffer.h index 61d73f8..307c8e3 100644 --- a/drivers/frame_buffer.h +++ b/drivers/frame_buffer.h @@ -1,6 +1,8 @@ #ifndef INCLUDE_FRAME_BUFFER_H #define INCLUDE_FRAME_BUFFER_H +#include "../types.h" + #define FB_COLS 80 #define FB_ROWS 25 #define FB_CELLS FB_COLS * FB_ROWS @@ -23,7 +25,6 @@ #define FB_WHITE 15 void clear_screen(); -int fb_write(const char * s); -void move_cursor(unsigned short row, unsigned short col); +void fb_write_byte(uint8_t b); #endif /* INCLUDE_FRAME_BUFFER_H */ \ No newline at end of file diff --git a/drivers/serial_port.c b/drivers/serial_port.c index 5621d72..557cd38 100644 --- a/drivers/serial_port.c +++ b/drivers/serial_port.c @@ -4,6 +4,8 @@ #include "../assembly_interface.h" #include "../types.h" +#define SERIAL_COM1_BASE 0x3F8 /* COM1 base port */ + /* The I/O ports */ /* All the I/O ports are calculated relative to the data port. This is because @@ -77,11 +79,11 @@ void serial_configure_modem(int16 com) outb(SERIAL_MODEM_COMMAND_PORT(com), 0x03); } -void serial_init(int16 com) { - serial_configure_baud_rate(com, 2); - serial_configure_line(com); - serial_configure_fifo(com); - serial_configure_modem(com); +void serial_init() { + serial_configure_baud_rate(SERIAL_COM1_BASE, 2); + serial_configure_line(SERIAL_COM1_BASE); + serial_configure_fifo(SERIAL_COM1_BASE); + serial_configure_modem(SERIAL_COM1_BASE); } /** serial_is_transmit_fifo_empty: @@ -98,24 +100,15 @@ int serial_is_transmit_fifo_empty(int16 com) return inb(SERIAL_LINE_STATUS_PORT(com)) & 0x20; } -int serial_write(int16 com, const char * s) { - int i = 0; - while (s[i]) { - serial_write_byte(com, s[i]); - i++; - } - return i; -} - -void serial_write_byte(int16 com, char c) { +void serial_write_byte(uint8_t b) { // Block until buffer is not full - while (!serial_is_transmit_fifo_empty(com)) {} + while (!serial_is_transmit_fifo_empty(SERIAL_COM1_BASE)) {} - outb(SERIAL_DATA_PORT(com), c); + outb(SERIAL_DATA_PORT(SERIAL_COM1_BASE), b); } -void serial_write_bytes(int16 com, char * c, int n) { +void serial_write_bytes(char * c, int n) { for (int i = 0; i < n; i++) { - serial_write_byte(com, c[i]); + serial_write_byte(c[i]); } } \ No newline at end of file diff --git a/drivers/serial_port.h b/drivers/serial_port.h index 5c1d4ca..2980a58 100644 --- a/drivers/serial_port.h +++ b/drivers/serial_port.h @@ -1,4 +1,9 @@ -#define SERIAL_COM1_BASE 0x3F8 /* COM1 base port */ +#ifndef INCLUSERIAL_PORTFER_H +#define INCLUSERIAL_PORTFER_H -void serial_init(unsigned short com); -int serial_write(unsigned short com, const char * s); \ No newline at end of file +#include "../types.h" + +void serial_init(); +void serial_write_byte(uint8_t b); + +#endif /* INCLUDE_SERIAL_PORT_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index ebbfbe5..764d8b1 100644 --- a/kmain.c +++ b/kmain.c @@ -130,7 +130,7 @@ void kmain() { printf(welcome_string); - serial_init(SERIAL_COM1_BASE); + serial_init(); log("Initialized serial port.\n"); initialize_gdt(); @@ -139,8 +139,6 @@ void kmain() { initialize_idt(); log("Loaded interrupt descriptor table.\n"); - move_cursor(17, 0); - interrupt(49); log("Returned from interrupt()\n"); diff --git a/stdio.c b/stdio.c index 88a1ec4..bae9e73 100644 --- a/stdio.c +++ b/stdio.c @@ -3,14 +3,22 @@ #include "drivers/serial_port.h" int fprintf (FILE stream, const char * format, ...) { + void (*write_byte)(uint8_t); switch (stream) { case (SCREEN): - return fb_write(format); + write_byte = fb_write_byte; break; case (LOG): - return serial_write(SERIAL_COM1_BASE, format); + write_byte = serial_write_byte; break; } + + int i = 0; + while (format[i]) { + write_byte(format[i]); + i++; + } + return i; } int printf (const char * format, ...) { @@ -18,5 +26,5 @@ int printf (const char * format, ...) { } int log(char * format, ...) { - return serial_write(SERIAL_COM1_BASE, format); + return fprintf(LOG, format); } \ No newline at end of file From 97e2c57bef2a73cb740bc28c6158743896f5eb40 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 14:43:01 -0700 Subject: [PATCH 05/67] Fix make clean --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index b2e18c1..8892434 100644 --- a/Makefile +++ b/Makefile @@ -61,8 +61,8 @@ run: os.iso $(QEMU) -monitor stdio -cdrom $< -serial file:log/log.txt clean: - rm *.iso - rm $(OBJECTS) - rm *.elf - rm *.out + rm -f *.iso + rm -f $(OBJECTS) + rm -f *.elf + rm -f *.out rm -rf iso/ From ff3fab247206566fdf3f461b73b3b481e0265716 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 15:05:37 -0700 Subject: [PATCH 06/67] Add function to print byte. --- kmain.c | 4 +++ stdio.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- stdio.h | 3 +++ 3 files changed, 77 insertions(+), 6 deletions(-) diff --git a/kmain.c b/kmain.c index 764d8b1..1d3c290 100644 --- a/kmain.c +++ b/kmain.c @@ -142,6 +142,10 @@ void kmain() { interrupt(49); log("Returned from interrupt()\n"); + print_int8(LOG, 0xAB); + + log("\nThe above line should be '0xAB'\n"); + // Loop forever // TODO: accept user input while(1) {}; diff --git a/stdio.c b/stdio.c index bae9e73..fca5984 100644 --- a/stdio.c +++ b/stdio.c @@ -2,16 +2,19 @@ #include "drivers/frame_buffer.h" #include "drivers/serial_port.h" -int fprintf (FILE stream, const char * format, ...) { - void (*write_byte)(uint8_t); +typedef void (*write_byte_t)(uint8_t); + +write_byte_t write_byte_function(FILE stream) { switch (stream) { case (SCREEN): - write_byte = fb_write_byte; - break; + return fb_write_byte; case (LOG): - write_byte = serial_write_byte; - break; + return serial_write_byte; } +} + +int fprintf (FILE stream, const char * format, ...) { + write_byte_t write_byte = write_byte_function(stream); int i = 0; while (format[i]) { @@ -21,6 +24,67 @@ int fprintf (FILE stream, const char * format, ...) { return i; } +void print_int8(FILE stream, uint8_t data) { + write_byte_t write_byte = write_byte_function(stream); + + uint8_t half_byte; + write_byte('0'); + write_byte('x'); + for (int i = 1; i >=0; i--) { + half_byte = (data >> (4*i)) & 0x0F; + switch (half_byte) { + case 0x0: + write_byte('0'); + break; + case 0x1: + write_byte('1'); + break; + case 0x2: + write_byte('2'); + break; + case 0x3: + write_byte('3'); + break; + case 0x4: + write_byte('4'); + break; + case 0x5: + write_byte('5'); + break; + case 0x6: + write_byte('6'); + break; + case 0x7: + write_byte('7'); + break; + case 0x8: + write_byte('8'); + break; + case 0x9: + write_byte('9'); + break; + case 0xA: + write_byte('A'); + break; + case 0xB: + write_byte('B'); + break; + case 0xC: + write_byte('C'); + break; + case 0xD: + write_byte('D'); + break; + case 0xE: + write_byte('E'); + break; + case 0xF: + write_byte('F'); + break; + } + } +} + int printf (const char * format, ...) { return fprintf(SCREEN, format); } diff --git a/stdio.h b/stdio.h index 907ed8e..7ec604d 100644 --- a/stdio.h +++ b/stdio.h @@ -1,10 +1,13 @@ #ifndef STDIO_H #define STDIO_H +#include "types.h" + typedef enum output_t {SCREEN, LOG} FILE; int fprintf (FILE stream, const char * format, ...); int log(char * format, ...); int printf (const char * format, ...); +void print_int8(FILE stream, uint8_t data); #endif /* STDIO_H */ \ No newline at end of file From 2551f447e653e9ed49c8fdd6a2a210ba117ef1bd Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 15:20:56 -0700 Subject: [PATCH 07/67] Add logging to interrupt handler. --- interrupts.c | 45 +++++++++++++++++++- interrupts.h | 22 +++++++++- kmain.c | 4 -- stdio.c | 116 +++++++++++++++++++++++++++++---------------------- stdio.h | 1 + 5 files changed, 131 insertions(+), 57 deletions(-) diff --git a/interrupts.c b/interrupts.c index 91d2c2b..dd00ec0 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,7 +1,48 @@ #include "interrupts.h" #include "stdio.h" -void interrupt_handler() { +void interrupt_handler(struct cpu_state cpu, struct stack_state stack, uint32_t interrupt) { log("interrupt_handler()\n"); + log("cpu.eax: "); + print_uint32(LOG, cpu.eax); + log("\n"); + log("cpu.ebx: "); + print_uint32(LOG, cpu.ebx); + log("\n"); + log("cpu.ecx: "); + print_uint32(LOG, cpu.ecx); + log("\n"); + log("cpu.edx: "); + print_uint32(LOG, cpu.edx); + log("\n"); + log("cpu.esi: "); + print_uint32(LOG, cpu.esi); + log("\n"); + log("cpu.edi: "); + print_uint32(LOG, cpu.edi); + log("\n"); + log("cpu.esp: "); + print_uint32(LOG, cpu.esp); + log("\n"); + log("cpu.ebp: "); + print_uint32(LOG, cpu.ebp); + log("\n"); + + log("stack.error_code: "); + print_uint32(LOG, stack.error_code); + log("\n"); + log("stack.eip: "); + print_uint32(LOG, stack.eip); + log("\n"); + log("stack.cs: "); + print_uint32(LOG, stack.cs); + log("\n"); + log("stack.eflags: "); + print_uint32(LOG, stack.eflags); + log("\n"); + + log("interrupt: "); + print_uint32(LOG, interrupt); + log("\n"); return; -} \ No newline at end of file +} diff --git a/interrupts.h b/interrupts.h index f9b90c7..d15a3fc 100644 --- a/interrupts.h +++ b/interrupts.h @@ -1,6 +1,26 @@ #ifndef INCLUDE_INTERRUPTS_H #define INCLUDE_INTERRUPTS_H -void interrupt_handler(); +#include "types.h" + +struct cpu_state { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t esp; + uint32_t ebp; +} __attribute__((packed)); + +struct stack_state { + uint32_t error_code; + uint32_t eip; + uint32_t cs; + uint32_t eflags; +} __attribute__((packed)); + +void interrupt_handler(struct cpu_state cpu, struct stack_state stack, uint32_t interrupt); #endif /* INCLUDE_INTERRUPTS_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index 1d3c290..764d8b1 100644 --- a/kmain.c +++ b/kmain.c @@ -142,10 +142,6 @@ void kmain() { interrupt(49); log("Returned from interrupt()\n"); - print_int8(LOG, 0xAB); - - log("\nThe above line should be '0xAB'\n"); - // Loop forever // TODO: accept user input while(1) {}; diff --git a/stdio.c b/stdio.c index fca5984..3010e15 100644 --- a/stdio.c +++ b/stdio.c @@ -24,6 +24,59 @@ int fprintf (FILE stream, const char * format, ...) { return i; } +void print_half_byte(write_byte_t write_byte, uint8_t half_byte) { + switch (half_byte) { + case 0x0: + write_byte('0'); + break; + case 0x1: + write_byte('1'); + break; + case 0x2: + write_byte('2'); + break; + case 0x3: + write_byte('3'); + break; + case 0x4: + write_byte('4'); + break; + case 0x5: + write_byte('5'); + break; + case 0x6: + write_byte('6'); + break; + case 0x7: + write_byte('7'); + break; + case 0x8: + write_byte('8'); + break; + case 0x9: + write_byte('9'); + break; + case 0xA: + write_byte('A'); + break; + case 0xB: + write_byte('B'); + break; + case 0xC: + write_byte('C'); + break; + case 0xD: + write_byte('D'); + break; + case 0xE: + write_byte('E'); + break; + case 0xF: + write_byte('F'); + break; + } +} + void print_int8(FILE stream, uint8_t data) { write_byte_t write_byte = write_byte_function(stream); @@ -32,56 +85,19 @@ void print_int8(FILE stream, uint8_t data) { write_byte('x'); for (int i = 1; i >=0; i--) { half_byte = (data >> (4*i)) & 0x0F; - switch (half_byte) { - case 0x0: - write_byte('0'); - break; - case 0x1: - write_byte('1'); - break; - case 0x2: - write_byte('2'); - break; - case 0x3: - write_byte('3'); - break; - case 0x4: - write_byte('4'); - break; - case 0x5: - write_byte('5'); - break; - case 0x6: - write_byte('6'); - break; - case 0x7: - write_byte('7'); - break; - case 0x8: - write_byte('8'); - break; - case 0x9: - write_byte('9'); - break; - case 0xA: - write_byte('A'); - break; - case 0xB: - write_byte('B'); - break; - case 0xC: - write_byte('C'); - break; - case 0xD: - write_byte('D'); - break; - case 0xE: - write_byte('E'); - break; - case 0xF: - write_byte('F'); - break; - } + print_half_byte(write_byte, half_byte); + } +} + +void print_uint32(FILE stream, uint32_t data) { + write_byte_t write_byte = write_byte_function(stream); + + uint8_t half_byte; + write_byte('0'); + write_byte('x'); + for (int i = 7; i >=0; i--) { + half_byte = (data >> (4*i)) & 0x0F; + print_half_byte(write_byte, half_byte); } } diff --git a/stdio.h b/stdio.h index 7ec604d..313b99e 100644 --- a/stdio.h +++ b/stdio.h @@ -9,5 +9,6 @@ int fprintf (FILE stream, const char * format, ...); int log(char * format, ...); int printf (const char * format, ...); void print_int8(FILE stream, uint8_t data); +void print_uint32(FILE stream, uint32_t data); #endif /* STDIO_H */ \ No newline at end of file From 9e50ed9044431d3b292470ead5457ad1007bd7ea Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 15:36:11 -0700 Subject: [PATCH 08/67] I think this is how paramters are being passed? --- interrupts.c | 28 ++++++++++------------------ interrupts.h | 2 +- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/interrupts.c b/interrupts.c index dd00ec0..c7e33f8 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,8 +1,17 @@ #include "interrupts.h" #include "stdio.h" -void interrupt_handler(struct cpu_state cpu, struct stack_state stack, uint32_t interrupt) { +void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code) { log("interrupt_handler()\n"); + + log("error_code: "); + print_uint32(LOG, error_code); + log("\n"); + + log("interrupt_number: "); + print_uint32(LOG, interrupt_number); + log("\n"); + log("cpu.eax: "); print_uint32(LOG, cpu.eax); log("\n"); @@ -27,22 +36,5 @@ void interrupt_handler(struct cpu_state cpu, struct stack_state stack, uint32_t log("cpu.ebp: "); print_uint32(LOG, cpu.ebp); log("\n"); - - log("stack.error_code: "); - print_uint32(LOG, stack.error_code); - log("\n"); - log("stack.eip: "); - print_uint32(LOG, stack.eip); - log("\n"); - log("stack.cs: "); - print_uint32(LOG, stack.cs); - log("\n"); - log("stack.eflags: "); - print_uint32(LOG, stack.eflags); - log("\n"); - - log("interrupt: "); - print_uint32(LOG, interrupt); - log("\n"); return; } diff --git a/interrupts.h b/interrupts.h index d15a3fc..0fda19c 100644 --- a/interrupts.h +++ b/interrupts.h @@ -21,6 +21,6 @@ struct stack_state { uint32_t eflags; } __attribute__((packed)); -void interrupt_handler(struct cpu_state cpu, struct stack_state stack, uint32_t interrupt); +void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code); #endif /* INCLUDE_INTERRUPTS_H */ \ No newline at end of file From 1973d666c15d3ec891abdb6fffd73118643828f1 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 11 Sep 2016 15:49:40 -0700 Subject: [PATCH 09/67] Enable keyboard interrupts. --- assembly_interface.h | 7 +++++++ assembly_interface.s | 5 +++++ interrupts.c | 8 ++++++++ interrupts.h | 1 + kmain.c | 2 ++ 5 files changed, 23 insertions(+) diff --git a/assembly_interface.h b/assembly_interface.h index 89d82b4..4c307d5 100644 --- a/assembly_interface.h +++ b/assembly_interface.h @@ -41,4 +41,11 @@ void load_idt(void * idt); */ void interrupt(uint32_t interrupt_number); +/** enable_hardware_interrupts: + * Sets the Interrupt bit in the FLAGS + * register, enabling maskable + * hardware interrupts + */ +void enable_hardware_interrupts(); + #endif /* INCLUDE_ASSEMBLY_INTERFACE_H */ \ No newline at end of file diff --git a/assembly_interface.s b/assembly_interface.s index 79d7a67..b4a7434 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -47,3 +47,8 @@ global interrupt interrupt: mov eax, [esp+4] int 49 + +global enable_hardware_interrupts +; enable_hardware_interrupts +enable_hardware_interrupts: + sti diff --git a/interrupts.c b/interrupts.c index c7e33f8..e9632e7 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,6 +1,14 @@ #include "interrupts.h" + +#include "assembly_interface.h" #include "stdio.h" +void enable_keyboard_interrupts() { + outb(0x21,0xfd); + outb(0xa1,0xff); + enable_hardware_interrupts(); +} + void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code) { log("interrupt_handler()\n"); diff --git a/interrupts.h b/interrupts.h index 0fda19c..c0e0309 100644 --- a/interrupts.h +++ b/interrupts.h @@ -21,6 +21,7 @@ struct stack_state { uint32_t eflags; } __attribute__((packed)); +void enable_keyboard_interrupts(); void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code); #endif /* INCLUDE_INTERRUPTS_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index 764d8b1..25cecf9 100644 --- a/kmain.c +++ b/kmain.c @@ -142,6 +142,8 @@ void kmain() { interrupt(49); log("Returned from interrupt()\n"); + enable_keyboard_interrupts(); + // Loop forever // TODO: accept user input while(1) {}; From 574c6c73d0ef702c97acdd4a91377d106108d5ff Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 17 Sep 2016 15:10:05 -0700 Subject: [PATCH 10/67] Consume scan code. --- Makefile | 2 + asm_interrupts.h | 257 +++++++- asm_interrupts.s | 1536 +++++++++++++++++++++++++++++++++++++++++++- drivers/keyboard.c | 25 + drivers/keyboard.h | 8 + drivers/pic.c | 30 + drivers/pic.h | 13 + interrupts.c | 41 +- kmain.c | 266 +++++++- stdio.c | 2 +- stdio.h | 2 +- 11 files changed, 2148 insertions(+), 34 deletions(-) create mode 100644 drivers/keyboard.c create mode 100644 drivers/keyboard.h create mode 100644 drivers/pic.c create mode 100644 drivers/pic.h diff --git a/Makefile b/Makefile index 8892434..e3adb03 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,8 @@ OBJECTS = loader.o \ asm_interrupts.o \ assembly_interface.o \ drivers/frame_buffer.o \ +drivers/keyboard.o \ +drivers/pic.o \ drivers/serial_port.o \ interrupts.o \ kmain.o \ diff --git a/asm_interrupts.h b/asm_interrupts.h index 260b3d2..3974009 100644 --- a/asm_interrupts.h +++ b/asm_interrupts.h @@ -1 +1,256 @@ -void interrupt_handler_49(); \ No newline at end of file +void interrupt_handler_0(); +void interrupt_handler_1(); +void interrupt_handler_2(); +void interrupt_handler_3(); +void interrupt_handler_4(); +void interrupt_handler_5(); +void interrupt_handler_6(); +void interrupt_handler_7(); +void interrupt_handler_8(); +void interrupt_handler_9(); +void interrupt_handler_10(); +void interrupt_handler_11(); +void interrupt_handler_12(); +void interrupt_handler_13(); +void interrupt_handler_14(); +void interrupt_handler_15(); +void interrupt_handler_16(); +void interrupt_handler_17(); +void interrupt_handler_18(); +void interrupt_handler_19(); +void interrupt_handler_20(); +void interrupt_handler_21(); +void interrupt_handler_22(); +void interrupt_handler_23(); +void interrupt_handler_24(); +void interrupt_handler_25(); +void interrupt_handler_26(); +void interrupt_handler_27(); +void interrupt_handler_28(); +void interrupt_handler_29(); +void interrupt_handler_30(); +void interrupt_handler_31(); +void interrupt_handler_32(); +void interrupt_handler_33(); +void interrupt_handler_34(); +void interrupt_handler_35(); +void interrupt_handler_36(); +void interrupt_handler_37(); +void interrupt_handler_38(); +void interrupt_handler_39(); +void interrupt_handler_40(); +void interrupt_handler_41(); +void interrupt_handler_42(); +void interrupt_handler_43(); +void interrupt_handler_44(); +void interrupt_handler_45(); +void interrupt_handler_46(); +void interrupt_handler_47(); +void interrupt_handler_48(); +void interrupt_handler_49(); +void interrupt_handler_50(); +void interrupt_handler_51(); +void interrupt_handler_52(); +void interrupt_handler_53(); +void interrupt_handler_54(); +void interrupt_handler_55(); +void interrupt_handler_56(); +void interrupt_handler_57(); +void interrupt_handler_58(); +void interrupt_handler_59(); +void interrupt_handler_60(); +void interrupt_handler_61(); +void interrupt_handler_62(); +void interrupt_handler_63(); +void interrupt_handler_64(); +void interrupt_handler_65(); +void interrupt_handler_66(); +void interrupt_handler_67(); +void interrupt_handler_68(); +void interrupt_handler_69(); +void interrupt_handler_70(); +void interrupt_handler_71(); +void interrupt_handler_72(); +void interrupt_handler_73(); +void interrupt_handler_74(); +void interrupt_handler_75(); +void interrupt_handler_76(); +void interrupt_handler_77(); +void interrupt_handler_78(); +void interrupt_handler_79(); +void interrupt_handler_80(); +void interrupt_handler_81(); +void interrupt_handler_82(); +void interrupt_handler_83(); +void interrupt_handler_84(); +void interrupt_handler_85(); +void interrupt_handler_86(); +void interrupt_handler_87(); +void interrupt_handler_88(); +void interrupt_handler_89(); +void interrupt_handler_90(); +void interrupt_handler_91(); +void interrupt_handler_92(); +void interrupt_handler_93(); +void interrupt_handler_94(); +void interrupt_handler_95(); +void interrupt_handler_96(); +void interrupt_handler_97(); +void interrupt_handler_98(); +void interrupt_handler_99(); +void interrupt_handler_100(); +void interrupt_handler_101(); +void interrupt_handler_102(); +void interrupt_handler_103(); +void interrupt_handler_104(); +void interrupt_handler_105(); +void interrupt_handler_106(); +void interrupt_handler_107(); +void interrupt_handler_108(); +void interrupt_handler_109(); +void interrupt_handler_110(); +void interrupt_handler_111(); +void interrupt_handler_112(); +void interrupt_handler_113(); +void interrupt_handler_114(); +void interrupt_handler_115(); +void interrupt_handler_116(); +void interrupt_handler_117(); +void interrupt_handler_118(); +void interrupt_handler_119(); +void interrupt_handler_120(); +void interrupt_handler_121(); +void interrupt_handler_122(); +void interrupt_handler_123(); +void interrupt_handler_124(); +void interrupt_handler_125(); +void interrupt_handler_126(); +void interrupt_handler_127(); +void interrupt_handler_128(); +void interrupt_handler_129(); +void interrupt_handler_130(); +void interrupt_handler_131(); +void interrupt_handler_132(); +void interrupt_handler_133(); +void interrupt_handler_134(); +void interrupt_handler_135(); +void interrupt_handler_136(); +void interrupt_handler_137(); +void interrupt_handler_138(); +void interrupt_handler_139(); +void interrupt_handler_140(); +void interrupt_handler_141(); +void interrupt_handler_142(); +void interrupt_handler_143(); +void interrupt_handler_144(); +void interrupt_handler_145(); +void interrupt_handler_146(); +void interrupt_handler_147(); +void interrupt_handler_148(); +void interrupt_handler_149(); +void interrupt_handler_150(); +void interrupt_handler_151(); +void interrupt_handler_152(); +void interrupt_handler_153(); +void interrupt_handler_154(); +void interrupt_handler_155(); +void interrupt_handler_156(); +void interrupt_handler_157(); +void interrupt_handler_158(); +void interrupt_handler_159(); +void interrupt_handler_160(); +void interrupt_handler_161(); +void interrupt_handler_162(); +void interrupt_handler_163(); +void interrupt_handler_164(); +void interrupt_handler_165(); +void interrupt_handler_166(); +void interrupt_handler_167(); +void interrupt_handler_168(); +void interrupt_handler_169(); +void interrupt_handler_170(); +void interrupt_handler_171(); +void interrupt_handler_172(); +void interrupt_handler_173(); +void interrupt_handler_174(); +void interrupt_handler_175(); +void interrupt_handler_176(); +void interrupt_handler_177(); +void interrupt_handler_178(); +void interrupt_handler_179(); +void interrupt_handler_180(); +void interrupt_handler_181(); +void interrupt_handler_182(); +void interrupt_handler_183(); +void interrupt_handler_184(); +void interrupt_handler_185(); +void interrupt_handler_186(); +void interrupt_handler_187(); +void interrupt_handler_188(); +void interrupt_handler_189(); +void interrupt_handler_190(); +void interrupt_handler_191(); +void interrupt_handler_192(); +void interrupt_handler_193(); +void interrupt_handler_194(); +void interrupt_handler_195(); +void interrupt_handler_196(); +void interrupt_handler_197(); +void interrupt_handler_198(); +void interrupt_handler_199(); +void interrupt_handler_200(); +void interrupt_handler_201(); +void interrupt_handler_202(); +void interrupt_handler_203(); +void interrupt_handler_204(); +void interrupt_handler_205(); +void interrupt_handler_206(); +void interrupt_handler_207(); +void interrupt_handler_208(); +void interrupt_handler_209(); +void interrupt_handler_210(); +void interrupt_handler_211(); +void interrupt_handler_212(); +void interrupt_handler_213(); +void interrupt_handler_214(); +void interrupt_handler_215(); +void interrupt_handler_216(); +void interrupt_handler_217(); +void interrupt_handler_218(); +void interrupt_handler_219(); +void interrupt_handler_220(); +void interrupt_handler_221(); +void interrupt_handler_222(); +void interrupt_handler_223(); +void interrupt_handler_224(); +void interrupt_handler_225(); +void interrupt_handler_226(); +void interrupt_handler_227(); +void interrupt_handler_228(); +void interrupt_handler_229(); +void interrupt_handler_230(); +void interrupt_handler_231(); +void interrupt_handler_232(); +void interrupt_handler_233(); +void interrupt_handler_234(); +void interrupt_handler_235(); +void interrupt_handler_236(); +void interrupt_handler_237(); +void interrupt_handler_238(); +void interrupt_handler_239(); +void interrupt_handler_240(); +void interrupt_handler_241(); +void interrupt_handler_242(); +void interrupt_handler_243(); +void interrupt_handler_244(); +void interrupt_handler_245(); +void interrupt_handler_246(); +void interrupt_handler_247(); +void interrupt_handler_248(); +void interrupt_handler_249(); +void interrupt_handler_250(); +void interrupt_handler_251(); +void interrupt_handler_252(); +void interrupt_handler_253(); +void interrupt_handler_254(); +void interrupt_handler_255(); \ No newline at end of file diff --git a/asm_interrupts.s b/asm_interrupts.s index 37a8ff8..573df5f 100644 --- a/asm_interrupts.s +++ b/asm_interrupts.s @@ -1,10 +1,1540 @@ extern interrupt_handler ; the C interrupt handler +global interrupt_handler_0 +interrupt_handler_0: + push dword 0 + push dword 0 + jmp common_interrupt_handler + +global interrupt_handler_1 +interrupt_handler_1: + push dword 0 + push dword 1 + jmp common_interrupt_handler + +global interrupt_handler_2 +interrupt_handler_2: + push dword 0 + push dword 2 + jmp common_interrupt_handler + +global interrupt_handler_3 +interrupt_handler_3: + push dword 0 + push dword 3 + jmp common_interrupt_handler + +global interrupt_handler_4 +interrupt_handler_4: + push dword 0 + push dword 4 + jmp common_interrupt_handler + +global interrupt_handler_5 +interrupt_handler_5: + push dword 0 + push dword 5 + jmp common_interrupt_handler + +global interrupt_handler_6 +interrupt_handler_6: + push dword 0 + push dword 6 + jmp common_interrupt_handler + +global interrupt_handler_7 +interrupt_handler_7: + push dword 0 + push dword 7 + jmp common_interrupt_handler + +global interrupt_handler_8 +interrupt_handler_8: + push dword 0 + push dword 8 + jmp common_interrupt_handler + +global interrupt_handler_9 +interrupt_handler_9: + push dword 0 + push dword 9 + jmp common_interrupt_handler + +global interrupt_handler_10 +interrupt_handler_10: + push dword 0 + push dword 10 + jmp common_interrupt_handler + +global interrupt_handler_11 +interrupt_handler_11: + push dword 0 + push dword 11 + jmp common_interrupt_handler + +global interrupt_handler_12 +interrupt_handler_12: + push dword 0 + push dword 12 + jmp common_interrupt_handler + +global interrupt_handler_13 +interrupt_handler_13: + push dword 0 + push dword 13 + jmp common_interrupt_handler + +global interrupt_handler_14 +interrupt_handler_14: + push dword 0 + push dword 14 + jmp common_interrupt_handler + +global interrupt_handler_15 +interrupt_handler_15: + push dword 0 + push dword 15 + jmp common_interrupt_handler + +global interrupt_handler_16 +interrupt_handler_16: + push dword 0 + push dword 16 + jmp common_interrupt_handler + +global interrupt_handler_17 +interrupt_handler_17: + push dword 0 + push dword 17 + jmp common_interrupt_handler + +global interrupt_handler_18 +interrupt_handler_18: + push dword 0 + push dword 18 + jmp common_interrupt_handler + +global interrupt_handler_19 +interrupt_handler_19: + push dword 0 + push dword 19 + jmp common_interrupt_handler + +global interrupt_handler_20 +interrupt_handler_20: + push dword 0 + push dword 20 + jmp common_interrupt_handler + +global interrupt_handler_21 +interrupt_handler_21: + push dword 0 + push dword 21 + jmp common_interrupt_handler + +global interrupt_handler_22 +interrupt_handler_22: + push dword 0 + push dword 22 + jmp common_interrupt_handler + +global interrupt_handler_23 +interrupt_handler_23: + push dword 0 + push dword 23 + jmp common_interrupt_handler + +global interrupt_handler_24 +interrupt_handler_24: + push dword 0 + push dword 24 + jmp common_interrupt_handler + +global interrupt_handler_25 +interrupt_handler_25: + push dword 0 + push dword 25 + jmp common_interrupt_handler + +global interrupt_handler_26 +interrupt_handler_26: + push dword 0 + push dword 26 + jmp common_interrupt_handler + +global interrupt_handler_27 +interrupt_handler_27: + push dword 0 + push dword 27 + jmp common_interrupt_handler + +global interrupt_handler_28 +interrupt_handler_28: + push dword 0 + push dword 28 + jmp common_interrupt_handler + +global interrupt_handler_29 +interrupt_handler_29: + push dword 0 + push dword 29 + jmp common_interrupt_handler + +global interrupt_handler_30 +interrupt_handler_30: + push dword 0 + push dword 30 + jmp common_interrupt_handler + +global interrupt_handler_31 +interrupt_handler_31: + push dword 0 + push dword 31 + jmp common_interrupt_handler + +global interrupt_handler_32 +interrupt_handler_32: + push dword 0 + push dword 32 + jmp common_interrupt_handler + +global interrupt_handler_33 +interrupt_handler_33: + push dword 0 + push dword 33 + jmp common_interrupt_handler + +global interrupt_handler_34 +interrupt_handler_34: + push dword 0 + push dword 34 + jmp common_interrupt_handler + +global interrupt_handler_35 +interrupt_handler_35: + push dword 0 + push dword 35 + jmp common_interrupt_handler + +global interrupt_handler_36 +interrupt_handler_36: + push dword 0 + push dword 36 + jmp common_interrupt_handler + +global interrupt_handler_37 +interrupt_handler_37: + push dword 0 + push dword 37 + jmp common_interrupt_handler + +global interrupt_handler_38 +interrupt_handler_38: + push dword 0 + push dword 38 + jmp common_interrupt_handler + +global interrupt_handler_39 +interrupt_handler_39: + push dword 0 + push dword 39 + jmp common_interrupt_handler + +global interrupt_handler_40 +interrupt_handler_40: + push dword 0 + push dword 40 + jmp common_interrupt_handler + +global interrupt_handler_41 +interrupt_handler_41: + push dword 0 + push dword 41 + jmp common_interrupt_handler + +global interrupt_handler_42 +interrupt_handler_42: + push dword 0 + push dword 42 + jmp common_interrupt_handler + +global interrupt_handler_43 +interrupt_handler_43: + push dword 0 + push dword 43 + jmp common_interrupt_handler + +global interrupt_handler_44 +interrupt_handler_44: + push dword 0 + push dword 44 + jmp common_interrupt_handler + +global interrupt_handler_45 +interrupt_handler_45: + push dword 0 + push dword 45 + jmp common_interrupt_handler + +global interrupt_handler_46 +interrupt_handler_46: + push dword 0 + push dword 46 + jmp common_interrupt_handler + +global interrupt_handler_47 +interrupt_handler_47: + push dword 0 + push dword 47 + jmp common_interrupt_handler + +global interrupt_handler_48 +interrupt_handler_48: + push dword 0 + push dword 48 + jmp common_interrupt_handler + global interrupt_handler_49 interrupt_handler_49: - push dword 0 ; push 0 as error code - push dword 49 ; push the interrupt number - jmp common_interrupt_handler ; jump to the common handler + push dword 0 + push dword 49 + jmp common_interrupt_handler + +global interrupt_handler_50 +interrupt_handler_50: + push dword 0 + push dword 50 + jmp common_interrupt_handler + +global interrupt_handler_51 +interrupt_handler_51: + push dword 0 + push dword 51 + jmp common_interrupt_handler + +global interrupt_handler_52 +interrupt_handler_52: + push dword 0 + push dword 52 + jmp common_interrupt_handler + +global interrupt_handler_53 +interrupt_handler_53: + push dword 0 + push dword 53 + jmp common_interrupt_handler + +global interrupt_handler_54 +interrupt_handler_54: + push dword 0 + push dword 54 + jmp common_interrupt_handler + +global interrupt_handler_55 +interrupt_handler_55: + push dword 0 + push dword 55 + jmp common_interrupt_handler + +global interrupt_handler_56 +interrupt_handler_56: + push dword 0 + push dword 56 + jmp common_interrupt_handler + +global interrupt_handler_57 +interrupt_handler_57: + push dword 0 + push dword 57 + jmp common_interrupt_handler + +global interrupt_handler_58 +interrupt_handler_58: + push dword 0 + push dword 58 + jmp common_interrupt_handler + +global interrupt_handler_59 +interrupt_handler_59: + push dword 0 + push dword 59 + jmp common_interrupt_handler + +global interrupt_handler_60 +interrupt_handler_60: + push dword 0 + push dword 60 + jmp common_interrupt_handler + +global interrupt_handler_61 +interrupt_handler_61: + push dword 0 + push dword 61 + jmp common_interrupt_handler + +global interrupt_handler_62 +interrupt_handler_62: + push dword 0 + push dword 62 + jmp common_interrupt_handler + +global interrupt_handler_63 +interrupt_handler_63: + push dword 0 + push dword 63 + jmp common_interrupt_handler + +global interrupt_handler_64 +interrupt_handler_64: + push dword 0 + push dword 64 + jmp common_interrupt_handler + +global interrupt_handler_65 +interrupt_handler_65: + push dword 0 + push dword 65 + jmp common_interrupt_handler + +global interrupt_handler_66 +interrupt_handler_66: + push dword 0 + push dword 66 + jmp common_interrupt_handler + +global interrupt_handler_67 +interrupt_handler_67: + push dword 0 + push dword 67 + jmp common_interrupt_handler + +global interrupt_handler_68 +interrupt_handler_68: + push dword 0 + push dword 68 + jmp common_interrupt_handler + +global interrupt_handler_69 +interrupt_handler_69: + push dword 0 + push dword 69 + jmp common_interrupt_handler + +global interrupt_handler_70 +interrupt_handler_70: + push dword 0 + push dword 70 + jmp common_interrupt_handler + +global interrupt_handler_71 +interrupt_handler_71: + push dword 0 + push dword 71 + jmp common_interrupt_handler + +global interrupt_handler_72 +interrupt_handler_72: + push dword 0 + push dword 72 + jmp common_interrupt_handler + +global interrupt_handler_73 +interrupt_handler_73: + push dword 0 + push dword 73 + jmp common_interrupt_handler + +global interrupt_handler_74 +interrupt_handler_74: + push dword 0 + push dword 74 + jmp common_interrupt_handler + +global interrupt_handler_75 +interrupt_handler_75: + push dword 0 + push dword 75 + jmp common_interrupt_handler + +global interrupt_handler_76 +interrupt_handler_76: + push dword 0 + push dword 76 + jmp common_interrupt_handler + +global interrupt_handler_77 +interrupt_handler_77: + push dword 0 + push dword 77 + jmp common_interrupt_handler + +global interrupt_handler_78 +interrupt_handler_78: + push dword 0 + push dword 78 + jmp common_interrupt_handler + +global interrupt_handler_79 +interrupt_handler_79: + push dword 0 + push dword 79 + jmp common_interrupt_handler + +global interrupt_handler_80 +interrupt_handler_80: + push dword 0 + push dword 80 + jmp common_interrupt_handler + +global interrupt_handler_81 +interrupt_handler_81: + push dword 0 + push dword 81 + jmp common_interrupt_handler + +global interrupt_handler_82 +interrupt_handler_82: + push dword 0 + push dword 82 + jmp common_interrupt_handler + +global interrupt_handler_83 +interrupt_handler_83: + push dword 0 + push dword 83 + jmp common_interrupt_handler + +global interrupt_handler_84 +interrupt_handler_84: + push dword 0 + push dword 84 + jmp common_interrupt_handler + +global interrupt_handler_85 +interrupt_handler_85: + push dword 0 + push dword 85 + jmp common_interrupt_handler + +global interrupt_handler_86 +interrupt_handler_86: + push dword 0 + push dword 86 + jmp common_interrupt_handler + +global interrupt_handler_87 +interrupt_handler_87: + push dword 0 + push dword 87 + jmp common_interrupt_handler + +global interrupt_handler_88 +interrupt_handler_88: + push dword 0 + push dword 88 + jmp common_interrupt_handler + +global interrupt_handler_89 +interrupt_handler_89: + push dword 0 + push dword 89 + jmp common_interrupt_handler + +global interrupt_handler_90 +interrupt_handler_90: + push dword 0 + push dword 90 + jmp common_interrupt_handler + +global interrupt_handler_91 +interrupt_handler_91: + push dword 0 + push dword 91 + jmp common_interrupt_handler + +global interrupt_handler_92 +interrupt_handler_92: + push dword 0 + push dword 92 + jmp common_interrupt_handler + +global interrupt_handler_93 +interrupt_handler_93: + push dword 0 + push dword 93 + jmp common_interrupt_handler + +global interrupt_handler_94 +interrupt_handler_94: + push dword 0 + push dword 94 + jmp common_interrupt_handler + +global interrupt_handler_95 +interrupt_handler_95: + push dword 0 + push dword 95 + jmp common_interrupt_handler + +global interrupt_handler_96 +interrupt_handler_96: + push dword 0 + push dword 96 + jmp common_interrupt_handler + +global interrupt_handler_97 +interrupt_handler_97: + push dword 0 + push dword 97 + jmp common_interrupt_handler + +global interrupt_handler_98 +interrupt_handler_98: + push dword 0 + push dword 98 + jmp common_interrupt_handler + +global interrupt_handler_99 +interrupt_handler_99: + push dword 0 + push dword 99 + jmp common_interrupt_handler + +global interrupt_handler_100 +interrupt_handler_100: + push dword 0 + push dword 100 + jmp common_interrupt_handler + +global interrupt_handler_101 +interrupt_handler_101: + push dword 0 + push dword 101 + jmp common_interrupt_handler + +global interrupt_handler_102 +interrupt_handler_102: + push dword 0 + push dword 102 + jmp common_interrupt_handler + +global interrupt_handler_103 +interrupt_handler_103: + push dword 0 + push dword 103 + jmp common_interrupt_handler + +global interrupt_handler_104 +interrupt_handler_104: + push dword 0 + push dword 104 + jmp common_interrupt_handler + +global interrupt_handler_105 +interrupt_handler_105: + push dword 0 + push dword 105 + jmp common_interrupt_handler + +global interrupt_handler_106 +interrupt_handler_106: + push dword 0 + push dword 106 + jmp common_interrupt_handler + +global interrupt_handler_107 +interrupt_handler_107: + push dword 0 + push dword 107 + jmp common_interrupt_handler + +global interrupt_handler_108 +interrupt_handler_108: + push dword 0 + push dword 108 + jmp common_interrupt_handler + +global interrupt_handler_109 +interrupt_handler_109: + push dword 0 + push dword 109 + jmp common_interrupt_handler + +global interrupt_handler_110 +interrupt_handler_110: + push dword 0 + push dword 110 + jmp common_interrupt_handler + +global interrupt_handler_111 +interrupt_handler_111: + push dword 0 + push dword 111 + jmp common_interrupt_handler + +global interrupt_handler_112 +interrupt_handler_112: + push dword 0 + push dword 112 + jmp common_interrupt_handler + +global interrupt_handler_113 +interrupt_handler_113: + push dword 0 + push dword 113 + jmp common_interrupt_handler + +global interrupt_handler_114 +interrupt_handler_114: + push dword 0 + push dword 114 + jmp common_interrupt_handler + +global interrupt_handler_115 +interrupt_handler_115: + push dword 0 + push dword 115 + jmp common_interrupt_handler + +global interrupt_handler_116 +interrupt_handler_116: + push dword 0 + push dword 116 + jmp common_interrupt_handler + +global interrupt_handler_117 +interrupt_handler_117: + push dword 0 + push dword 117 + jmp common_interrupt_handler + +global interrupt_handler_118 +interrupt_handler_118: + push dword 0 + push dword 118 + jmp common_interrupt_handler + +global interrupt_handler_119 +interrupt_handler_119: + push dword 0 + push dword 119 + jmp common_interrupt_handler + +global interrupt_handler_120 +interrupt_handler_120: + push dword 0 + push dword 120 + jmp common_interrupt_handler + +global interrupt_handler_121 +interrupt_handler_121: + push dword 0 + push dword 121 + jmp common_interrupt_handler + +global interrupt_handler_122 +interrupt_handler_122: + push dword 0 + push dword 122 + jmp common_interrupt_handler + +global interrupt_handler_123 +interrupt_handler_123: + push dword 0 + push dword 123 + jmp common_interrupt_handler + +global interrupt_handler_124 +interrupt_handler_124: + push dword 0 + push dword 124 + jmp common_interrupt_handler + +global interrupt_handler_125 +interrupt_handler_125: + push dword 0 + push dword 125 + jmp common_interrupt_handler + +global interrupt_handler_126 +interrupt_handler_126: + push dword 0 + push dword 126 + jmp common_interrupt_handler + +global interrupt_handler_127 +interrupt_handler_127: + push dword 0 + push dword 127 + jmp common_interrupt_handler + +global interrupt_handler_128 +interrupt_handler_128: + push dword 0 + push dword 128 + jmp common_interrupt_handler + +global interrupt_handler_129 +interrupt_handler_129: + push dword 0 + push dword 129 + jmp common_interrupt_handler + +global interrupt_handler_130 +interrupt_handler_130: + push dword 0 + push dword 130 + jmp common_interrupt_handler + +global interrupt_handler_131 +interrupt_handler_131: + push dword 0 + push dword 131 + jmp common_interrupt_handler + +global interrupt_handler_132 +interrupt_handler_132: + push dword 0 + push dword 132 + jmp common_interrupt_handler + +global interrupt_handler_133 +interrupt_handler_133: + push dword 0 + push dword 133 + jmp common_interrupt_handler + +global interrupt_handler_134 +interrupt_handler_134: + push dword 0 + push dword 134 + jmp common_interrupt_handler + +global interrupt_handler_135 +interrupt_handler_135: + push dword 0 + push dword 135 + jmp common_interrupt_handler + +global interrupt_handler_136 +interrupt_handler_136: + push dword 0 + push dword 136 + jmp common_interrupt_handler + +global interrupt_handler_137 +interrupt_handler_137: + push dword 0 + push dword 137 + jmp common_interrupt_handler + +global interrupt_handler_138 +interrupt_handler_138: + push dword 0 + push dword 138 + jmp common_interrupt_handler + +global interrupt_handler_139 +interrupt_handler_139: + push dword 0 + push dword 139 + jmp common_interrupt_handler + +global interrupt_handler_140 +interrupt_handler_140: + push dword 0 + push dword 140 + jmp common_interrupt_handler + +global interrupt_handler_141 +interrupt_handler_141: + push dword 0 + push dword 141 + jmp common_interrupt_handler + +global interrupt_handler_142 +interrupt_handler_142: + push dword 0 + push dword 142 + jmp common_interrupt_handler + +global interrupt_handler_143 +interrupt_handler_143: + push dword 0 + push dword 143 + jmp common_interrupt_handler + +global interrupt_handler_144 +interrupt_handler_144: + push dword 0 + push dword 144 + jmp common_interrupt_handler + +global interrupt_handler_145 +interrupt_handler_145: + push dword 0 + push dword 145 + jmp common_interrupt_handler + +global interrupt_handler_146 +interrupt_handler_146: + push dword 0 + push dword 146 + jmp common_interrupt_handler + +global interrupt_handler_147 +interrupt_handler_147: + push dword 0 + push dword 147 + jmp common_interrupt_handler + +global interrupt_handler_148 +interrupt_handler_148: + push dword 0 + push dword 148 + jmp common_interrupt_handler + +global interrupt_handler_149 +interrupt_handler_149: + push dword 0 + push dword 149 + jmp common_interrupt_handler + +global interrupt_handler_150 +interrupt_handler_150: + push dword 0 + push dword 150 + jmp common_interrupt_handler + +global interrupt_handler_151 +interrupt_handler_151: + push dword 0 + push dword 151 + jmp common_interrupt_handler + +global interrupt_handler_152 +interrupt_handler_152: + push dword 0 + push dword 152 + jmp common_interrupt_handler + +global interrupt_handler_153 +interrupt_handler_153: + push dword 0 + push dword 153 + jmp common_interrupt_handler + +global interrupt_handler_154 +interrupt_handler_154: + push dword 0 + push dword 154 + jmp common_interrupt_handler + +global interrupt_handler_155 +interrupt_handler_155: + push dword 0 + push dword 155 + jmp common_interrupt_handler + +global interrupt_handler_156 +interrupt_handler_156: + push dword 0 + push dword 156 + jmp common_interrupt_handler + +global interrupt_handler_157 +interrupt_handler_157: + push dword 0 + push dword 157 + jmp common_interrupt_handler + +global interrupt_handler_158 +interrupt_handler_158: + push dword 0 + push dword 158 + jmp common_interrupt_handler + +global interrupt_handler_159 +interrupt_handler_159: + push dword 0 + push dword 159 + jmp common_interrupt_handler + +global interrupt_handler_160 +interrupt_handler_160: + push dword 0 + push dword 160 + jmp common_interrupt_handler + +global interrupt_handler_161 +interrupt_handler_161: + push dword 0 + push dword 161 + jmp common_interrupt_handler + +global interrupt_handler_162 +interrupt_handler_162: + push dword 0 + push dword 162 + jmp common_interrupt_handler + +global interrupt_handler_163 +interrupt_handler_163: + push dword 0 + push dword 163 + jmp common_interrupt_handler + +global interrupt_handler_164 +interrupt_handler_164: + push dword 0 + push dword 164 + jmp common_interrupt_handler + +global interrupt_handler_165 +interrupt_handler_165: + push dword 0 + push dword 165 + jmp common_interrupt_handler + +global interrupt_handler_166 +interrupt_handler_166: + push dword 0 + push dword 166 + jmp common_interrupt_handler + +global interrupt_handler_167 +interrupt_handler_167: + push dword 0 + push dword 167 + jmp common_interrupt_handler + +global interrupt_handler_168 +interrupt_handler_168: + push dword 0 + push dword 168 + jmp common_interrupt_handler + +global interrupt_handler_169 +interrupt_handler_169: + push dword 0 + push dword 169 + jmp common_interrupt_handler + +global interrupt_handler_170 +interrupt_handler_170: + push dword 0 + push dword 170 + jmp common_interrupt_handler + +global interrupt_handler_171 +interrupt_handler_171: + push dword 0 + push dword 171 + jmp common_interrupt_handler + +global interrupt_handler_172 +interrupt_handler_172: + push dword 0 + push dword 172 + jmp common_interrupt_handler + +global interrupt_handler_173 +interrupt_handler_173: + push dword 0 + push dword 173 + jmp common_interrupt_handler + +global interrupt_handler_174 +interrupt_handler_174: + push dword 0 + push dword 174 + jmp common_interrupt_handler + +global interrupt_handler_175 +interrupt_handler_175: + push dword 0 + push dword 175 + jmp common_interrupt_handler + +global interrupt_handler_176 +interrupt_handler_176: + push dword 0 + push dword 176 + jmp common_interrupt_handler + +global interrupt_handler_177 +interrupt_handler_177: + push dword 0 + push dword 177 + jmp common_interrupt_handler + +global interrupt_handler_178 +interrupt_handler_178: + push dword 0 + push dword 178 + jmp common_interrupt_handler + +global interrupt_handler_179 +interrupt_handler_179: + push dword 0 + push dword 179 + jmp common_interrupt_handler + +global interrupt_handler_180 +interrupt_handler_180: + push dword 0 + push dword 180 + jmp common_interrupt_handler + +global interrupt_handler_181 +interrupt_handler_181: + push dword 0 + push dword 181 + jmp common_interrupt_handler + +global interrupt_handler_182 +interrupt_handler_182: + push dword 0 + push dword 182 + jmp common_interrupt_handler + +global interrupt_handler_183 +interrupt_handler_183: + push dword 0 + push dword 183 + jmp common_interrupt_handler + +global interrupt_handler_184 +interrupt_handler_184: + push dword 0 + push dword 184 + jmp common_interrupt_handler + +global interrupt_handler_185 +interrupt_handler_185: + push dword 0 + push dword 185 + jmp common_interrupt_handler + +global interrupt_handler_186 +interrupt_handler_186: + push dword 0 + push dword 186 + jmp common_interrupt_handler + +global interrupt_handler_187 +interrupt_handler_187: + push dword 0 + push dword 187 + jmp common_interrupt_handler + +global interrupt_handler_188 +interrupt_handler_188: + push dword 0 + push dword 188 + jmp common_interrupt_handler + +global interrupt_handler_189 +interrupt_handler_189: + push dword 0 + push dword 189 + jmp common_interrupt_handler + +global interrupt_handler_190 +interrupt_handler_190: + push dword 0 + push dword 190 + jmp common_interrupt_handler + +global interrupt_handler_191 +interrupt_handler_191: + push dword 0 + push dword 191 + jmp common_interrupt_handler + +global interrupt_handler_192 +interrupt_handler_192: + push dword 0 + push dword 192 + jmp common_interrupt_handler + +global interrupt_handler_193 +interrupt_handler_193: + push dword 0 + push dword 193 + jmp common_interrupt_handler + +global interrupt_handler_194 +interrupt_handler_194: + push dword 0 + push dword 194 + jmp common_interrupt_handler + +global interrupt_handler_195 +interrupt_handler_195: + push dword 0 + push dword 195 + jmp common_interrupt_handler + +global interrupt_handler_196 +interrupt_handler_196: + push dword 0 + push dword 196 + jmp common_interrupt_handler + +global interrupt_handler_197 +interrupt_handler_197: + push dword 0 + push dword 197 + jmp common_interrupt_handler + +global interrupt_handler_198 +interrupt_handler_198: + push dword 0 + push dword 198 + jmp common_interrupt_handler + +global interrupt_handler_199 +interrupt_handler_199: + push dword 0 + push dword 199 + jmp common_interrupt_handler + +global interrupt_handler_200 +interrupt_handler_200: + push dword 0 + push dword 200 + jmp common_interrupt_handler + +global interrupt_handler_201 +interrupt_handler_201: + push dword 0 + push dword 201 + jmp common_interrupt_handler + +global interrupt_handler_202 +interrupt_handler_202: + push dword 0 + push dword 202 + jmp common_interrupt_handler + +global interrupt_handler_203 +interrupt_handler_203: + push dword 0 + push dword 203 + jmp common_interrupt_handler + +global interrupt_handler_204 +interrupt_handler_204: + push dword 0 + push dword 204 + jmp common_interrupt_handler + +global interrupt_handler_205 +interrupt_handler_205: + push dword 0 + push dword 205 + jmp common_interrupt_handler + +global interrupt_handler_206 +interrupt_handler_206: + push dword 0 + push dword 206 + jmp common_interrupt_handler + +global interrupt_handler_207 +interrupt_handler_207: + push dword 0 + push dword 207 + jmp common_interrupt_handler + +global interrupt_handler_208 +interrupt_handler_208: + push dword 0 + push dword 208 + jmp common_interrupt_handler + +global interrupt_handler_209 +interrupt_handler_209: + push dword 0 + push dword 209 + jmp common_interrupt_handler + +global interrupt_handler_210 +interrupt_handler_210: + push dword 0 + push dword 210 + jmp common_interrupt_handler + +global interrupt_handler_211 +interrupt_handler_211: + push dword 0 + push dword 211 + jmp common_interrupt_handler + +global interrupt_handler_212 +interrupt_handler_212: + push dword 0 + push dword 212 + jmp common_interrupt_handler + +global interrupt_handler_213 +interrupt_handler_213: + push dword 0 + push dword 213 + jmp common_interrupt_handler + +global interrupt_handler_214 +interrupt_handler_214: + push dword 0 + push dword 214 + jmp common_interrupt_handler + +global interrupt_handler_215 +interrupt_handler_215: + push dword 0 + push dword 215 + jmp common_interrupt_handler + +global interrupt_handler_216 +interrupt_handler_216: + push dword 0 + push dword 216 + jmp common_interrupt_handler + +global interrupt_handler_217 +interrupt_handler_217: + push dword 0 + push dword 217 + jmp common_interrupt_handler + +global interrupt_handler_218 +interrupt_handler_218: + push dword 0 + push dword 218 + jmp common_interrupt_handler + +global interrupt_handler_219 +interrupt_handler_219: + push dword 0 + push dword 219 + jmp common_interrupt_handler + +global interrupt_handler_220 +interrupt_handler_220: + push dword 0 + push dword 220 + jmp common_interrupt_handler + +global interrupt_handler_221 +interrupt_handler_221: + push dword 0 + push dword 221 + jmp common_interrupt_handler + +global interrupt_handler_222 +interrupt_handler_222: + push dword 0 + push dword 222 + jmp common_interrupt_handler + +global interrupt_handler_223 +interrupt_handler_223: + push dword 0 + push dword 223 + jmp common_interrupt_handler + +global interrupt_handler_224 +interrupt_handler_224: + push dword 0 + push dword 224 + jmp common_interrupt_handler + +global interrupt_handler_225 +interrupt_handler_225: + push dword 0 + push dword 225 + jmp common_interrupt_handler + +global interrupt_handler_226 +interrupt_handler_226: + push dword 0 + push dword 226 + jmp common_interrupt_handler + +global interrupt_handler_227 +interrupt_handler_227: + push dword 0 + push dword 227 + jmp common_interrupt_handler + +global interrupt_handler_228 +interrupt_handler_228: + push dword 0 + push dword 228 + jmp common_interrupt_handler + +global interrupt_handler_229 +interrupt_handler_229: + push dword 0 + push dword 229 + jmp common_interrupt_handler + +global interrupt_handler_230 +interrupt_handler_230: + push dword 0 + push dword 230 + jmp common_interrupt_handler + +global interrupt_handler_231 +interrupt_handler_231: + push dword 0 + push dword 231 + jmp common_interrupt_handler + +global interrupt_handler_232 +interrupt_handler_232: + push dword 0 + push dword 232 + jmp common_interrupt_handler + +global interrupt_handler_233 +interrupt_handler_233: + push dword 0 + push dword 233 + jmp common_interrupt_handler + +global interrupt_handler_234 +interrupt_handler_234: + push dword 0 + push dword 234 + jmp common_interrupt_handler + +global interrupt_handler_235 +interrupt_handler_235: + push dword 0 + push dword 235 + jmp common_interrupt_handler + +global interrupt_handler_236 +interrupt_handler_236: + push dword 0 + push dword 236 + jmp common_interrupt_handler + +global interrupt_handler_237 +interrupt_handler_237: + push dword 0 + push dword 237 + jmp common_interrupt_handler + +global interrupt_handler_238 +interrupt_handler_238: + push dword 0 + push dword 238 + jmp common_interrupt_handler + +global interrupt_handler_239 +interrupt_handler_239: + push dword 0 + push dword 239 + jmp common_interrupt_handler + +global interrupt_handler_240 +interrupt_handler_240: + push dword 0 + push dword 240 + jmp common_interrupt_handler + +global interrupt_handler_241 +interrupt_handler_241: + push dword 0 + push dword 241 + jmp common_interrupt_handler + +global interrupt_handler_242 +interrupt_handler_242: + push dword 0 + push dword 242 + jmp common_interrupt_handler + +global interrupt_handler_243 +interrupt_handler_243: + push dword 0 + push dword 243 + jmp common_interrupt_handler + +global interrupt_handler_244 +interrupt_handler_244: + push dword 0 + push dword 244 + jmp common_interrupt_handler + +global interrupt_handler_245 +interrupt_handler_245: + push dword 0 + push dword 245 + jmp common_interrupt_handler + +global interrupt_handler_246 +interrupt_handler_246: + push dword 0 + push dword 246 + jmp common_interrupt_handler + +global interrupt_handler_247 +interrupt_handler_247: + push dword 0 + push dword 247 + jmp common_interrupt_handler + +global interrupt_handler_248 +interrupt_handler_248: + push dword 0 + push dword 248 + jmp common_interrupt_handler + +global interrupt_handler_249 +interrupt_handler_249: + push dword 0 + push dword 249 + jmp common_interrupt_handler + +global interrupt_handler_250 +interrupt_handler_250: + push dword 0 + push dword 250 + jmp common_interrupt_handler + +global interrupt_handler_251 +interrupt_handler_251: + push dword 0 + push dword 251 + jmp common_interrupt_handler + +global interrupt_handler_252 +interrupt_handler_252: + push dword 0 + push dword 252 + jmp common_interrupt_handler + +global interrupt_handler_253 +interrupt_handler_253: + push dword 0 + push dword 253 + jmp common_interrupt_handler + +global interrupt_handler_254 +interrupt_handler_254: + push dword 0 + push dword 254 + jmp common_interrupt_handler + +global interrupt_handler_255 +interrupt_handler_255: + push dword 0 + push dword 255 + jmp common_interrupt_handler common_interrupt_handler: ; the common parts of the generic interrupt handler ; save the registers diff --git a/drivers/keyboard.c b/drivers/keyboard.c new file mode 100644 index 0000000..eb95355 --- /dev/null +++ b/drivers/keyboard.c @@ -0,0 +1,25 @@ +#include "keyboard.h" +#include "../assembly_interface.h" +#include "../stdio.h" +#include "../types.h" + +#define KBD_DATA_PORT 0x60 + +/** read_scan_code: +* Reads a scan code from the keyboard +* +* @return The scan code (NOT an ASCII character!) +*/ +uint8_t read_scan_code() +{ + return inb(KBD_DATA_PORT); +} + +uint8_t consume_scan_code() { + uint8_t scan_code = read_scan_code(); + log("consume_scan_code() consumed: "); + print_uint8(LOG, scan_code); + log("\n"); + + return scan_code; +} \ No newline at end of file diff --git a/drivers/keyboard.h b/drivers/keyboard.h new file mode 100644 index 0000000..8beec47 --- /dev/null +++ b/drivers/keyboard.h @@ -0,0 +1,8 @@ +#ifndef INCLUDE_KEYBOARD_H +#define INCLUDE_KEYBOARD_H + +#include "../types.h" + +uint8_t consume_scan_code(); + +#endif /* INCLUDE_KEYBOARD_H */ \ No newline at end of file diff --git a/drivers/pic.c b/drivers/pic.c new file mode 100644 index 0000000..f2c078e --- /dev/null +++ b/drivers/pic.c @@ -0,0 +1,30 @@ +#include "pic.h" +#include "../assembly_interface.h" + +#define PIC1_PORT_A 0x20 +#define PIC2_PORT_A 0xA0 + +/* The PIC interrupts have been remapped */ +#define PIC1_START_INTERRUPT 0x20 +#define PIC2_START_INTERRUPT 0x28 +#define PIC2_END_INTERRUPT PIC2_START_INTERRUPT + 7 + +#define PIC_ACK 0x20 + +/** pic_acknowledge: + * Acknowledges an interrupt from either PIC 1 or PIC 2. + * + * @param num The number of the interrupt + */ +void pic_acknowledge(uint32_t interrupt) +{ + if (interrupt < PIC1_START_INTERRUPT || interrupt > PIC2_END_INTERRUPT) { + return; + } + + if (interrupt < PIC2_START_INTERRUPT) { + outb(PIC1_PORT_A, PIC_ACK); + } else { + outb(PIC2_PORT_A, PIC_ACK); + } +} \ No newline at end of file diff --git a/drivers/pic.h b/drivers/pic.h new file mode 100644 index 0000000..1bb3757 --- /dev/null +++ b/drivers/pic.h @@ -0,0 +1,13 @@ +#ifndef INCLUDE_PIC_H +#define INCLUDE_PIC_H + +#include "../types.h" + +/** pic_acknowledge: + * Acknowledges an interrupt from either PIC 1 or PIC 2. + * + * @param num The number of the interrupt + */ +void pic_acknowledge(uint32_t interrupt); + +#endif /* INCLUDE_PIC_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index e9632e7..73a930f 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,6 +1,8 @@ #include "interrupts.h" #include "assembly_interface.h" +#include "drivers/keyboard.h" +#include "drivers/pic.h" #include "stdio.h" void enable_keyboard_interrupts() { @@ -20,29 +22,18 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t print_uint32(LOG, interrupt_number); log("\n"); - log("cpu.eax: "); - print_uint32(LOG, cpu.eax); - log("\n"); - log("cpu.ebx: "); - print_uint32(LOG, cpu.ebx); - log("\n"); - log("cpu.ecx: "); - print_uint32(LOG, cpu.ecx); - log("\n"); - log("cpu.edx: "); - print_uint32(LOG, cpu.edx); - log("\n"); - log("cpu.esi: "); - print_uint32(LOG, cpu.esi); - log("\n"); - log("cpu.edi: "); - print_uint32(LOG, cpu.edi); - log("\n"); - log("cpu.esp: "); - print_uint32(LOG, cpu.esp); - log("\n"); - log("cpu.ebp: "); - print_uint32(LOG, cpu.ebp); - log("\n"); - return; + if (cpu.eax) {}; // Avoid unused parameter error + + switch(interrupt_number) { + case(0x00000009): + consume_scan_code(); + pic_acknowledge(interrupt_number); + break; + + default: + log("Unhandled Interrupt: "); + print_uint32(LOG, interrupt_number); + log("\n"); + break; + } } diff --git a/kmain.c b/kmain.c index 25cecf9..2ae69b7 100644 --- a/kmain.c +++ b/kmain.c @@ -75,18 +75,278 @@ void initialize_gdt() { // with the correct values (0x8 for cs, 0x10 for the others) } +uint32_t interrupt_handler_addresses[] = { + (uint32_t) interrupt_handler_0, + (uint32_t) interrupt_handler_1, + (uint32_t) interrupt_handler_2, + (uint32_t) interrupt_handler_3, + (uint32_t) interrupt_handler_4, + (uint32_t) interrupt_handler_5, + (uint32_t) interrupt_handler_6, + (uint32_t) interrupt_handler_7, + (uint32_t) interrupt_handler_8, + (uint32_t) interrupt_handler_9, + (uint32_t) interrupt_handler_10, + (uint32_t) interrupt_handler_11, + (uint32_t) interrupt_handler_12, + (uint32_t) interrupt_handler_13, + (uint32_t) interrupt_handler_14, + (uint32_t) interrupt_handler_15, + (uint32_t) interrupt_handler_16, + (uint32_t) interrupt_handler_17, + (uint32_t) interrupt_handler_18, + (uint32_t) interrupt_handler_19, + (uint32_t) interrupt_handler_20, + (uint32_t) interrupt_handler_21, + (uint32_t) interrupt_handler_22, + (uint32_t) interrupt_handler_23, + (uint32_t) interrupt_handler_24, + (uint32_t) interrupt_handler_25, + (uint32_t) interrupt_handler_26, + (uint32_t) interrupt_handler_27, + (uint32_t) interrupt_handler_28, + (uint32_t) interrupt_handler_29, + (uint32_t) interrupt_handler_30, + (uint32_t) interrupt_handler_31, + (uint32_t) interrupt_handler_32, + (uint32_t) interrupt_handler_33, + (uint32_t) interrupt_handler_34, + (uint32_t) interrupt_handler_35, + (uint32_t) interrupt_handler_36, + (uint32_t) interrupt_handler_37, + (uint32_t) interrupt_handler_38, + (uint32_t) interrupt_handler_39, + (uint32_t) interrupt_handler_40, + (uint32_t) interrupt_handler_41, + (uint32_t) interrupt_handler_42, + (uint32_t) interrupt_handler_43, + (uint32_t) interrupt_handler_44, + (uint32_t) interrupt_handler_45, + (uint32_t) interrupt_handler_46, + (uint32_t) interrupt_handler_47, + (uint32_t) interrupt_handler_48, + (uint32_t) interrupt_handler_49, + (uint32_t) interrupt_handler_50, + (uint32_t) interrupt_handler_51, + (uint32_t) interrupt_handler_52, + (uint32_t) interrupt_handler_53, + (uint32_t) interrupt_handler_54, + (uint32_t) interrupt_handler_55, + (uint32_t) interrupt_handler_56, + (uint32_t) interrupt_handler_57, + (uint32_t) interrupt_handler_58, + (uint32_t) interrupt_handler_59, + (uint32_t) interrupt_handler_60, + (uint32_t) interrupt_handler_61, + (uint32_t) interrupt_handler_62, + (uint32_t) interrupt_handler_63, + (uint32_t) interrupt_handler_64, + (uint32_t) interrupt_handler_65, + (uint32_t) interrupt_handler_66, + (uint32_t) interrupt_handler_67, + (uint32_t) interrupt_handler_68, + (uint32_t) interrupt_handler_69, + (uint32_t) interrupt_handler_70, + (uint32_t) interrupt_handler_71, + (uint32_t) interrupt_handler_72, + (uint32_t) interrupt_handler_73, + (uint32_t) interrupt_handler_74, + (uint32_t) interrupt_handler_75, + (uint32_t) interrupt_handler_76, + (uint32_t) interrupt_handler_77, + (uint32_t) interrupt_handler_78, + (uint32_t) interrupt_handler_79, + (uint32_t) interrupt_handler_80, + (uint32_t) interrupt_handler_81, + (uint32_t) interrupt_handler_82, + (uint32_t) interrupt_handler_83, + (uint32_t) interrupt_handler_84, + (uint32_t) interrupt_handler_85, + (uint32_t) interrupt_handler_86, + (uint32_t) interrupt_handler_87, + (uint32_t) interrupt_handler_88, + (uint32_t) interrupt_handler_89, + (uint32_t) interrupt_handler_90, + (uint32_t) interrupt_handler_91, + (uint32_t) interrupt_handler_92, + (uint32_t) interrupt_handler_93, + (uint32_t) interrupt_handler_94, + (uint32_t) interrupt_handler_95, + (uint32_t) interrupt_handler_96, + (uint32_t) interrupt_handler_97, + (uint32_t) interrupt_handler_98, + (uint32_t) interrupt_handler_99, + (uint32_t) interrupt_handler_100, + (uint32_t) interrupt_handler_101, + (uint32_t) interrupt_handler_102, + (uint32_t) interrupt_handler_103, + (uint32_t) interrupt_handler_104, + (uint32_t) interrupt_handler_105, + (uint32_t) interrupt_handler_106, + (uint32_t) interrupt_handler_107, + (uint32_t) interrupt_handler_108, + (uint32_t) interrupt_handler_109, + (uint32_t) interrupt_handler_110, + (uint32_t) interrupt_handler_111, + (uint32_t) interrupt_handler_112, + (uint32_t) interrupt_handler_113, + (uint32_t) interrupt_handler_114, + (uint32_t) interrupt_handler_115, + (uint32_t) interrupt_handler_116, + (uint32_t) interrupt_handler_117, + (uint32_t) interrupt_handler_118, + (uint32_t) interrupt_handler_119, + (uint32_t) interrupt_handler_120, + (uint32_t) interrupt_handler_121, + (uint32_t) interrupt_handler_122, + (uint32_t) interrupt_handler_123, + (uint32_t) interrupt_handler_124, + (uint32_t) interrupt_handler_125, + (uint32_t) interrupt_handler_126, + (uint32_t) interrupt_handler_127, + (uint32_t) interrupt_handler_128, + (uint32_t) interrupt_handler_129, + (uint32_t) interrupt_handler_130, + (uint32_t) interrupt_handler_131, + (uint32_t) interrupt_handler_132, + (uint32_t) interrupt_handler_133, + (uint32_t) interrupt_handler_134, + (uint32_t) interrupt_handler_135, + (uint32_t) interrupt_handler_136, + (uint32_t) interrupt_handler_137, + (uint32_t) interrupt_handler_138, + (uint32_t) interrupt_handler_139, + (uint32_t) interrupt_handler_140, + (uint32_t) interrupt_handler_141, + (uint32_t) interrupt_handler_142, + (uint32_t) interrupt_handler_143, + (uint32_t) interrupt_handler_144, + (uint32_t) interrupt_handler_145, + (uint32_t) interrupt_handler_146, + (uint32_t) interrupt_handler_147, + (uint32_t) interrupt_handler_148, + (uint32_t) interrupt_handler_149, + (uint32_t) interrupt_handler_150, + (uint32_t) interrupt_handler_151, + (uint32_t) interrupt_handler_152, + (uint32_t) interrupt_handler_153, + (uint32_t) interrupt_handler_154, + (uint32_t) interrupt_handler_155, + (uint32_t) interrupt_handler_156, + (uint32_t) interrupt_handler_157, + (uint32_t) interrupt_handler_158, + (uint32_t) interrupt_handler_159, + (uint32_t) interrupt_handler_160, + (uint32_t) interrupt_handler_161, + (uint32_t) interrupt_handler_162, + (uint32_t) interrupt_handler_163, + (uint32_t) interrupt_handler_164, + (uint32_t) interrupt_handler_165, + (uint32_t) interrupt_handler_166, + (uint32_t) interrupt_handler_167, + (uint32_t) interrupt_handler_168, + (uint32_t) interrupt_handler_169, + (uint32_t) interrupt_handler_170, + (uint32_t) interrupt_handler_171, + (uint32_t) interrupt_handler_172, + (uint32_t) interrupt_handler_173, + (uint32_t) interrupt_handler_174, + (uint32_t) interrupt_handler_175, + (uint32_t) interrupt_handler_176, + (uint32_t) interrupt_handler_177, + (uint32_t) interrupt_handler_178, + (uint32_t) interrupt_handler_179, + (uint32_t) interrupt_handler_180, + (uint32_t) interrupt_handler_181, + (uint32_t) interrupt_handler_182, + (uint32_t) interrupt_handler_183, + (uint32_t) interrupt_handler_184, + (uint32_t) interrupt_handler_185, + (uint32_t) interrupt_handler_186, + (uint32_t) interrupt_handler_187, + (uint32_t) interrupt_handler_188, + (uint32_t) interrupt_handler_189, + (uint32_t) interrupt_handler_190, + (uint32_t) interrupt_handler_191, + (uint32_t) interrupt_handler_192, + (uint32_t) interrupt_handler_193, + (uint32_t) interrupt_handler_194, + (uint32_t) interrupt_handler_195, + (uint32_t) interrupt_handler_196, + (uint32_t) interrupt_handler_197, + (uint32_t) interrupt_handler_198, + (uint32_t) interrupt_handler_199, + (uint32_t) interrupt_handler_200, + (uint32_t) interrupt_handler_201, + (uint32_t) interrupt_handler_202, + (uint32_t) interrupt_handler_203, + (uint32_t) interrupt_handler_204, + (uint32_t) interrupt_handler_205, + (uint32_t) interrupt_handler_206, + (uint32_t) interrupt_handler_207, + (uint32_t) interrupt_handler_208, + (uint32_t) interrupt_handler_209, + (uint32_t) interrupt_handler_210, + (uint32_t) interrupt_handler_211, + (uint32_t) interrupt_handler_212, + (uint32_t) interrupt_handler_213, + (uint32_t) interrupt_handler_214, + (uint32_t) interrupt_handler_215, + (uint32_t) interrupt_handler_216, + (uint32_t) interrupt_handler_217, + (uint32_t) interrupt_handler_218, + (uint32_t) interrupt_handler_219, + (uint32_t) interrupt_handler_220, + (uint32_t) interrupt_handler_221, + (uint32_t) interrupt_handler_222, + (uint32_t) interrupt_handler_223, + (uint32_t) interrupt_handler_224, + (uint32_t) interrupt_handler_225, + (uint32_t) interrupt_handler_226, + (uint32_t) interrupt_handler_227, + (uint32_t) interrupt_handler_228, + (uint32_t) interrupt_handler_229, + (uint32_t) interrupt_handler_230, + (uint32_t) interrupt_handler_231, + (uint32_t) interrupt_handler_232, + (uint32_t) interrupt_handler_233, + (uint32_t) interrupt_handler_234, + (uint32_t) interrupt_handler_235, + (uint32_t) interrupt_handler_236, + (uint32_t) interrupt_handler_237, + (uint32_t) interrupt_handler_238, + (uint32_t) interrupt_handler_239, + (uint32_t) interrupt_handler_240, + (uint32_t) interrupt_handler_241, + (uint32_t) interrupt_handler_242, + (uint32_t) interrupt_handler_243, + (uint32_t) interrupt_handler_244, + (uint32_t) interrupt_handler_245, + (uint32_t) interrupt_handler_246, + (uint32_t) interrupt_handler_247, + (uint32_t) interrupt_handler_248, + (uint32_t) interrupt_handler_249, + (uint32_t) interrupt_handler_250, + (uint32_t) interrupt_handler_251, + (uint32_t) interrupt_handler_252, + (uint32_t) interrupt_handler_253, + (uint32_t) interrupt_handler_254, + (uint32_t) interrupt_handler_255, +}; + void initialize_idt() { idt_description_structure.size = sizeof(idt) - 1; idt_description_structure.offset = (uint32_t) idt; - uint32_t interrupt_handler_address = (uint32_t) &interrupt_handler_49; - uint16_t offset_0_15 = interrupt_handler_address & 0x0000FFFF; - uint16_t offset_16_31 = interrupt_handler_address >> 16; uint16_t selector = KERNAL_CODE_SEGMENT_SELECTOR; uint8_t zero = 0x00; uint8_t type_attr = 0x8E; for (int i = 0; i < 256; i++) { + uint32_t interrupt_handler_address = interrupt_handler_addresses[i]; + uint16_t offset_0_15 = interrupt_handler_address & 0x0000FFFF; + uint16_t offset_16_31 = interrupt_handler_address >> 16; + idt[i].offset_0_15 = offset_0_15; idt[i].selector = selector; idt[i].zero = zero; diff --git a/stdio.c b/stdio.c index 3010e15..dda0644 100644 --- a/stdio.c +++ b/stdio.c @@ -77,7 +77,7 @@ void print_half_byte(write_byte_t write_byte, uint8_t half_byte) { } } -void print_int8(FILE stream, uint8_t data) { +void print_uint8(FILE stream, uint8_t data) { write_byte_t write_byte = write_byte_function(stream); uint8_t half_byte; diff --git a/stdio.h b/stdio.h index 313b99e..b94576f 100644 --- a/stdio.h +++ b/stdio.h @@ -8,7 +8,7 @@ typedef enum output_t {SCREEN, LOG} FILE; int fprintf (FILE stream, const char * format, ...); int log(char * format, ...); int printf (const char * format, ...); -void print_int8(FILE stream, uint8_t data); +void print_uint8(FILE stream, uint8_t data); void print_uint32(FILE stream, uint32_t data); #endif /* STDIO_H */ \ No newline at end of file From 36e1fa837f57260b97291631bb372593e29a4cf4 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 17 Sep 2016 16:17:29 -0700 Subject: [PATCH 11/67] Correctly acknowledge PIC so we can handle more than just the first interrupt. --- asm_interrupts.s | 6 ++---- drivers/keyboard.c | 8 +------- drivers/pic.c | 37 +++++++++++++++---------------------- drivers/pic.h | 8 ++------ interrupts.c | 11 ++++------- interrupts.h | 1 - kmain.c | 10 ++++++---- 7 files changed, 30 insertions(+), 51 deletions(-) diff --git a/asm_interrupts.s b/asm_interrupts.s index 573df5f..b8b91f5 100644 --- a/asm_interrupts.s +++ b/asm_interrupts.s @@ -58,7 +58,7 @@ global interrupt_handler_9 interrupt_handler_9: push dword 0 push dword 9 - jmp common_interrupt_handler + jmp common_interrupt_handler global interrupt_handler_10 interrupt_handler_10: @@ -1544,7 +1544,6 @@ common_interrupt_handler: ; the common parts of the generic interr push edx push esi push edi - push esp push ebp ; call the C function @@ -1552,7 +1551,6 @@ common_interrupt_handler: ; the common parts of the generic interr ; restore the registers pop ebp - pop esp pop edi pop esi pop edx @@ -1560,7 +1558,7 @@ common_interrupt_handler: ; the common parts of the generic interr pop ebx pop eax - ; restore the esp + ; pop error_code and interrupt_number off the stack add esp, 8 ; return to the code that got interrupted diff --git a/drivers/keyboard.c b/drivers/keyboard.c index eb95355..f670fcd 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -5,11 +5,6 @@ #define KBD_DATA_PORT 0x60 -/** read_scan_code: -* Reads a scan code from the keyboard -* -* @return The scan code (NOT an ASCII character!) -*/ uint8_t read_scan_code() { return inb(KBD_DATA_PORT); @@ -17,9 +12,8 @@ uint8_t read_scan_code() uint8_t consume_scan_code() { uint8_t scan_code = read_scan_code(); - log("consume_scan_code() consumed: "); + log("consume_scan_code() "); print_uint8(LOG, scan_code); log("\n"); - return scan_code; } \ No newline at end of file diff --git a/drivers/pic.c b/drivers/pic.c index f2c078e..d327d0c 100644 --- a/drivers/pic.c +++ b/drivers/pic.c @@ -1,30 +1,23 @@ #include "pic.h" #include "../assembly_interface.h" +#include "../stdio.h" -#define PIC1_PORT_A 0x20 -#define PIC2_PORT_A 0xA0 +#define PIC1 0x20 /* IO base address for master PIC */ +#define PIC2 0xA0 /* IO base address for slave PIC */ +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) -/* The PIC interrupts have been remapped */ -#define PIC1_START_INTERRUPT 0x20 -#define PIC2_START_INTERRUPT 0x28 -#define PIC2_END_INTERRUPT PIC2_START_INTERRUPT + 7 +#define PIC_EOI 0x20 /* End-of-interrupt command code */ -#define PIC_ACK 0x20 +void pic_init() { + outb(PIC1_DATA, 0b11111101); // Only enable keyboard (irc 1) + outb(PIC2_DATA, 0b11111111); // Don't enable any interrupts on slave pic (irc 8-15) + enable_hardware_interrupts(); +} -/** pic_acknowledge: - * Acknowledges an interrupt from either PIC 1 or PIC 2. - * - * @param num The number of the interrupt - */ -void pic_acknowledge(uint32_t interrupt) +void pic_acknowledge() { - if (interrupt < PIC1_START_INTERRUPT || interrupt > PIC2_END_INTERRUPT) { - return; - } - - if (interrupt < PIC2_START_INTERRUPT) { - outb(PIC1_PORT_A, PIC_ACK); - } else { - outb(PIC2_PORT_A, PIC_ACK); - } + outb(PIC1_COMMAND, PIC_EOI); } \ No newline at end of file diff --git a/drivers/pic.h b/drivers/pic.h index 1bb3757..4bcba10 100644 --- a/drivers/pic.h +++ b/drivers/pic.h @@ -3,11 +3,7 @@ #include "../types.h" -/** pic_acknowledge: - * Acknowledges an interrupt from either PIC 1 or PIC 2. - * - * @param num The number of the interrupt - */ -void pic_acknowledge(uint32_t interrupt); +void pic_acknowledge(); +void pic_init(); #endif /* INCLUDE_PIC_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index 73a930f..25f5395 100644 --- a/interrupts.c +++ b/interrupts.c @@ -5,11 +5,7 @@ #include "drivers/pic.h" #include "stdio.h" -void enable_keyboard_interrupts() { - outb(0x21,0xfd); - outb(0xa1,0xff); - enable_hardware_interrupts(); -} +#define INT_KEYBOARD 0x00000009 void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code) { log("interrupt_handler()\n"); @@ -25,9 +21,8 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t if (cpu.eax) {}; // Avoid unused parameter error switch(interrupt_number) { - case(0x00000009): + case(INT_KEYBOARD): consume_scan_code(); - pic_acknowledge(interrupt_number); break; default: @@ -36,4 +31,6 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t log("\n"); break; } + + pic_acknowledge(); } diff --git a/interrupts.h b/interrupts.h index c0e0309..b9e1892 100644 --- a/interrupts.h +++ b/interrupts.h @@ -10,7 +10,6 @@ struct cpu_state { uint32_t edx; uint32_t esi; uint32_t edi; - uint32_t esp; uint32_t ebp; } __attribute__((packed)); diff --git a/kmain.c b/kmain.c index 2ae69b7..d387a62 100644 --- a/kmain.c +++ b/kmain.c @@ -1,6 +1,7 @@ #include "asm_interrupts.h" #include "assembly_interface.h" #include "drivers/frame_buffer.h" +#include "drivers/pic.h" #include "drivers/serial_port.h" #include "interrupts.h" #include "stdio.h" @@ -400,11 +401,12 @@ void kmain() { log("Loaded interrupt descriptor table.\n"); interrupt(49); - log("Returned from interrupt()\n"); + log("Returned from test interrupt()\n"); - enable_keyboard_interrupts(); + pic_init(); + log("Initialized PIC\n"); // Loop forever - // TODO: accept user input - while(1) {}; + // User input is accepted asynchronously via interrupts + while(1){} } \ No newline at end of file From f78ee6a7e0699d8be8217bfbdb5677a7000adc5d Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 18 Sep 2016 15:48:53 -0700 Subject: [PATCH 12/67] Type on the screen --- drivers/keyboard.c | 9 --- drivers/keyboard.h | 2 +- interrupts.c | 150 ++++++++++++++++++++++++++++++++++++++++++++- kmain.c | 56 ++++++++--------- stdio.c | 5 ++ stdio.h | 1 + 6 files changed, 184 insertions(+), 39 deletions(-) diff --git a/drivers/keyboard.c b/drivers/keyboard.c index f670fcd..9a5f0d6 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -1,6 +1,5 @@ #include "keyboard.h" #include "../assembly_interface.h" -#include "../stdio.h" #include "../types.h" #define KBD_DATA_PORT 0x60 @@ -8,12 +7,4 @@ uint8_t read_scan_code() { return inb(KBD_DATA_PORT); -} - -uint8_t consume_scan_code() { - uint8_t scan_code = read_scan_code(); - log("consume_scan_code() "); - print_uint8(LOG, scan_code); - log("\n"); - return scan_code; } \ No newline at end of file diff --git a/drivers/keyboard.h b/drivers/keyboard.h index 8beec47..640dc80 100644 --- a/drivers/keyboard.h +++ b/drivers/keyboard.h @@ -3,6 +3,6 @@ #include "../types.h" -uint8_t consume_scan_code(); +uint8_t read_scan_code(); #endif /* INCLUDE_KEYBOARD_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index 25f5395..8785b56 100644 --- a/interrupts.c +++ b/interrupts.c @@ -7,6 +7,154 @@ #define INT_KEYBOARD 0x00000009 +char scan_code_table[128] = { + 0, // 0x00 + 0, // 0x01 + '1', // 0x02 + '2', // 0x03 + '3', // 0x04 + '4', // 0x05 + '5', // 0x06 + '6', // 0x07 + '7', // 0x08 + '8', // 0x09 + '9', // 0x0a + '0', // 0x0b + '-', // 0x0c + '=', // 0x0d + 0, // 0x0e + 0, // 0x0f + 'q', // 0x10 + 'w', // 0x11 + 'e', // 0x12 + 'r', // 0x13 + 't', // 0x14 + 'y', // 0x15 + 'u', // 0x16 + 'i', // 0x17 + 'o', // 0x18 + 'p', // 0x19 + '[', // 0x1a + ']', // 0x1b + '\n', // 0x1c + 0, // 0x1d + 'a', // 0x1e + 's', // 0x1f + 'd', // 0x20 + 'f', // 0x21 + 'g', // 0x22 + 'h', // 0x23 + 'j', // 0x24 + 'k', // 0x25 + 'l', // 0x26 + ':', // 0x27 + '"', // 0x28 + '`', // 0x29 + 0, // 0x2a + '\\', // 0x2b + 'z', // 0x2c + 'x', // 0x2d + 'c', // 0x2e + 'v', // 0x2f + 'b', // 0x30 + 'n', // 0x31 + 'm', // 0x32 + ',', // 0x33 + '.', // 0x34 + '/', // 0x35 + 0, // 0x36 + 0, // 0x37 + 0, // 0x38 + ' ', // 0x39 + 0, // 0x3a + 0, // 0x3b + 0, // 0x3c + 0, // 0x3d + 0, // 0x3e + 0, // 0x3f + 0, // 0x40 + 0, // 0x41 + 0, // 0x42 + 0, // 0x43 + 0, // 0x44 + 0, // 0x45 + 0, // 0x46 + 0, // 0x47 + 0, // 0x48 + 0, // 0x49 + 0, // 0x4a + 0, // 0x4b + 0, // 0x4c + 0, // 0x4d + 0, // 0x4e + 0, // 0x4f + 0, // 0x50 + 0, // 0x51 + 0, // 0x52 + 0, // 0x53 + 0, // 0x54 + 0, // 0x55 + 0, // 0x56 + 0, // 0x57 + 0, // 0x58 + 0, // 0x59 + 0, // 0x5a + 0, // 0x5b + 0, // 0x5c + 0, // 0x5d + 0, // 0x5e + 0, // 0x5f + 0, // 0x60 + 0, // 0x61 + 0, // 0x62 + 0, // 0x63 + 0, // 0x64 + 0, // 0x65 + 0, // 0x66 + 0, // 0x67 + 0, // 0x68 + 0, // 0x69 + 0, // 0x6a + 0, // 0x6b + 0, // 0x6c + 0, // 0x6d + 0, // 0x6e + 0, // 0x6f + 0, // 0x70 + 0, // 0x71 + 0, // 0x72 + 0, // 0x73 + 0, // 0x74 + 0, // 0x75 + 0, // 0x76 + 0, // 0x77 + 0, // 0x78 + 0, // 0x79 + 0, // 0x7a + 0, // 0x7b + 0, // 0x7c + 0, // 0x7d + 0, // 0x7e + 0, // 0x7f +}; + +void keyboard_handler() { + uint8_t scan_code = read_scan_code(); + // print_uint8(LOG,scan_code); + // log("\n"); + char c = 0; + if (scan_code < 128) { + // key down + c = scan_code_table[scan_code]; + } else { + // key up + } + if (c != 0) { + print_char(LOG, c); + print_char(SCREEN, c); + } +} + void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code) { log("interrupt_handler()\n"); @@ -22,7 +170,7 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t switch(interrupt_number) { case(INT_KEYBOARD): - consume_scan_code(); + keyboard_handler(); break; default: diff --git a/kmain.c b/kmain.c index d387a62..513d1d7 100644 --- a/kmain.c +++ b/kmain.c @@ -358,38 +358,38 @@ void initialize_idt() { load_idt(&idt_description_structure); } -static char *welcome_string = "" -" " -" " -" " -" " -" | | | | " -" ___ ___ | |_ __ _ ___ | | __ " -" / __| / __| | __| / _` | / __| | |/ / " -" | (__ \\__ \\ | |_ | (_| | | (__ | < " -" \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " -" " -" " -" ____ _____ " -" / __ \\ / ____| " -" | | | | | (___ " -" | | | | \\___ \\ " -" | |__| | ____) | " -" \\____/ |_____/ " -" " -" " -" " -" " -" " -" " -" " -" " -""; +// static char *welcome_string = "" +// " " +// " " +// " " +// " " +// " | | | | " +// " ___ ___ | |_ __ _ ___ | | __ " +// " / __| / __| | __| / _` | / __| | |/ / " +// " | (__ \\__ \\ | |_ | (_| | | (__ | < " +// " \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " +// " " +// " " +// " ____ _____ " +// " / __ \\ / ____| " +// " | | | | | (___ " +// " | | | | \\___ \\ " +// " | |__| | ____) | " +// " \\____/ |_____/ " +// " " +// " " +// " " +// " " +// " " +// " " +// " " +// " " +// ""; void kmain() { clear_screen(); - printf(welcome_string); + // printf(welcome_string); serial_init(); log("Initialized serial port.\n"); diff --git a/stdio.c b/stdio.c index dda0644..6416918 100644 --- a/stdio.c +++ b/stdio.c @@ -13,6 +13,11 @@ write_byte_t write_byte_function(FILE stream) { } } +void print_char(FILE stream, char c) { + write_byte_t write_byte = write_byte_function(stream); + write_byte(c); +} + int fprintf (FILE stream, const char * format, ...) { write_byte_t write_byte = write_byte_function(stream); diff --git a/stdio.h b/stdio.h index b94576f..4f061a5 100644 --- a/stdio.h +++ b/stdio.h @@ -10,5 +10,6 @@ int log(char * format, ...); int printf (const char * format, ...); void print_uint8(FILE stream, uint8_t data); void print_uint32(FILE stream, uint32_t data); +void print_char(FILE stream, char c); #endif /* STDIO_H */ \ No newline at end of file From 7059c7fe013cc7bfae52609fe9375d22275a792d Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 18 Sep 2016 16:38:40 -0700 Subject: [PATCH 13/67] Shift and backspace. --- drivers/frame_buffer.c | 7 + drivers/frame_buffer.h | 1 + drivers/keyboard.c | 308 ++++++++++++++++++++++++++++++++++++++++- drivers/keyboard.h | 1 + interrupts.c | 165 +--------------------- stdio.c | 12 ++ stdio.h | 1 + types.h | 11 +- 8 files changed, 345 insertions(+), 161 deletions(-) diff --git a/drivers/frame_buffer.c b/drivers/frame_buffer.c index 0d5dadf..0f61021 100644 --- a/drivers/frame_buffer.c +++ b/drivers/frame_buffer.c @@ -3,6 +3,7 @@ #include "frame_buffer.h" #include "../assembly_interface.h" +#include "../stdio.h" /* The I/O ports */ #define FB_COMMAND_PORT 0x3D4 @@ -63,3 +64,9 @@ void fb_write_byte(uint8_t b) { move_cursor_to_pos(cursor_pos); } } + +void fb_backspace() { + cursor_pos--; + fb_write_cell(cursor_pos, ' ', FB_WHITE, FB_BLACK); + move_cursor_to_pos(cursor_pos); +} diff --git a/drivers/frame_buffer.h b/drivers/frame_buffer.h index 307c8e3..1920dc2 100644 --- a/drivers/frame_buffer.h +++ b/drivers/frame_buffer.h @@ -25,6 +25,7 @@ #define FB_WHITE 15 void clear_screen(); +void fb_backspace(); void fb_write_byte(uint8_t b); #endif /* INCLUDE_FRAME_BUFFER_H */ \ No newline at end of file diff --git a/drivers/keyboard.c b/drivers/keyboard.c index 9a5f0d6..1fc2c35 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -1,10 +1,316 @@ #include "keyboard.h" + +#include "frame_buffer.h" #include "../assembly_interface.h" +#include "../stdio.h" #include "../types.h" #define KBD_DATA_PORT 0x60 +#define BACKSPACE 0x0E +#define LSHIFT 0x2A +#define RSHIFT 0x36 + +char normal_scan_code_table[128] = { + 0, // 0x00 + 0, // 0x01 + '1', // 0x02 + '2', // 0x03 + '3', // 0x04 + '4', // 0x05 + '5', // 0x06 + '6', // 0x07 + '7', // 0x08 + '8', // 0x09 + '9', // 0x0a + '0', // 0x0b + '-', // 0x0c + '=', // 0x0d + 0, // 0x0e + 0, // 0x0f + 'q', // 0x10 + 'w', // 0x11 + 'e', // 0x12 + 'r', // 0x13 + 't', // 0x14 + 'y', // 0x15 + 'u', // 0x16 + 'i', // 0x17 + 'o', // 0x18 + 'p', // 0x19 + '[', // 0x1a + ']', // 0x1b + '\n', // 0x1c + 0, // 0x1d + 'a', // 0x1e + 's', // 0x1f + 'd', // 0x20 + 'f', // 0x21 + 'g', // 0x22 + 'h', // 0x23 + 'j', // 0x24 + 'k', // 0x25 + 'l', // 0x26 + ';', // 0x27 + '\'', // 0x28 + '`', // 0x29 + 0, // 0x2a + '\\', // 0x2b + 'z', // 0x2c + 'x', // 0x2d + 'c', // 0x2e + 'v', // 0x2f + 'b', // 0x30 + 'n', // 0x31 + 'm', // 0x32 + ',', // 0x33 + '.', // 0x34 + '/', // 0x35 + 0, // 0x36 + 0, // 0x37 + 0, // 0x38 + ' ', // 0x39 + 0, // 0x3a + 0, // 0x3b + 0, // 0x3c + 0, // 0x3d + 0, // 0x3e + 0, // 0x3f + 0, // 0x40 + 0, // 0x41 + 0, // 0x42 + 0, // 0x43 + 0, // 0x44 + 0, // 0x45 + 0, // 0x46 + 0, // 0x47 + 0, // 0x48 + 0, // 0x49 + 0, // 0x4a + 0, // 0x4b + 0, // 0x4c + 0, // 0x4d + 0, // 0x4e + 0, // 0x4f + 0, // 0x50 + 0, // 0x51 + 0, // 0x52 + 0, // 0x53 + 0, // 0x54 + 0, // 0x55 + 0, // 0x56 + 0, // 0x57 + 0, // 0x58 + 0, // 0x59 + 0, // 0x5a + 0, // 0x5b + 0, // 0x5c + 0, // 0x5d + 0, // 0x5e + 0, // 0x5f + 0, // 0x60 + 0, // 0x61 + 0, // 0x62 + 0, // 0x63 + 0, // 0x64 + 0, // 0x65 + 0, // 0x66 + 0, // 0x67 + 0, // 0x68 + 0, // 0x69 + 0, // 0x6a + 0, // 0x6b + 0, // 0x6c + 0, // 0x6d + 0, // 0x6e + 0, // 0x6f + 0, // 0x70 + 0, // 0x71 + 0, // 0x72 + 0, // 0x73 + 0, // 0x74 + 0, // 0x75 + 0, // 0x76 + 0, // 0x77 + 0, // 0x78 + 0, // 0x79 + 0, // 0x7a + 0, // 0x7b + 0, // 0x7c + 0, // 0x7d + 0, // 0x7e + 0, // 0x7f +}; + +char shift_scan_code_table[128] = { + 0, // 0x00 + 0, // 0x01 + '!', // 0x02 + '@', // 0x03 + '#', // 0x04 + '$', // 0x05 + '%', // 0x06 + '^', // 0x07 + '&', // 0x08 + '*', // 0x09 + '(', // 0x0a + ')', // 0x0b + '_', // 0x0c + '+', // 0x0d + 0, // 0x0e + 0, // 0x0f + 'Q', // 0x10 + 'W', // 0x11 + 'E', // 0x12 + 'R', // 0x13 + 'T', // 0x14 + 'Y', // 0x15 + 'U', // 0x16 + 'I', // 0x17 + 'O', // 0x18 + 'P', // 0x19 + '{', // 0x1a + '}', // 0x1b + '\n', // 0x1c + 0, // 0x1d + 'A', // 0x1e + 'S', // 0x1f + 'D', // 0x20 + 'F', // 0x21 + 'G', // 0x22 + 'H', // 0x23 + 'J', // 0x24 + 'K', // 0x25 + 'L', // 0x26 + ':', // 0x27 + '"', // 0x28 + '~', // 0x29 + 0, // 0x2a + '|', // 0x2b + 'Z', // 0x2c + 'X', // 0x2d + 'C', // 0x2e + 'V', // 0x2f + 'B', // 0x30 + 'N', // 0x31 + 'M', // 0x32 + '<', // 0x33 + '>', // 0x34 + '?', // 0x35 + 0, // 0x36 + 0, // 0x37 + 0, // 0x38 + ' ', // 0x39 + 0, // 0x3a + 0, // 0x3b + 0, // 0x3c + 0, // 0x3d + 0, // 0x3e + 0, // 0x3f + 0, // 0x40 + 0, // 0x41 + 0, // 0x42 + 0, // 0x43 + 0, // 0x44 + 0, // 0x45 + 0, // 0x46 + 0, // 0x47 + 0, // 0x48 + 0, // 0x49 + 0, // 0x4a + 0, // 0x4b + 0, // 0x4c + 0, // 0x4d + 0, // 0x4e + 0, // 0x4f + 0, // 0x50 + 0, // 0x51 + 0, // 0x52 + 0, // 0x53 + 0, // 0x54 + 0, // 0x55 + 0, // 0x56 + 0, // 0x57 + 0, // 0x58 + 0, // 0x59 + 0, // 0x5a + 0, // 0x5b + 0, // 0x5c + 0, // 0x5d + 0, // 0x5e + 0, // 0x5f + 0, // 0x60 + 0, // 0x61 + 0, // 0x62 + 0, // 0x63 + 0, // 0x64 + 0, // 0x65 + 0, // 0x66 + 0, // 0x67 + 0, // 0x68 + 0, // 0x69 + 0, // 0x6a + 0, // 0x6b + 0, // 0x6c + 0, // 0x6d + 0, // 0x6e + 0, // 0x6f + 0, // 0x70 + 0, // 0x71 + 0, // 0x72 + 0, // 0x73 + 0, // 0x74 + 0, // 0x75 + 0, // 0x76 + 0, // 0x77 + 0, // 0x78 + 0, // 0x79 + 0, // 0x7a + 0, // 0x7b + 0, // 0x7c + 0, // 0x7d + 0, // 0x7e + 0, // 0x7f +}; + +bool key_pressed[128]; + +bool lshift_pressed; +bool rshift_pressed; +bool extended_scan_code; + uint8_t read_scan_code() { return inb(KBD_DATA_PORT); -} \ No newline at end of file +} + +void keyboard_interrupt_handler() { + uint8_t scan_code = read_scan_code(); + bool pressed = 1; + if (scan_code >= 128) { + pressed = false; + scan_code -= 128; + } + key_pressed[scan_code] = pressed; + + if (!pressed) { + return; + } + + if (scan_code == BACKSPACE) { + fb_backspace(); + return; + } + + char c; + if (key_pressed[LSHIFT] || key_pressed[RSHIFT]) { + c = shift_scan_code_table[scan_code]; + } else { + c = normal_scan_code_table[scan_code]; + } + + if (c != 0) { + print_char(LOG, c); + print_char(SCREEN, c); + } +} diff --git a/drivers/keyboard.h b/drivers/keyboard.h index 640dc80..a8974b4 100644 --- a/drivers/keyboard.h +++ b/drivers/keyboard.h @@ -3,6 +3,7 @@ #include "../types.h" +void keyboard_interrupt_handler(); uint8_t read_scan_code(); #endif /* INCLUDE_KEYBOARD_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index 8785b56..3f05520 100644 --- a/interrupts.c +++ b/interrupts.c @@ -7,170 +7,17 @@ #define INT_KEYBOARD 0x00000009 -char scan_code_table[128] = { - 0, // 0x00 - 0, // 0x01 - '1', // 0x02 - '2', // 0x03 - '3', // 0x04 - '4', // 0x05 - '5', // 0x06 - '6', // 0x07 - '7', // 0x08 - '8', // 0x09 - '9', // 0x0a - '0', // 0x0b - '-', // 0x0c - '=', // 0x0d - 0, // 0x0e - 0, // 0x0f - 'q', // 0x10 - 'w', // 0x11 - 'e', // 0x12 - 'r', // 0x13 - 't', // 0x14 - 'y', // 0x15 - 'u', // 0x16 - 'i', // 0x17 - 'o', // 0x18 - 'p', // 0x19 - '[', // 0x1a - ']', // 0x1b - '\n', // 0x1c - 0, // 0x1d - 'a', // 0x1e - 's', // 0x1f - 'd', // 0x20 - 'f', // 0x21 - 'g', // 0x22 - 'h', // 0x23 - 'j', // 0x24 - 'k', // 0x25 - 'l', // 0x26 - ':', // 0x27 - '"', // 0x28 - '`', // 0x29 - 0, // 0x2a - '\\', // 0x2b - 'z', // 0x2c - 'x', // 0x2d - 'c', // 0x2e - 'v', // 0x2f - 'b', // 0x30 - 'n', // 0x31 - 'm', // 0x32 - ',', // 0x33 - '.', // 0x34 - '/', // 0x35 - 0, // 0x36 - 0, // 0x37 - 0, // 0x38 - ' ', // 0x39 - 0, // 0x3a - 0, // 0x3b - 0, // 0x3c - 0, // 0x3d - 0, // 0x3e - 0, // 0x3f - 0, // 0x40 - 0, // 0x41 - 0, // 0x42 - 0, // 0x43 - 0, // 0x44 - 0, // 0x45 - 0, // 0x46 - 0, // 0x47 - 0, // 0x48 - 0, // 0x49 - 0, // 0x4a - 0, // 0x4b - 0, // 0x4c - 0, // 0x4d - 0, // 0x4e - 0, // 0x4f - 0, // 0x50 - 0, // 0x51 - 0, // 0x52 - 0, // 0x53 - 0, // 0x54 - 0, // 0x55 - 0, // 0x56 - 0, // 0x57 - 0, // 0x58 - 0, // 0x59 - 0, // 0x5a - 0, // 0x5b - 0, // 0x5c - 0, // 0x5d - 0, // 0x5e - 0, // 0x5f - 0, // 0x60 - 0, // 0x61 - 0, // 0x62 - 0, // 0x63 - 0, // 0x64 - 0, // 0x65 - 0, // 0x66 - 0, // 0x67 - 0, // 0x68 - 0, // 0x69 - 0, // 0x6a - 0, // 0x6b - 0, // 0x6c - 0, // 0x6d - 0, // 0x6e - 0, // 0x6f - 0, // 0x70 - 0, // 0x71 - 0, // 0x72 - 0, // 0x73 - 0, // 0x74 - 0, // 0x75 - 0, // 0x76 - 0, // 0x77 - 0, // 0x78 - 0, // 0x79 - 0, // 0x7a - 0, // 0x7b - 0, // 0x7c - 0, // 0x7d - 0, // 0x7e - 0, // 0x7f -}; - -void keyboard_handler() { - uint8_t scan_code = read_scan_code(); - // print_uint8(LOG,scan_code); - // log("\n"); - char c = 0; - if (scan_code < 128) { - // key down - c = scan_code_table[scan_code]; - } else { - // key up - } - if (c != 0) { - print_char(LOG, c); - print_char(SCREEN, c); - } -} - void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code) { - log("interrupt_handler()\n"); - - log("error_code: "); - print_uint32(LOG, error_code); - log("\n"); - - log("interrupt_number: "); - print_uint32(LOG, interrupt_number); - log("\n"); - if (cpu.eax) {}; // Avoid unused parameter error + if (error_code) { + log("interrupt_handler() error_code "); + print_uint32(LOG, error_code); + log("\n"); + } switch(interrupt_number) { case(INT_KEYBOARD): - keyboard_handler(); + keyboard_interrupt_handler(); break; default: diff --git a/stdio.c b/stdio.c index 6416918..fe734ef 100644 --- a/stdio.c +++ b/stdio.c @@ -94,6 +94,18 @@ void print_uint8(FILE stream, uint8_t data) { } } +void print_uint16(FILE stream, uint16_t data) { + write_byte_t write_byte = write_byte_function(stream); + + uint8_t half_byte; + write_byte('0'); + write_byte('x'); + for (int i = 3; i >=0; i--) { + half_byte = (data >> (4*i)) & 0x0F; + print_half_byte(write_byte, half_byte); + } +} + void print_uint32(FILE stream, uint32_t data) { write_byte_t write_byte = write_byte_function(stream); diff --git a/stdio.h b/stdio.h index 4f061a5..b5aed8b 100644 --- a/stdio.h +++ b/stdio.h @@ -9,6 +9,7 @@ int fprintf (FILE stream, const char * format, ...); int log(char * format, ...); int printf (const char * format, ...); void print_uint8(FILE stream, uint8_t data); +void print_uint16(FILE stream, uint16_t data); void print_uint32(FILE stream, uint32_t data); void print_char(FILE stream, char c); diff --git a/types.h b/types.h index 9b2309d..e226ea5 100644 --- a/types.h +++ b/types.h @@ -1,3 +1,6 @@ +#ifndef INCLUDE_TYPES_H +#define INCLUDE_TYPES_H + typedef unsigned char int8; typedef int8 byte; typedef unsigned short int16; @@ -8,4 +11,10 @@ typedef unsigned long long int64; typedef unsigned char uint8_t; typedef unsigned short uint16_t; -typedef unsigned long uint32_t; \ No newline at end of file +typedef unsigned long uint32_t; + +#define bool char +#define true 1 +#define false 0 + +#endif /* INCLUDE_TYPES_H */ \ No newline at end of file From b192c01c075d9307a8ab6eb7fafcbfb462975e60 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 1 Oct 2016 11:07:45 -0700 Subject: [PATCH 14/67] Fix bug where blue cells appeared on the screen. --- assembly_interface.s | 1 + kmain.c | 56 ++++++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/assembly_interface.s b/assembly_interface.s index b4a7434..fd8dce3 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -52,3 +52,4 @@ global enable_hardware_interrupts ; enable_hardware_interrupts enable_hardware_interrupts: sti + ret diff --git a/kmain.c b/kmain.c index 513d1d7..d387a62 100644 --- a/kmain.c +++ b/kmain.c @@ -358,38 +358,38 @@ void initialize_idt() { load_idt(&idt_description_structure); } -// static char *welcome_string = "" -// " " -// " " -// " " -// " " -// " | | | | " -// " ___ ___ | |_ __ _ ___ | | __ " -// " / __| / __| | __| / _` | / __| | |/ / " -// " | (__ \\__ \\ | |_ | (_| | | (__ | < " -// " \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " -// " " -// " " -// " ____ _____ " -// " / __ \\ / ____| " -// " | | | | | (___ " -// " | | | | \\___ \\ " -// " | |__| | ____) | " -// " \\____/ |_____/ " -// " " -// " " -// " " -// " " -// " " -// " " -// " " -// " " -// ""; +static char *welcome_string = "" +" " +" " +" " +" " +" | | | | " +" ___ ___ | |_ __ _ ___ | | __ " +" / __| / __| | __| / _` | / __| | |/ / " +" | (__ \\__ \\ | |_ | (_| | | (__ | < " +" \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " +" " +" " +" ____ _____ " +" / __ \\ / ____| " +" | | | | | (___ " +" | | | | \\___ \\ " +" | |__| | ____) | " +" \\____/ |_____/ " +" " +" " +" " +" " +" " +" " +" " +" " +""; void kmain() { clear_screen(); - // printf(welcome_string); + printf(welcome_string); serial_init(); log("Initialized serial port.\n"); From 1738a49de549df797ae2ba556ef27e655732bb2c Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 1 Oct 2016 11:10:13 -0700 Subject: [PATCH 15/67] Fix typos. --- Makefile | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index e3adb03..c72fb2d 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ NASM=nasm # https://en.wikipedia.org/wiki/GNU_linker -LD=~/.local/binutils/bin/i386-unkown-linux-gnu-ld +LD=~/.local/binutils/bin/i386-unknown-linux-gnu-ld # https://en.wikipedia.org/wiki/QEMU # Virtual machine diff --git a/README.md b/README.md index 6cf39ae..95adcc3 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ Following the tutorial: https://littleosbook.github.io # Setup ## OSX ``` -$ brew install nasm # virtual machine -$ brew install qemu # assembler +$ brew install nasm # assembler +$ brew install qemu # virtual machine $ brew install cdrtools # includes a utility for making disk images ``` From 5fa14bc9eab02dd582745cb926af2b6353d2e6ce Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 1 Oct 2016 13:52:32 -0700 Subject: [PATCH 16/67] Include a program in the iso and call it from kmain. --- .gitignore | 1 + Makefile | 13 +++-- kmain.c | 12 ++++- loader.s | 20 +++++--- menu.lst | 3 +- multiboot.h | 121 ++++++++++++++++++++++++++++++++++++++++++++++ multiboot_utils.c | 61 +++++++++++++++++++++++ multiboot_utils.h | 11 +++++ program.s | 8 +++ stdio.c | 10 ++++ stdio.h | 1 + types.h | 2 + 12 files changed, 252 insertions(+), 11 deletions(-) create mode 100644 multiboot.h create mode 100644 multiboot_utils.c create mode 100644 multiboot_utils.h create mode 100644 program.s diff --git a/.gitignore b/.gitignore index 738c016..0055e21 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.out iso/ *.elf +*.bin *.o *.iso stage2_eltorito diff --git a/Makefile b/Makefile index c72fb2d..fe26f12 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ drivers/pic.o \ drivers/serial_port.o \ interrupts.o \ kmain.o \ +multiboot_utils.o \ stdio.o all: os.iso @@ -42,11 +43,16 @@ all: os.iso kernel.elf: $(OBJECTS) $(LD) -T link.ld -melf_i386 $(OBJECTS) -o kernel.elf # Link to make an executable for the kernel. -os.iso: kernel.elf +program.bin: program.s + $(NASM) -f bin $< -o $@ # `-f bin` creates a flat binary + +os.iso: kernel.elf program.bin menu.lst mkdir -p iso/boot/grub # create the folder structure + mkdir -p iso/modules cp stage2_eltorito iso/boot/grub/ # copy the bootloader cp kernel.elf iso/boot/ # copy the kernel - cp menu.lst iso/boot/grub # copy the configuration file + cp program.bin iso/modules # copy the 'user' program + cp menu.lst iso/boot/grub # copy the grub configuration file mkisofs -R \ -b boot/grub/stage2_eltorito \ -no-emul-boot \ @@ -65,6 +71,7 @@ run: os.iso clean: rm -f *.iso rm -f $(OBJECTS) - rm -f *.elf + rm -f *.elf # elf executables + rm -f *.bin # flat binary executables rm -f *.out rm -rf iso/ diff --git a/kmain.c b/kmain.c index d387a62..9806e72 100644 --- a/kmain.c +++ b/kmain.c @@ -4,6 +4,7 @@ #include "drivers/pic.h" #include "drivers/serial_port.h" #include "interrupts.h" +#include "multiboot_utils.h" #include "stdio.h" #include "types.h" @@ -386,7 +387,10 @@ static char *welcome_string = "" " " ""; -void kmain() { +void kmain(uint32_t ebx) { + // GRUB passes info to the kernel through the ebx register + multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; + clear_screen(); printf(welcome_string); @@ -394,6 +398,12 @@ void kmain() { serial_init(); log("Initialized serial port.\n"); + print_multiboot_info(LOG, mbinfo); + + void_function_t start_program = first_module_as_a_function(mbinfo); + start_program(); + log("Got past call to start_program()\n"); + initialize_gdt(); log("Loaded global descriptor table.\n"); diff --git a/loader.s b/loader.s index 50534c0..43f2e65 100644 --- a/loader.s +++ b/loader.s @@ -14,10 +14,15 @@ MAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant ; whereever 'MAGIC_NUMBER' shows up, in the code, ; it will be replaced with 0x1BADB002 -FLAGS equ 0x0 ; multiboot flags +ALIGN_MODULES equ 0x00000001 ; tell GRUB to align modules on page boundaries. + ; We use modules to load a 'user' program into + ; memory -CHECKSUM equ -MAGIC_NUMBER ; calculate the checksum - ; (magic number + checksum + flags should equal 0) +FLAGS equ ALIGN_MODULES ; multiboot flags passed to GRUB + +; calculate the checksum +; (magic number + checksum + flags should equal 0) +CHECKSUM equ -(MAGIC_NUMBER + FLAGS) KERNEL_STACK_SIZE equ 4096 ; size of stack in bytes (1 kilobyte) @@ -40,12 +45,15 @@ loader: ; the loader label (defined as entry point in li ; that means the address of this instruction will ; appear in the symbol table - mov eax, 0xCAFEBABE ; place the number 0xCAFEBABE in the register eax - mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the ; stack (end of memory area) - jmp kmain + push ebx ; GRUB stores a pointer to a struct in the register ebx that, + ; among other things, describes at which addresses the modules are loaded. + ; Push ebx on the stack before calling kmain to make it an argument for kmain. + + call kmain ; use call rather than jmp so C function finds paramters in the correct place + hlt ; should never get here. kmain should not return. section .bss ; Use the 'bss' section for the stack align 4 ; align at 4 bytes for performance reasons diff --git a/menu.lst b/menu.lst index 93bfce3..2ba530e 100644 --- a/menu.lst +++ b/menu.lst @@ -2,4 +2,5 @@ default=0 timeout=0 title os -kernel /boot/kernel.elf \ No newline at end of file +kernel /boot/kernel.elf +module /modules/program.bin \ No newline at end of file diff --git a/multiboot.h b/multiboot.h new file mode 100644 index 0000000..8ec8a24 --- /dev/null +++ b/multiboot.h @@ -0,0 +1,121 @@ +// The following was copied from https://www.gnu.org/software/grub/manual/multiboot/html_node/multiboot.h.html + +/* multiboot.h - the header for Multiboot */ +/* Copyright (C) 1999, 2001 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Macros. */ + +/* The magic number for the Multiboot header. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* The flags for the Multiboot header. */ +#ifdef __ELF__ +# define MULTIBOOT_HEADER_FLAGS 0x00000003 +#else +# define MULTIBOOT_HEADER_FLAGS 0x00010003 +#endif + +/* The magic number passed by a Multiboot-compliant boot loader. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The size of our stack (16KB). */ +#define STACK_SIZE 0x4000 + +/* C symbol format. HAVE_ASM_USCORE is defined by configure. */ +#ifdef HAVE_ASM_USCORE +# define EXT_C(sym) _ ## sym +#else +# define EXT_C(sym) sym +#endif + +#ifndef ASM +/* Do not include here in boot.S. */ + +/* Types. */ + +/* The Multiboot header. */ +typedef struct multiboot_header +{ + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +} multiboot_header_t; + +/* The symbol table for a.out. */ +typedef struct aout_symbol_table +{ + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long reserved; +} aout_symbol_table_t; + +/* The section header table for ELF. */ +typedef struct elf_section_header_table +{ + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; +} elf_section_header_table_t; + +/* The Multiboot information. */ +typedef struct multiboot_info +{ + unsigned long flags; + unsigned long mem_lower; + unsigned long mem_upper; + unsigned long boot_device; + unsigned long cmdline; + unsigned long mods_count; + unsigned long mods_addr; + union + { + aout_symbol_table_t aout_sym; + elf_section_header_table_t elf_sec; + } u; + unsigned long mmap_length; + unsigned long mmap_addr; +} multiboot_info_t; + +/* The module structure. */ +typedef struct module +{ + unsigned long mod_start; + unsigned long mod_end; + unsigned long string; + unsigned long reserved; +} module_t; + +/* The memory map. Be careful that the offset 0 is base_addr_low + but no size. */ +typedef struct memory_map +{ + unsigned long size; + unsigned long base_addr_low; + unsigned long base_addr_high; + unsigned long length_low; + unsigned long length_high; + unsigned long type; +} memory_map_t; + +#endif /* ! ASM */ \ No newline at end of file diff --git a/multiboot_utils.c b/multiboot_utils.c new file mode 100644 index 0000000..f925187 --- /dev/null +++ b/multiboot_utils.c @@ -0,0 +1,61 @@ +#include "multiboot_utils.h" + +void print_module_info(FILE stream, struct module * m) { + fprintf(stream, "mod_start: "); + print_uint32(stream, m->mod_start); + fprintf(stream, "\n"); + fprintf(stream, "mod_end: "); + print_uint32(stream, m->mod_end); + fprintf(stream, "\n"); + fprintf(stream, "string: "); + fprintf(stream, (char*) m->string); + fprintf(stream, "\n"); +} + +void print_multiboot_info(FILE stream, multiboot_info_t* info) { + fprintf(stream, "flags: "); + print_uint32(stream, info->flags); + fprintf(stream, "\n"); + + fprintf(stream, "mem_lower: "); + print_uint32(stream, info->mem_lower); + fprintf(stream, "\n"); + fprintf(stream, "mem_upper: "); + print_uint32(stream, info->mem_upper); + fprintf(stream, "\n"); + + fprintf(stream, "boot_device: "); + print_uint32(stream, info->boot_device); + fprintf(stream, "\n"); + fprintf(stream, "cmdline: "); + print_uint32(stream, info->cmdline); + fprintf(stream, "\n"); + + fprintf(stream, "mods_count: "); + print_uint32(stream, info->mods_count); + fprintf(stream, "\n"); + fprintf(stream, "mods_addr: "); + print_uint32(stream, info->mods_addr); + fprintf(stream, "\n"); + + struct module * modules; + if (info->mods_count > 0) { + fprintf(stream, "\nmodules:\n"); + modules = (struct module *) info->mods_addr; + for (uint8_t i = 0; i < info->mods_count; i++) { + fprintf(stream, "module #"); + print_uint8(stream, i); + fprintf(stream, ":\n"); + print_module_info(stream, &(modules[i])); + } + } +} + +void_function_t first_module_as_a_function(multiboot_info_t* info) { + if (info->mods_count == 0) { + return 0; + } + + struct module * module_info = (struct module *) info->mods_addr; + return (void_function_t) module_info->mod_start; +} diff --git a/multiboot_utils.h b/multiboot_utils.h new file mode 100644 index 0000000..6895892 --- /dev/null +++ b/multiboot_utils.h @@ -0,0 +1,11 @@ +#ifndef MULTIBOOT_UTILS_H +#define MULTIBOOT_UTILS_H + +#include "multiboot.h" +#include "stdio.h" +#include "types.h" + +void print_multiboot_info(FILE stream, multiboot_info_t* info); +void_function_t first_module_as_a_function(multiboot_info_t* info); + +#endif diff --git a/program.s b/program.s new file mode 100644 index 0000000..d142bf8 --- /dev/null +++ b/program.s @@ -0,0 +1,8 @@ +BITS 32 ; In a flat binary program, nasm assumes the code will run in 16-bit mode. + ; More advanced executable formats like ELF specify this automatically. + +mov eax, 0xDEADBEEF ; Write a recognizable value to a register just so we know + ; that this program ran. + +jmp $ ; Enter infinite loop, nothing more to do. + ; `$` means "beginning of line", ie. the same instruction. \ No newline at end of file diff --git a/stdio.c b/stdio.c index fe734ef..2aa19e0 100644 --- a/stdio.c +++ b/stdio.c @@ -18,6 +18,16 @@ void print_char(FILE stream, char c) { write_byte(c); } +void print_bytes(FILE stream, uint8_t * bytes, uint32_t num_bytes) { + write_byte_t write_byte = write_byte_function(stream); + if (num_bytes == 0) { return; } + print_uint8(stream, bytes[0]); + for (uint32_t i=1; i < num_bytes; i++) { + write_byte(' '); + print_uint8(stream, bytes[i]); + } +} + int fprintf (FILE stream, const char * format, ...) { write_byte_t write_byte = write_byte_function(stream); diff --git a/stdio.h b/stdio.h index b5aed8b..20fb71a 100644 --- a/stdio.h +++ b/stdio.h @@ -12,5 +12,6 @@ void print_uint8(FILE stream, uint8_t data); void print_uint16(FILE stream, uint16_t data); void print_uint32(FILE stream, uint32_t data); void print_char(FILE stream, char c); +void print_bytes(FILE stream, uint8_t * bytes, uint32_t num_bytes); #endif /* STDIO_H */ \ No newline at end of file diff --git a/types.h b/types.h index e226ea5..4b96d9e 100644 --- a/types.h +++ b/types.h @@ -13,6 +13,8 @@ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; +typedef void (*void_function_t)(void); + #define bool char #define true 1 #define false 0 From 35eb19346770f89b5338becce4984901820e83ca Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 1 Oct 2016 18:28:52 -0700 Subject: [PATCH 17/67] Move idt and gdt code into data_structures directory. --- Makefile | 2 + data_structures/global_descriptor_table.c | 55 +++ data_structures/global_descriptor_table.h | 12 + data_structures/interrupt_descriptor_table.c | 306 +++++++++++++++ data_structures/interrupt_descriptor_table.h | 6 + kmain.c | 371 +------------------ multiboot_utils.c | 10 +- 7 files changed, 395 insertions(+), 367 deletions(-) create mode 100644 data_structures/global_descriptor_table.c create mode 100644 data_structures/global_descriptor_table.h create mode 100644 data_structures/interrupt_descriptor_table.c create mode 100644 data_structures/interrupt_descriptor_table.h diff --git a/Makefile b/Makefile index fe26f12..95af2ee 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,8 @@ ASFLAGS = -f elf OBJECTS = loader.o \ asm_interrupts.o \ assembly_interface.o \ +data_structures/global_descriptor_table.o \ +data_structures/interrupt_descriptor_table.o \ drivers/frame_buffer.o \ drivers/keyboard.o \ drivers/pic.o \ diff --git a/data_structures/global_descriptor_table.c b/data_structures/global_descriptor_table.c new file mode 100644 index 0000000..f9222c3 --- /dev/null +++ b/data_structures/global_descriptor_table.c @@ -0,0 +1,55 @@ +#include "global_descriptor_table.h" + +#include "../assembly_interface.h" + +struct segment_descriptor_t { + uint16_t limit_0_15; // bits o-15 of limit + uint16_t base_0_15; + uint8_t base_16_23; + uint8_t access_byte; + uint8_t flags_and_limit_16_19; + uint8_t base_24_31; +} __attribute__((packed)); + +const uint16_t NULL_SEGMENT_SELECTOR = 0x0; +const uint16_t KERNAL_CODE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 1; +const uint16_t KERNAL_DATA_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 2; + +struct segment_descriptor_t gdt[3]; + +enum segment_selector_t { + NULL_DESCRIPTOR, // Not used but has to be here + KERNAL_CODE_SEGMENT_INDEX, // Offset 0x8 + KERNAL_DATA_SEGMENT_INDEX // Offset 0x10 +}; + +// a pointer to the global descriptor table +// passed by reference to the LGDT instruction +struct gdt_description_structure_t { + uint16_t size; // in bytes + uint32_t offset; +} __attribute__((packed)) gdt_description_structure; + +void initialize_gdt() { + gdt_description_structure.size = sizeof(gdt) - 1; + gdt_description_structure.offset = (uint32_t) gdt; + + gdt[KERNAL_CODE_SEGMENT_INDEX].limit_0_15 = 0xFFFF; + gdt[KERNAL_CODE_SEGMENT_INDEX].base_0_15 = 0x0000; + gdt[KERNAL_CODE_SEGMENT_INDEX].base_16_23 = 0x00; + gdt[KERNAL_CODE_SEGMENT_INDEX].access_byte = 0b10011010; + gdt[KERNAL_CODE_SEGMENT_INDEX].flags_and_limit_16_19 = 0xCF; + gdt[KERNAL_CODE_SEGMENT_INDEX].base_24_31 = 0x00; + + gdt[KERNAL_DATA_SEGMENT_INDEX].limit_0_15 = 0xFFFF; + gdt[KERNAL_DATA_SEGMENT_INDEX].base_0_15 = 0x0000; + gdt[KERNAL_DATA_SEGMENT_INDEX].base_16_23 = 0x00; + gdt[KERNAL_DATA_SEGMENT_INDEX].access_byte = 0b10010010; + gdt[KERNAL_DATA_SEGMENT_INDEX].flags_and_limit_16_19 = 0xCF; + gdt[KERNAL_DATA_SEGMENT_INDEX].base_24_31 = 0x00; + + lgdt(&gdt_description_structure); + + // Grub has already loaded the segment registers + // with the correct values (0x8 for cs, 0x10 for the others) +} \ No newline at end of file diff --git a/data_structures/global_descriptor_table.h b/data_structures/global_descriptor_table.h new file mode 100644 index 0000000..f0c7025 --- /dev/null +++ b/data_structures/global_descriptor_table.h @@ -0,0 +1,12 @@ +#ifndef INCLUDE_GLOBAL_DESCRIPTOR_TABLE_H +#define INCLUDE_GLOBAL_DESCRIPTOR_TABLE_H + +#include "../types.h" + +const uint16_t NULL_SEGMENT_SELECTOR; +const uint16_t KERNAL_CODE_SEGMENT_SELECTOR; +const uint16_t KERNAL_DATA_SEGMENT_SELECTOR; + +void initialize_gdt(); + +#endif /* INCLUDE_GLOBAL_DESCRIPTOR_TABLE_H */ \ No newline at end of file diff --git a/data_structures/interrupt_descriptor_table.c b/data_structures/interrupt_descriptor_table.c new file mode 100644 index 0000000..3a6b925 --- /dev/null +++ b/data_structures/interrupt_descriptor_table.c @@ -0,0 +1,306 @@ +#include "interrupt_descriptor_table.h" + +#include "../asm_interrupts.h" +#include "../assembly_interface.h" +#include "../types.h" +#include "global_descriptor_table.h" + +// a pointer to the interrupt descriptor table +// passed by reference to the LIDT instruction +struct idt_description_structure_t { + uint16_t size; // in bytes + uint32_t offset; +} __attribute__((packed)) idt_description_structure; + +// See http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure_IA-32 +struct interrupt_descriptor_t { + uint16_t offset_0_15; + uint16_t selector; + uint8_t zero; + uint8_t type_attr; + uint16_t offset_16_31; +} __attribute__((packed)); + +struct interrupt_descriptor_t idt[256]; + +uint32_t interrupt_handler_addresses[] = { + (uint32_t) interrupt_handler_0, + (uint32_t) interrupt_handler_1, + (uint32_t) interrupt_handler_2, + (uint32_t) interrupt_handler_3, + (uint32_t) interrupt_handler_4, + (uint32_t) interrupt_handler_5, + (uint32_t) interrupt_handler_6, + (uint32_t) interrupt_handler_7, + (uint32_t) interrupt_handler_8, + (uint32_t) interrupt_handler_9, + (uint32_t) interrupt_handler_10, + (uint32_t) interrupt_handler_11, + (uint32_t) interrupt_handler_12, + (uint32_t) interrupt_handler_13, + (uint32_t) interrupt_handler_14, + (uint32_t) interrupt_handler_15, + (uint32_t) interrupt_handler_16, + (uint32_t) interrupt_handler_17, + (uint32_t) interrupt_handler_18, + (uint32_t) interrupt_handler_19, + (uint32_t) interrupt_handler_20, + (uint32_t) interrupt_handler_21, + (uint32_t) interrupt_handler_22, + (uint32_t) interrupt_handler_23, + (uint32_t) interrupt_handler_24, + (uint32_t) interrupt_handler_25, + (uint32_t) interrupt_handler_26, + (uint32_t) interrupt_handler_27, + (uint32_t) interrupt_handler_28, + (uint32_t) interrupt_handler_29, + (uint32_t) interrupt_handler_30, + (uint32_t) interrupt_handler_31, + (uint32_t) interrupt_handler_32, + (uint32_t) interrupt_handler_33, + (uint32_t) interrupt_handler_34, + (uint32_t) interrupt_handler_35, + (uint32_t) interrupt_handler_36, + (uint32_t) interrupt_handler_37, + (uint32_t) interrupt_handler_38, + (uint32_t) interrupt_handler_39, + (uint32_t) interrupt_handler_40, + (uint32_t) interrupt_handler_41, + (uint32_t) interrupt_handler_42, + (uint32_t) interrupt_handler_43, + (uint32_t) interrupt_handler_44, + (uint32_t) interrupt_handler_45, + (uint32_t) interrupt_handler_46, + (uint32_t) interrupt_handler_47, + (uint32_t) interrupt_handler_48, + (uint32_t) interrupt_handler_49, + (uint32_t) interrupt_handler_50, + (uint32_t) interrupt_handler_51, + (uint32_t) interrupt_handler_52, + (uint32_t) interrupt_handler_53, + (uint32_t) interrupt_handler_54, + (uint32_t) interrupt_handler_55, + (uint32_t) interrupt_handler_56, + (uint32_t) interrupt_handler_57, + (uint32_t) interrupt_handler_58, + (uint32_t) interrupt_handler_59, + (uint32_t) interrupt_handler_60, + (uint32_t) interrupt_handler_61, + (uint32_t) interrupt_handler_62, + (uint32_t) interrupt_handler_63, + (uint32_t) interrupt_handler_64, + (uint32_t) interrupt_handler_65, + (uint32_t) interrupt_handler_66, + (uint32_t) interrupt_handler_67, + (uint32_t) interrupt_handler_68, + (uint32_t) interrupt_handler_69, + (uint32_t) interrupt_handler_70, + (uint32_t) interrupt_handler_71, + (uint32_t) interrupt_handler_72, + (uint32_t) interrupt_handler_73, + (uint32_t) interrupt_handler_74, + (uint32_t) interrupt_handler_75, + (uint32_t) interrupt_handler_76, + (uint32_t) interrupt_handler_77, + (uint32_t) interrupt_handler_78, + (uint32_t) interrupt_handler_79, + (uint32_t) interrupt_handler_80, + (uint32_t) interrupt_handler_81, + (uint32_t) interrupt_handler_82, + (uint32_t) interrupt_handler_83, + (uint32_t) interrupt_handler_84, + (uint32_t) interrupt_handler_85, + (uint32_t) interrupt_handler_86, + (uint32_t) interrupt_handler_87, + (uint32_t) interrupt_handler_88, + (uint32_t) interrupt_handler_89, + (uint32_t) interrupt_handler_90, + (uint32_t) interrupt_handler_91, + (uint32_t) interrupt_handler_92, + (uint32_t) interrupt_handler_93, + (uint32_t) interrupt_handler_94, + (uint32_t) interrupt_handler_95, + (uint32_t) interrupt_handler_96, + (uint32_t) interrupt_handler_97, + (uint32_t) interrupt_handler_98, + (uint32_t) interrupt_handler_99, + (uint32_t) interrupt_handler_100, + (uint32_t) interrupt_handler_101, + (uint32_t) interrupt_handler_102, + (uint32_t) interrupt_handler_103, + (uint32_t) interrupt_handler_104, + (uint32_t) interrupt_handler_105, + (uint32_t) interrupt_handler_106, + (uint32_t) interrupt_handler_107, + (uint32_t) interrupt_handler_108, + (uint32_t) interrupt_handler_109, + (uint32_t) interrupt_handler_110, + (uint32_t) interrupt_handler_111, + (uint32_t) interrupt_handler_112, + (uint32_t) interrupt_handler_113, + (uint32_t) interrupt_handler_114, + (uint32_t) interrupt_handler_115, + (uint32_t) interrupt_handler_116, + (uint32_t) interrupt_handler_117, + (uint32_t) interrupt_handler_118, + (uint32_t) interrupt_handler_119, + (uint32_t) interrupt_handler_120, + (uint32_t) interrupt_handler_121, + (uint32_t) interrupt_handler_122, + (uint32_t) interrupt_handler_123, + (uint32_t) interrupt_handler_124, + (uint32_t) interrupt_handler_125, + (uint32_t) interrupt_handler_126, + (uint32_t) interrupt_handler_127, + (uint32_t) interrupt_handler_128, + (uint32_t) interrupt_handler_129, + (uint32_t) interrupt_handler_130, + (uint32_t) interrupt_handler_131, + (uint32_t) interrupt_handler_132, + (uint32_t) interrupt_handler_133, + (uint32_t) interrupt_handler_134, + (uint32_t) interrupt_handler_135, + (uint32_t) interrupt_handler_136, + (uint32_t) interrupt_handler_137, + (uint32_t) interrupt_handler_138, + (uint32_t) interrupt_handler_139, + (uint32_t) interrupt_handler_140, + (uint32_t) interrupt_handler_141, + (uint32_t) interrupt_handler_142, + (uint32_t) interrupt_handler_143, + (uint32_t) interrupt_handler_144, + (uint32_t) interrupt_handler_145, + (uint32_t) interrupt_handler_146, + (uint32_t) interrupt_handler_147, + (uint32_t) interrupt_handler_148, + (uint32_t) interrupt_handler_149, + (uint32_t) interrupt_handler_150, + (uint32_t) interrupt_handler_151, + (uint32_t) interrupt_handler_152, + (uint32_t) interrupt_handler_153, + (uint32_t) interrupt_handler_154, + (uint32_t) interrupt_handler_155, + (uint32_t) interrupt_handler_156, + (uint32_t) interrupt_handler_157, + (uint32_t) interrupt_handler_158, + (uint32_t) interrupt_handler_159, + (uint32_t) interrupt_handler_160, + (uint32_t) interrupt_handler_161, + (uint32_t) interrupt_handler_162, + (uint32_t) interrupt_handler_163, + (uint32_t) interrupt_handler_164, + (uint32_t) interrupt_handler_165, + (uint32_t) interrupt_handler_166, + (uint32_t) interrupt_handler_167, + (uint32_t) interrupt_handler_168, + (uint32_t) interrupt_handler_169, + (uint32_t) interrupt_handler_170, + (uint32_t) interrupt_handler_171, + (uint32_t) interrupt_handler_172, + (uint32_t) interrupt_handler_173, + (uint32_t) interrupt_handler_174, + (uint32_t) interrupt_handler_175, + (uint32_t) interrupt_handler_176, + (uint32_t) interrupt_handler_177, + (uint32_t) interrupt_handler_178, + (uint32_t) interrupt_handler_179, + (uint32_t) interrupt_handler_180, + (uint32_t) interrupt_handler_181, + (uint32_t) interrupt_handler_182, + (uint32_t) interrupt_handler_183, + (uint32_t) interrupt_handler_184, + (uint32_t) interrupt_handler_185, + (uint32_t) interrupt_handler_186, + (uint32_t) interrupt_handler_187, + (uint32_t) interrupt_handler_188, + (uint32_t) interrupt_handler_189, + (uint32_t) interrupt_handler_190, + (uint32_t) interrupt_handler_191, + (uint32_t) interrupt_handler_192, + (uint32_t) interrupt_handler_193, + (uint32_t) interrupt_handler_194, + (uint32_t) interrupt_handler_195, + (uint32_t) interrupt_handler_196, + (uint32_t) interrupt_handler_197, + (uint32_t) interrupt_handler_198, + (uint32_t) interrupt_handler_199, + (uint32_t) interrupt_handler_200, + (uint32_t) interrupt_handler_201, + (uint32_t) interrupt_handler_202, + (uint32_t) interrupt_handler_203, + (uint32_t) interrupt_handler_204, + (uint32_t) interrupt_handler_205, + (uint32_t) interrupt_handler_206, + (uint32_t) interrupt_handler_207, + (uint32_t) interrupt_handler_208, + (uint32_t) interrupt_handler_209, + (uint32_t) interrupt_handler_210, + (uint32_t) interrupt_handler_211, + (uint32_t) interrupt_handler_212, + (uint32_t) interrupt_handler_213, + (uint32_t) interrupt_handler_214, + (uint32_t) interrupt_handler_215, + (uint32_t) interrupt_handler_216, + (uint32_t) interrupt_handler_217, + (uint32_t) interrupt_handler_218, + (uint32_t) interrupt_handler_219, + (uint32_t) interrupt_handler_220, + (uint32_t) interrupt_handler_221, + (uint32_t) interrupt_handler_222, + (uint32_t) interrupt_handler_223, + (uint32_t) interrupt_handler_224, + (uint32_t) interrupt_handler_225, + (uint32_t) interrupt_handler_226, + (uint32_t) interrupt_handler_227, + (uint32_t) interrupt_handler_228, + (uint32_t) interrupt_handler_229, + (uint32_t) interrupt_handler_230, + (uint32_t) interrupt_handler_231, + (uint32_t) interrupt_handler_232, + (uint32_t) interrupt_handler_233, + (uint32_t) interrupt_handler_234, + (uint32_t) interrupt_handler_235, + (uint32_t) interrupt_handler_236, + (uint32_t) interrupt_handler_237, + (uint32_t) interrupt_handler_238, + (uint32_t) interrupt_handler_239, + (uint32_t) interrupt_handler_240, + (uint32_t) interrupt_handler_241, + (uint32_t) interrupt_handler_242, + (uint32_t) interrupt_handler_243, + (uint32_t) interrupt_handler_244, + (uint32_t) interrupt_handler_245, + (uint32_t) interrupt_handler_246, + (uint32_t) interrupt_handler_247, + (uint32_t) interrupt_handler_248, + (uint32_t) interrupt_handler_249, + (uint32_t) interrupt_handler_250, + (uint32_t) interrupt_handler_251, + (uint32_t) interrupt_handler_252, + (uint32_t) interrupt_handler_253, + (uint32_t) interrupt_handler_254, + (uint32_t) interrupt_handler_255, +}; + +void initialize_idt() { + idt_description_structure.size = sizeof(idt) - 1; + idt_description_structure.offset = (uint32_t) idt; + + uint16_t selector = KERNAL_CODE_SEGMENT_SELECTOR; + uint8_t zero = 0x00; + uint8_t type_attr = 0x8E; + + for (int i = 0; i < 256; i++) { + uint32_t interrupt_handler_address = interrupt_handler_addresses[i]; + uint16_t offset_0_15 = interrupt_handler_address & 0x0000FFFF; + uint16_t offset_16_31 = interrupt_handler_address >> 16; + + idt[i].offset_0_15 = offset_0_15; + idt[i].selector = selector; + idt[i].zero = zero; + idt[i].type_attr = type_attr; + idt[i].offset_16_31 = offset_16_31; + } + + load_idt(&idt_description_structure); +} \ No newline at end of file diff --git a/data_structures/interrupt_descriptor_table.h b/data_structures/interrupt_descriptor_table.h new file mode 100644 index 0000000..f096b6a --- /dev/null +++ b/data_structures/interrupt_descriptor_table.h @@ -0,0 +1,6 @@ +#ifndef INCLUDE_INTERRUPT_DESCRIPTOR_TABLE_H +#define INCLUDE_INTERRUPT_DESCRIPTOR_TABLE_H + +void initialize_idt(); + +#endif /* INCLUDE_INTERRUPT_DESCRIPTOR_TABLE_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index 9806e72..06702d3 100644 --- a/kmain.c +++ b/kmain.c @@ -1,364 +1,13 @@ -#include "asm_interrupts.h" #include "assembly_interface.h" +#include "data_structures/global_descriptor_table.h" +#include "data_structures/interrupt_descriptor_table.h" #include "drivers/frame_buffer.h" #include "drivers/pic.h" #include "drivers/serial_port.h" -#include "interrupts.h" #include "multiboot_utils.h" #include "stdio.h" #include "types.h" -// a pointer to the global descriptor table -// passed by reference to the LGDT instruction -struct gdt_description_structure_t { - uint16_t size; // in bytes - uint32_t offset; -} __attribute__((packed)) gdt_description_structure; - -// a pointer to the interrupt descriptor table -// passed by reference to the LIDT instruction -struct idt_description_structure_t { - uint16_t size; // in bytes - uint32_t offset; -} __attribute__((packed)) idt_description_structure; - -// See http://wiki.osdev.org/Global_Descriptor_Table#Structure -struct segment_descriptor_t { - uint16_t limit_0_15; // bits o-15 of limit - uint16_t base_0_15; - uint8_t base_16_23; - uint8_t access_byte; - uint8_t flags_and_limit_16_19; - uint8_t base_24_31; -} __attribute__((packed)); - -// See http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure_IA-32 -struct interrupt_descriptor_t { - uint16_t offset_0_15; - uint16_t selector; - uint8_t zero; - uint8_t type_attr; - uint16_t offset_16_31; -} __attribute__((packed)); - -enum segment_selector_t { - NULL_DESCRIPTOR, // Not used but has to be here - KERNAL_CODE_SEGMENT_INDEX, // Offset 0x8 - KERNAL_DATA_SEGMENT_INDEX // Offset 0x10 -}; -struct segment_descriptor_t gdt[3]; -const uint16_t NULL_SEGMENT_SELECTOR = 0x0; -const uint16_t KERNAL_CODE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 1; -const uint16_t KERNAL_DATA_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 2; - -struct interrupt_descriptor_t idt[256]; - -void initialize_gdt() { - gdt_description_structure.size = sizeof(gdt) - 1; - gdt_description_structure.offset = (uint32_t) gdt; - - gdt[KERNAL_CODE_SEGMENT_INDEX].limit_0_15 = 0xFFFF; - gdt[KERNAL_CODE_SEGMENT_INDEX].base_0_15 = 0x0000; - gdt[KERNAL_CODE_SEGMENT_INDEX].base_16_23 = 0x00; - gdt[KERNAL_CODE_SEGMENT_INDEX].access_byte = 0b10011010; - gdt[KERNAL_CODE_SEGMENT_INDEX].flags_and_limit_16_19 = 0xCF; - gdt[KERNAL_CODE_SEGMENT_INDEX].base_24_31 = 0x00; - - gdt[KERNAL_DATA_SEGMENT_INDEX].limit_0_15 = 0xFFFF; - gdt[KERNAL_DATA_SEGMENT_INDEX].base_0_15 = 0x0000; - gdt[KERNAL_DATA_SEGMENT_INDEX].base_16_23 = 0x00; - gdt[KERNAL_DATA_SEGMENT_INDEX].access_byte = 0b10010010; - gdt[KERNAL_DATA_SEGMENT_INDEX].flags_and_limit_16_19 = 0xCF; - gdt[KERNAL_DATA_SEGMENT_INDEX].base_24_31 = 0x00; - - lgdt(&gdt_description_structure); - - // Grub has already loaded the segment registers - // with the correct values (0x8 for cs, 0x10 for the others) -} - -uint32_t interrupt_handler_addresses[] = { - (uint32_t) interrupt_handler_0, - (uint32_t) interrupt_handler_1, - (uint32_t) interrupt_handler_2, - (uint32_t) interrupt_handler_3, - (uint32_t) interrupt_handler_4, - (uint32_t) interrupt_handler_5, - (uint32_t) interrupt_handler_6, - (uint32_t) interrupt_handler_7, - (uint32_t) interrupt_handler_8, - (uint32_t) interrupt_handler_9, - (uint32_t) interrupt_handler_10, - (uint32_t) interrupt_handler_11, - (uint32_t) interrupt_handler_12, - (uint32_t) interrupt_handler_13, - (uint32_t) interrupt_handler_14, - (uint32_t) interrupt_handler_15, - (uint32_t) interrupt_handler_16, - (uint32_t) interrupt_handler_17, - (uint32_t) interrupt_handler_18, - (uint32_t) interrupt_handler_19, - (uint32_t) interrupt_handler_20, - (uint32_t) interrupt_handler_21, - (uint32_t) interrupt_handler_22, - (uint32_t) interrupt_handler_23, - (uint32_t) interrupt_handler_24, - (uint32_t) interrupt_handler_25, - (uint32_t) interrupt_handler_26, - (uint32_t) interrupt_handler_27, - (uint32_t) interrupt_handler_28, - (uint32_t) interrupt_handler_29, - (uint32_t) interrupt_handler_30, - (uint32_t) interrupt_handler_31, - (uint32_t) interrupt_handler_32, - (uint32_t) interrupt_handler_33, - (uint32_t) interrupt_handler_34, - (uint32_t) interrupt_handler_35, - (uint32_t) interrupt_handler_36, - (uint32_t) interrupt_handler_37, - (uint32_t) interrupt_handler_38, - (uint32_t) interrupt_handler_39, - (uint32_t) interrupt_handler_40, - (uint32_t) interrupt_handler_41, - (uint32_t) interrupt_handler_42, - (uint32_t) interrupt_handler_43, - (uint32_t) interrupt_handler_44, - (uint32_t) interrupt_handler_45, - (uint32_t) interrupt_handler_46, - (uint32_t) interrupt_handler_47, - (uint32_t) interrupt_handler_48, - (uint32_t) interrupt_handler_49, - (uint32_t) interrupt_handler_50, - (uint32_t) interrupt_handler_51, - (uint32_t) interrupt_handler_52, - (uint32_t) interrupt_handler_53, - (uint32_t) interrupt_handler_54, - (uint32_t) interrupt_handler_55, - (uint32_t) interrupt_handler_56, - (uint32_t) interrupt_handler_57, - (uint32_t) interrupt_handler_58, - (uint32_t) interrupt_handler_59, - (uint32_t) interrupt_handler_60, - (uint32_t) interrupt_handler_61, - (uint32_t) interrupt_handler_62, - (uint32_t) interrupt_handler_63, - (uint32_t) interrupt_handler_64, - (uint32_t) interrupt_handler_65, - (uint32_t) interrupt_handler_66, - (uint32_t) interrupt_handler_67, - (uint32_t) interrupt_handler_68, - (uint32_t) interrupt_handler_69, - (uint32_t) interrupt_handler_70, - (uint32_t) interrupt_handler_71, - (uint32_t) interrupt_handler_72, - (uint32_t) interrupt_handler_73, - (uint32_t) interrupt_handler_74, - (uint32_t) interrupt_handler_75, - (uint32_t) interrupt_handler_76, - (uint32_t) interrupt_handler_77, - (uint32_t) interrupt_handler_78, - (uint32_t) interrupt_handler_79, - (uint32_t) interrupt_handler_80, - (uint32_t) interrupt_handler_81, - (uint32_t) interrupt_handler_82, - (uint32_t) interrupt_handler_83, - (uint32_t) interrupt_handler_84, - (uint32_t) interrupt_handler_85, - (uint32_t) interrupt_handler_86, - (uint32_t) interrupt_handler_87, - (uint32_t) interrupt_handler_88, - (uint32_t) interrupt_handler_89, - (uint32_t) interrupt_handler_90, - (uint32_t) interrupt_handler_91, - (uint32_t) interrupt_handler_92, - (uint32_t) interrupt_handler_93, - (uint32_t) interrupt_handler_94, - (uint32_t) interrupt_handler_95, - (uint32_t) interrupt_handler_96, - (uint32_t) interrupt_handler_97, - (uint32_t) interrupt_handler_98, - (uint32_t) interrupt_handler_99, - (uint32_t) interrupt_handler_100, - (uint32_t) interrupt_handler_101, - (uint32_t) interrupt_handler_102, - (uint32_t) interrupt_handler_103, - (uint32_t) interrupt_handler_104, - (uint32_t) interrupt_handler_105, - (uint32_t) interrupt_handler_106, - (uint32_t) interrupt_handler_107, - (uint32_t) interrupt_handler_108, - (uint32_t) interrupt_handler_109, - (uint32_t) interrupt_handler_110, - (uint32_t) interrupt_handler_111, - (uint32_t) interrupt_handler_112, - (uint32_t) interrupt_handler_113, - (uint32_t) interrupt_handler_114, - (uint32_t) interrupt_handler_115, - (uint32_t) interrupt_handler_116, - (uint32_t) interrupt_handler_117, - (uint32_t) interrupt_handler_118, - (uint32_t) interrupt_handler_119, - (uint32_t) interrupt_handler_120, - (uint32_t) interrupt_handler_121, - (uint32_t) interrupt_handler_122, - (uint32_t) interrupt_handler_123, - (uint32_t) interrupt_handler_124, - (uint32_t) interrupt_handler_125, - (uint32_t) interrupt_handler_126, - (uint32_t) interrupt_handler_127, - (uint32_t) interrupt_handler_128, - (uint32_t) interrupt_handler_129, - (uint32_t) interrupt_handler_130, - (uint32_t) interrupt_handler_131, - (uint32_t) interrupt_handler_132, - (uint32_t) interrupt_handler_133, - (uint32_t) interrupt_handler_134, - (uint32_t) interrupt_handler_135, - (uint32_t) interrupt_handler_136, - (uint32_t) interrupt_handler_137, - (uint32_t) interrupt_handler_138, - (uint32_t) interrupt_handler_139, - (uint32_t) interrupt_handler_140, - (uint32_t) interrupt_handler_141, - (uint32_t) interrupt_handler_142, - (uint32_t) interrupt_handler_143, - (uint32_t) interrupt_handler_144, - (uint32_t) interrupt_handler_145, - (uint32_t) interrupt_handler_146, - (uint32_t) interrupt_handler_147, - (uint32_t) interrupt_handler_148, - (uint32_t) interrupt_handler_149, - (uint32_t) interrupt_handler_150, - (uint32_t) interrupt_handler_151, - (uint32_t) interrupt_handler_152, - (uint32_t) interrupt_handler_153, - (uint32_t) interrupt_handler_154, - (uint32_t) interrupt_handler_155, - (uint32_t) interrupt_handler_156, - (uint32_t) interrupt_handler_157, - (uint32_t) interrupt_handler_158, - (uint32_t) interrupt_handler_159, - (uint32_t) interrupt_handler_160, - (uint32_t) interrupt_handler_161, - (uint32_t) interrupt_handler_162, - (uint32_t) interrupt_handler_163, - (uint32_t) interrupt_handler_164, - (uint32_t) interrupt_handler_165, - (uint32_t) interrupt_handler_166, - (uint32_t) interrupt_handler_167, - (uint32_t) interrupt_handler_168, - (uint32_t) interrupt_handler_169, - (uint32_t) interrupt_handler_170, - (uint32_t) interrupt_handler_171, - (uint32_t) interrupt_handler_172, - (uint32_t) interrupt_handler_173, - (uint32_t) interrupt_handler_174, - (uint32_t) interrupt_handler_175, - (uint32_t) interrupt_handler_176, - (uint32_t) interrupt_handler_177, - (uint32_t) interrupt_handler_178, - (uint32_t) interrupt_handler_179, - (uint32_t) interrupt_handler_180, - (uint32_t) interrupt_handler_181, - (uint32_t) interrupt_handler_182, - (uint32_t) interrupt_handler_183, - (uint32_t) interrupt_handler_184, - (uint32_t) interrupt_handler_185, - (uint32_t) interrupt_handler_186, - (uint32_t) interrupt_handler_187, - (uint32_t) interrupt_handler_188, - (uint32_t) interrupt_handler_189, - (uint32_t) interrupt_handler_190, - (uint32_t) interrupt_handler_191, - (uint32_t) interrupt_handler_192, - (uint32_t) interrupt_handler_193, - (uint32_t) interrupt_handler_194, - (uint32_t) interrupt_handler_195, - (uint32_t) interrupt_handler_196, - (uint32_t) interrupt_handler_197, - (uint32_t) interrupt_handler_198, - (uint32_t) interrupt_handler_199, - (uint32_t) interrupt_handler_200, - (uint32_t) interrupt_handler_201, - (uint32_t) interrupt_handler_202, - (uint32_t) interrupt_handler_203, - (uint32_t) interrupt_handler_204, - (uint32_t) interrupt_handler_205, - (uint32_t) interrupt_handler_206, - (uint32_t) interrupt_handler_207, - (uint32_t) interrupt_handler_208, - (uint32_t) interrupt_handler_209, - (uint32_t) interrupt_handler_210, - (uint32_t) interrupt_handler_211, - (uint32_t) interrupt_handler_212, - (uint32_t) interrupt_handler_213, - (uint32_t) interrupt_handler_214, - (uint32_t) interrupt_handler_215, - (uint32_t) interrupt_handler_216, - (uint32_t) interrupt_handler_217, - (uint32_t) interrupt_handler_218, - (uint32_t) interrupt_handler_219, - (uint32_t) interrupt_handler_220, - (uint32_t) interrupt_handler_221, - (uint32_t) interrupt_handler_222, - (uint32_t) interrupt_handler_223, - (uint32_t) interrupt_handler_224, - (uint32_t) interrupt_handler_225, - (uint32_t) interrupt_handler_226, - (uint32_t) interrupt_handler_227, - (uint32_t) interrupt_handler_228, - (uint32_t) interrupt_handler_229, - (uint32_t) interrupt_handler_230, - (uint32_t) interrupt_handler_231, - (uint32_t) interrupt_handler_232, - (uint32_t) interrupt_handler_233, - (uint32_t) interrupt_handler_234, - (uint32_t) interrupt_handler_235, - (uint32_t) interrupt_handler_236, - (uint32_t) interrupt_handler_237, - (uint32_t) interrupt_handler_238, - (uint32_t) interrupt_handler_239, - (uint32_t) interrupt_handler_240, - (uint32_t) interrupt_handler_241, - (uint32_t) interrupt_handler_242, - (uint32_t) interrupt_handler_243, - (uint32_t) interrupt_handler_244, - (uint32_t) interrupt_handler_245, - (uint32_t) interrupt_handler_246, - (uint32_t) interrupt_handler_247, - (uint32_t) interrupt_handler_248, - (uint32_t) interrupt_handler_249, - (uint32_t) interrupt_handler_250, - (uint32_t) interrupt_handler_251, - (uint32_t) interrupt_handler_252, - (uint32_t) interrupt_handler_253, - (uint32_t) interrupt_handler_254, - (uint32_t) interrupt_handler_255, -}; - -void initialize_idt() { - idt_description_structure.size = sizeof(idt) - 1; - idt_description_structure.offset = (uint32_t) idt; - - uint16_t selector = KERNAL_CODE_SEGMENT_SELECTOR; - uint8_t zero = 0x00; - uint8_t type_attr = 0x8E; - - for (int i = 0; i < 256; i++) { - uint32_t interrupt_handler_address = interrupt_handler_addresses[i]; - uint16_t offset_0_15 = interrupt_handler_address & 0x0000FFFF; - uint16_t offset_16_31 = interrupt_handler_address >> 16; - - idt[i].offset_0_15 = offset_0_15; - idt[i].selector = selector; - idt[i].zero = zero; - idt[i].type_attr = type_attr; - idt[i].offset_16_31 = offset_16_31; - } - - load_idt(&idt_description_structure); -} - static char *welcome_string = "" " " " " @@ -396,13 +45,7 @@ void kmain(uint32_t ebx) { printf(welcome_string); serial_init(); - log("Initialized serial port.\n"); - - print_multiboot_info(LOG, mbinfo); - - void_function_t start_program = first_module_as_a_function(mbinfo); - start_program(); - log("Got past call to start_program()\n"); + log("\n--------------------\ncstackOS is booting!\n--------------------\n\nInitialized serial port.\n"); initialize_gdt(); log("Loaded global descriptor table.\n"); @@ -410,12 +53,20 @@ void kmain(uint32_t ebx) { initialize_idt(); log("Loaded interrupt descriptor table.\n"); + log("Issuing test interrupt.\n"); interrupt(49); log("Returned from test interrupt()\n"); pic_init(); log("Initialized PIC\n"); + log("\nMultiboot info passed to kernel from GRUB:\n"); + print_multiboot_info(LOG, mbinfo); + + void_function_t start_program = first_module_as_a_function(mbinfo); + start_program(); + log("Got past call to start_program()\n"); + // Loop forever // User input is accepted asynchronously via interrupts while(1){} diff --git a/multiboot_utils.c b/multiboot_utils.c index f925187..652aa7f 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -1,15 +1,14 @@ #include "multiboot_utils.h" void print_module_info(FILE stream, struct module * m) { + fprintf(stream, (char*) m->string); + fprintf(stream, ":\n"); fprintf(stream, "mod_start: "); print_uint32(stream, m->mod_start); fprintf(stream, "\n"); fprintf(stream, "mod_end: "); print_uint32(stream, m->mod_end); fprintf(stream, "\n"); - fprintf(stream, "string: "); - fprintf(stream, (char*) m->string); - fprintf(stream, "\n"); } void print_multiboot_info(FILE stream, multiboot_info_t* info) { @@ -40,12 +39,9 @@ void print_multiboot_info(FILE stream, multiboot_info_t* info) { struct module * modules; if (info->mods_count > 0) { - fprintf(stream, "\nmodules:\n"); modules = (struct module *) info->mods_addr; for (uint8_t i = 0; i < info->mods_count; i++) { - fprintf(stream, "module #"); - print_uint8(stream, i); - fprintf(stream, ":\n"); + fprintf(stream, "\n"); print_module_info(stream, &(modules[i])); } } From 10b6c727602c9d6ba5c2c12752a47f6f9172d60e Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 2 Oct 2016 17:29:28 -0700 Subject: [PATCH 18/67] Enable paging and set up page fault handler. --- Makefile | 1 + asm_interrupts.s | 5 ++- assembly_interface.h | 10 +++++ assembly_interface.s | 17 +++++++ data_structures/page_table.c | 86 ++++++++++++++++++++++++++++++++++++ data_structures/page_table.h | 12 +++++ interrupts.c | 31 ++++++++++++- interrupts.h | 13 +++--- kmain.c | 33 ++++++++++++++ loader.h | 7 +++ loader.s | 10 ++++- 11 files changed, 216 insertions(+), 9 deletions(-) create mode 100644 data_structures/page_table.c create mode 100644 data_structures/page_table.h create mode 100644 loader.h diff --git a/Makefile b/Makefile index 95af2ee..2b089a8 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ asm_interrupts.o \ assembly_interface.o \ data_structures/global_descriptor_table.o \ data_structures/interrupt_descriptor_table.o \ +data_structures/page_table.o \ drivers/frame_buffer.o \ drivers/keyboard.o \ drivers/pic.o \ diff --git a/asm_interrupts.s b/asm_interrupts.s index b8b91f5..8bbcb0b 100644 --- a/asm_interrupts.s +++ b/asm_interrupts.s @@ -86,7 +86,7 @@ interrupt_handler_13: global interrupt_handler_14 interrupt_handler_14: - push dword 0 + ; don't push an error code, the cpu will do that push dword 14 jmp common_interrupt_handler @@ -1545,11 +1545,14 @@ common_interrupt_handler: ; the common parts of the generic interr push esi push edi push ebp + mov eax, cr2 + push eax ; call the C function call interrupt_handler ; restore the registers + add esp, 4 ; cr2 pop ebp pop edi pop esi diff --git a/assembly_interface.h b/assembly_interface.h index 4c307d5..ad88310 100644 --- a/assembly_interface.h +++ b/assembly_interface.h @@ -48,4 +48,14 @@ void interrupt(uint32_t interrupt_number); */ void enable_hardware_interrupts(); +/** set_page_directory: + * Sets control register 3 to the physical address of a page directory + */ +void set_page_directory(); + +/** enable_paging: + * Sets the paging bit on control register 0 + */ +void enable_paging(); + #endif /* INCLUDE_ASSEMBLY_INTERFACE_H */ \ No newline at end of file diff --git a/assembly_interface.s b/assembly_interface.s index fd8dce3..07dee22 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -53,3 +53,20 @@ global enable_hardware_interrupts enable_hardware_interrupts: sti ret + +global set_page_directory +; sets cr3 to the physical address of a page directory +; page_directory: [esp + 4] the physical address of the page directory +; [esp ] the return address +set_page_directory: + mov eax, [esp+4] + mov cr3, eax + ret + +global enable_paging +; sets the paging bit on control register 0 +enable_paging: + mov eax, cr0 + or eax, 0x80000000 + mov cr0, eax + ret diff --git a/data_structures/page_table.c b/data_structures/page_table.c new file mode 100644 index 0000000..04d1a97 --- /dev/null +++ b/data_structures/page_table.c @@ -0,0 +1,86 @@ +#include "page_table.h" + +#include "../loader.h" + +enum page_size_t {FOUR_KB, FOUR_MB}; +enum page_privilege_t {SUPERVISOR, USER}; +enum page_permissions_t {READ_ONLY, READ_WRITE}; + +struct page_directory_entry_t { + uint32_t page_table_address; +} __attribute__((packed)); + +uint32_t make_page_directory_entry( + uint32_t page_table_address, + enum page_size_t page_size, + bool cache_disabled, + bool write_through, + enum page_privilege_t privelage, + enum page_permissions_t permissions, + bool present +) { + uint32_t entry = page_table_address; + entry |= page_size << 7; + entry |= cache_disabled << 4; + entry |= write_through << 3; + entry |= privelage << 2; + entry |= permissions << 1; + entry |= present; + + return entry; +} + +uint32_t make_page_table_entry( + uint32_t page_frame_address, + bool global, + bool cache_disabled, + bool write_through, + enum page_privilege_t privelage, + enum page_permissions_t permissions, + bool present +) { + uint32_t entry = page_frame_address; + entry |= global << 8; + entry |= cache_disabled << 6; + entry |= write_through << 3; + entry |= privelage << 2; + entry |= permissions << 1; + entry |= present; + + return entry; +} + +// 1 page = 1024 * 4 bytes = 4 kB +// 1 page table = 1024 pages = 4 mB +// 1 page directory = 1024 page tables = 4 gB + +page_directory_t initialize_page_directory() { + page_directory_t pd = (page_directory_t) &boot_pagedir; + page_table_t pt = (page_table_t) &boot_pagetab1; + *pd = make_page_directory_entry( + (uint32_t) pt, + FOUR_KB, + false, + false, + SUPERVISOR, + READ_WRITE, + true + ); + for (int i = 0; i < 1024; i++) { + pt[i] = make_page_table_entry( + 4096*i, + false, + false, + false, + SUPERVISOR, + READ_WRITE, + true + ); + } + return pd; +} + +page_table_t get_page_table(page_directory_t pd, int i) { + uint32_t entry = pd[i]; + return (page_table_t) (entry & 0xFFFFF000); +} \ No newline at end of file diff --git a/data_structures/page_table.h b/data_structures/page_table.h new file mode 100644 index 0000000..95b64ac --- /dev/null +++ b/data_structures/page_table.h @@ -0,0 +1,12 @@ +#ifndef INCLUDE_PAGE_TABLE_H +#define INCLUDE_PAGE_TABLE_H + +#include "../types.h" + +typedef uint32_t * page_directory_t; +typedef uint32_t * page_table_t; + +page_directory_t initialize_page_directory(); +page_table_t get_page_table(page_directory_t pd, int i); + +#endif /* INCLUDE_PAGE_TABLE_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index 3f05520..b98e3fe 100644 --- a/interrupts.c +++ b/interrupts.c @@ -6,9 +6,10 @@ #include "stdio.h" #define INT_KEYBOARD 0x00000009 +#define INT_GENERAL_PROTECTION_FAULT 0x0000000D +#define INT_PAGE_FAULT 0x0000000E void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code) { - if (cpu.eax) {}; // Avoid unused parameter error if (error_code) { log("interrupt_handler() error_code "); print_uint32(LOG, error_code); @@ -19,6 +20,34 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t case(INT_KEYBOARD): keyboard_interrupt_handler(); break; + case(INT_PAGE_FAULT): + log("\nPage fault! Here's what I know:\n"); + log("- Tried to access linear address "); + print_uint32(LOG, cpu.cr2); + log("\n"); + if (error_code & 0b1) { + log("- Couldn't complete because of page-protection violation\n"); + } else { + log("- Couldn't complete because page was not present\n"); + } + if (error_code & 0b10) { + log("- This was an attempt to WRITE to this address.\n"); + } else { + log("- This was an attempt to READ from this address.\n"); + } + if (error_code & 0b100) { + log("- Memory access came from user.\n"); + } else { + log("- Memory access came from kernel.\n"); + } + if (error_code & 0b1000) { + log("- caused by reading a 1 in a reserved field.\n"); + } + if (error_code & 0b10000) { + log("- caused by an instruction fetch.\n"); + } + while(1){}; + break; default: log("Unhandled Interrupt: "); diff --git a/interrupts.h b/interrupts.h index b9e1892..7f9f90d 100644 --- a/interrupts.h +++ b/interrupts.h @@ -4,13 +4,14 @@ #include "types.h" struct cpu_state { - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t esi; - uint32_t edi; + uint32_t cr2; uint32_t ebp; + uint32_t edi; + uint32_t esi; + uint32_t edx; + uint32_t ecx; + uint32_t ebx; + uint32_t eax; } __attribute__((packed)); struct stack_state { diff --git a/kmain.c b/kmain.c index 06702d3..d1bbc41 100644 --- a/kmain.c +++ b/kmain.c @@ -1,6 +1,7 @@ #include "assembly_interface.h" #include "data_structures/global_descriptor_table.h" #include "data_structures/interrupt_descriptor_table.h" +#include "data_structures/page_table.h" #include "drivers/frame_buffer.h" #include "drivers/pic.h" #include "drivers/serial_port.h" @@ -60,6 +61,38 @@ void kmain(uint32_t ebx) { pic_init(); log("Initialized PIC\n"); + page_directory_t pd = initialize_page_directory(); + log("Initialized page directory.\n"); + log("Address of page directory: "); + print_uint32(LOG, (uint32_t) pd); + log("\n"); + + page_table_t pt = get_page_table(pd, 0); + log("Address of first page table: "); + print_uint32(LOG, (uint32_t) pt); + log("\n"); + + log("First 5 page table entries: "); + for (int i = 0; i < 5; i++) { + print_uint32(LOG, pt[i]); + log("\n"); + } + + log("Setting page directory...\n"); + set_page_directory(pd); + log("Set page directory.\n"); + + log("Enabling paging...\n"); + enable_paging(); + log("Paging enabled.\n"); + + uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB + log("Trying to access address "); + print_uint32(LOG, (uint32_t) unmapped_address); + log(":\n"); + print_uint8(LOG, *unmapped_address); + log("\n. Successfully accessed."); + log("\nMultiboot info passed to kernel from GRUB:\n"); print_multiboot_info(LOG, mbinfo); diff --git a/loader.h b/loader.h new file mode 100644 index 0000000..5865dd9 --- /dev/null +++ b/loader.h @@ -0,0 +1,7 @@ +#ifndef INCLUDE_LOADER_H +#define INCLUDE_LOADER_H + +void * boot_pagedir; +void * boot_pagetab1; + +#endif /* INCLUDE_LOADER_H */ \ No newline at end of file diff --git a/loader.s b/loader.s index 43f2e65..43b3d49 100644 --- a/loader.s +++ b/loader.s @@ -55,7 +55,15 @@ loader: ; the loader label (defined as entry point in li call kmain ; use call rather than jmp so C function finds paramters in the correct place hlt ; should never get here. kmain should not return. +global boot_pagedir +global boot_pagetab1 section .bss ; Use the 'bss' section for the stack align 4 ; align at 4 bytes for performance reasons kernel_stack: ; label points to beginning of memory - resb KERNEL_STACK_SIZE ; reserve stack for the kernel \ No newline at end of file + resb KERNEL_STACK_SIZE ; reserve stack for the kernel + + align 4096 + boot_pagedir: + resb 4096 + boot_pagetab1: + resb 4096 \ No newline at end of file From 846dc5f172e2f254c22f90d3fe3c51965ceaf8c0 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 15 Oct 2016 19:41:30 -0700 Subject: [PATCH 19/67] Higher half kernel is able to call kmain(). --- kmain.c | 176 ++++++++++++++++++++++++++++--------------------------- link.ld | 10 ++-- loader.s | 53 ++++++++++++++++- 3 files changed, 144 insertions(+), 95 deletions(-) diff --git a/kmain.c b/kmain.c index d1bbc41..65d97dc 100644 --- a/kmain.c +++ b/kmain.c @@ -9,98 +9,100 @@ #include "stdio.h" #include "types.h" -static char *welcome_string = "" -" " -" " -" " -" " -" | | | | " -" ___ ___ | |_ __ _ ___ | | __ " -" / __| / __| | __| / _` | / __| | |/ / " -" | (__ \\__ \\ | |_ | (_| | | (__ | < " -" \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " -" " -" " -" ____ _____ " -" / __ \\ / ____| " -" | | | | | (___ " -" | | | | \\___ \\ " -" | |__| | ____) | " -" \\____/ |_____/ " -" " -" " -" " -" " -" " -" " -" " -" " -""; +// static char *welcome_string = "" +// " " +// " " +// " " +// " " +// " | | | | " +// " ___ ___ | |_ __ _ ___ | | __ " +// " / __| / __| | __| / _` | / __| | |/ / " +// " | (__ \\__ \\ | |_ | (_| | | (__ | < " +// " \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " +// " " +// " " +// " ____ _____ " +// " / __ \\ / ____| " +// " | | | | | (___ " +// " | | | | \\___ \\ " +// " | |__| | ____) | " +// " \\____/ |_____/ " +// " " +// " " +// " " +// " " +// " " +// " " +// " " +// " " +// ""; void kmain(uint32_t ebx) { - // GRUB passes info to the kernel through the ebx register - multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; + // // GRUB passes info to the kernel through the ebx register + // multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; + if(ebx){}; - clear_screen(); + // clear_screen(); - printf(welcome_string); + // printf(welcome_string); serial_init(); log("\n--------------------\ncstackOS is booting!\n--------------------\n\nInitialized serial port.\n"); - - initialize_gdt(); - log("Loaded global descriptor table.\n"); - - initialize_idt(); - log("Loaded interrupt descriptor table.\n"); - - log("Issuing test interrupt.\n"); - interrupt(49); - log("Returned from test interrupt()\n"); - - pic_init(); - log("Initialized PIC\n"); - - page_directory_t pd = initialize_page_directory(); - log("Initialized page directory.\n"); - log("Address of page directory: "); - print_uint32(LOG, (uint32_t) pd); - log("\n"); - - page_table_t pt = get_page_table(pd, 0); - log("Address of first page table: "); - print_uint32(LOG, (uint32_t) pt); - log("\n"); - - log("First 5 page table entries: "); - for (int i = 0; i < 5; i++) { - print_uint32(LOG, pt[i]); - log("\n"); - } - - log("Setting page directory...\n"); - set_page_directory(pd); - log("Set page directory.\n"); - - log("Enabling paging...\n"); - enable_paging(); - log("Paging enabled.\n"); - - uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB - log("Trying to access address "); - print_uint32(LOG, (uint32_t) unmapped_address); - log(":\n"); - print_uint8(LOG, *unmapped_address); - log("\n. Successfully accessed."); - - log("\nMultiboot info passed to kernel from GRUB:\n"); - print_multiboot_info(LOG, mbinfo); - - void_function_t start_program = first_module_as_a_function(mbinfo); - start_program(); - log("Got past call to start_program()\n"); - - // Loop forever - // User input is accepted asynchronously via interrupts - while(1){} + while(1){}; + + // initialize_gdt(); + // log("Loaded global descriptor table.\n"); + + // initialize_idt(); + // log("Loaded interrupt descriptor table.\n"); + + // log("Issuing test interrupt.\n"); + // interrupt(49); + // log("Returned from test interrupt()\n"); + + // pic_init(); + // log("Initialized PIC\n"); + + // page_directory_t pd = initialize_page_directory(); + // log("Initialized page directory.\n"); + // log("Address of page directory: "); + // print_uint32(LOG, (uint32_t) pd); + // log("\n"); + + // page_table_t pt = get_page_table(pd, 0); + // log("Address of first page table: "); + // print_uint32(LOG, (uint32_t) pt); + // log("\n"); + + // log("First 5 page table entries: "); + // for (int i = 0; i < 5; i++) { + // print_uint32(LOG, pt[i]); + // log("\n"); + // } + + // log("Setting page directory...\n"); + // set_page_directory(pd); + // log("Set page directory.\n"); + + // log("Enabling paging...\n"); + // enable_paging(); + // log("Paging enabled.\n"); + + // uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB + // log("Trying to access address "); + // print_uint32(LOG, (uint32_t) unmapped_address); + // log(":\n"); + // print_uint8(LOG, *unmapped_address); + // log("\n. Successfully accessed."); + + // log("\nMultiboot info passed to kernel from GRUB:\n"); + // print_multiboot_info(LOG, mbinfo); + + // void_function_t start_program = first_module_as_a_function(mbinfo); + // start_program(); + // log("Got past call to start_program()\n"); + + // // Loop forever + // // User input is accepted asynchronously via interrupts + // while(1){} } \ No newline at end of file diff --git a/link.ld b/link.ld index e3d6195..233dc0f 100644 --- a/link.ld +++ b/link.ld @@ -10,24 +10,24 @@ ENTRY(loader) /* the name of the entry label */ file that we're linking */ SECTIONS { - . = 0x00100000; /* the code should be loaded at 1 MB */ + . = 0xC0100000; /* the code should be linked as though it were loaded at 3GB + 1MB. In actuality, it will be loaded at physical address 1MB, then we will map virtual addresses above 3GB to physical address starting at 0 */ - .text ALIGN (0x1000) : /* align at 4 KB, the size of a page */ + .text ALIGN (0x1000) : AT(ADDR(.text)-0xC0000000) /* align at 4 KB, the size of a page */ { *(.text) /* all text sections from all files */ } - .rodata ALIGN (0x1000) : /* align at 4 KB, the size of a page */ + .rodata ALIGN (0x1000) : AT(ADDR(.rodata)-0xC0000000) /* align at 4 KB, the size of a page */ { *(.rodata*) /* all read-only data sections from all files */ } - .data ALIGN (0x1000) : /* align at 4 KB, the size of a page */ + .data ALIGN (0x1000) : AT(ADDR(.data)-0xC0000000) /* align at 4 KB, the size of a page */ { *(.data) /* all data sections from all files */ } - .bss ALIGN (0x1000) : /* align at 4 KB, the size of a page */ + .bss ALIGN (0x1000) : AT(ADDR(.bss)-0xC0000000) /* align at 4 KB, the size of a page */ { *(COMMON) /* all COMMON sections from all files */ *(.bss) /* all bss sections from all files */ diff --git a/loader.s b/loader.s index 43b3d49..fe69c61 100644 --- a/loader.s +++ b/loader.s @@ -26,6 +26,29 @@ CHECKSUM equ -(MAGIC_NUMBER + FLAGS) KERNEL_STACK_SIZE equ 4096 ; size of stack in bytes (1 kilobyte) +; This is the virtual base address of kernel space. It must be used to convert virtual +; addresses into physical addresses until paging is enabled. Note that this is not +; the virtual address where the kernel image itself is loaded -- just the amount that must +; be subtracted from a virtual address to get a physical address. +KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB +KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; Page directory index of kernel's 4MB PTE. + +section .data +align 0x1000 +BootPageDirectory: + ; This page directory entry identity-maps the first 4MB of the 32-bit physical address space. + ; All bits are clear except the following: + ; bit 7: PS The kernel page is 4MB. + ; bit 1: RW The kernel page is read/write. + ; bit 0: P The kernel page is present. + ; This entry must be here -- otherwise the kernel will crash immediately after paging is + ; enabled because it can't fetch the next instruction! It's ok to unmap this page later. + dd 0x00000083 + times (KERNEL_PAGE_NUMBER - 1) dd 0 ; Pages before kernel space. + ; This page directory entry defines a 4MB page containing the kernel. + dd 0x00000083 + times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0 ; Pages after the kernel image. + section .text ; start of the text (code) section ; .data is for initialized variables ; .bss is for uninitialized variables @@ -41,9 +64,33 @@ align 4 ; the code must be 4 byte aligned dd FLAGS ; the flags, dd CHECKSUM ; and the checksum -loader: ; the loader label (defined as entry point in linker script) - ; that means the address of this instruction will - ; appear in the symbol table +loader equ (_loader - KERNEL_VIRTUAL_BASE) +_loader: + ; NOTE: Until paging is set up, the code must be position-independent and use physical + ; addresses, not virtual ones! + mov ecx, (BootPageDirectory - KERNEL_VIRTUAL_BASE) ; 0x104000 + mov cr3, ecx ; Load Page Directory Base Register. + + mov ecx, cr4 + or ecx, 0x00000010 ; Set PSE bit in CR4 to enable 4MB pages. + mov cr4, ecx + + mov ecx, cr0 + or ecx, 0x80000000 ; Set PG bit in CR0 to enable paging. + mov cr0, ecx + + ; Start fetching instructions in kernel space. + ; Since eip at this point holds the physical address of this command (approximately 0x00100000) + ; we need to do a long jump to the correct virtual address of StartInHigherHalf which is + ; approximately 0xC0100000. + lea ecx, [StartInHigherHalf] + jmp ecx + +StartInHigherHalf: + ; Unmap the identity-mapped first 4MB of physical address space. It should not be needed + ; anymore. + mov dword [BootPageDirectory], 0 + invlpg [0] mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the ; stack (end of memory area) From ad86a8ba4a57c6bf499a5f237637b876a5cd6e2c Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 15 Oct 2016 21:12:51 -0700 Subject: [PATCH 20/67] Fix address for frame buffer. --- drivers/frame_buffer.c | 2 +- kmain.c | 78 +++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/drivers/frame_buffer.c b/drivers/frame_buffer.c index 0f61021..beb71b2 100644 --- a/drivers/frame_buffer.c +++ b/drivers/frame_buffer.c @@ -14,7 +14,7 @@ #define FB_LOW_BYTE_COMMAND 15 // Start of memory that maps to the frame buffer -char *fb = (char *) 0x000B8000; +char *fb = (char *) 0xC00B8000; uint16_t cursor_pos = 0; diff --git a/kmain.c b/kmain.c index 65d97dc..49fc374 100644 --- a/kmain.c +++ b/kmain.c @@ -9,59 +9,59 @@ #include "stdio.h" #include "types.h" -// static char *welcome_string = "" -// " " -// " " -// " " -// " " -// " | | | | " -// " ___ ___ | |_ __ _ ___ | | __ " -// " / __| / __| | __| / _` | / __| | |/ / " -// " | (__ \\__ \\ | |_ | (_| | | (__ | < " -// " \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " -// " " -// " " -// " ____ _____ " -// " / __ \\ / ____| " -// " | | | | | (___ " -// " | | | | \\___ \\ " -// " | |__| | ____) | " -// " \\____/ |_____/ " -// " " -// " " -// " " -// " " -// " " -// " " -// " " -// " " -// ""; +static char *welcome_string = "" +" " +" " +" " +" " +" | | | | " +" ___ ___ | |_ __ _ ___ | | __ " +" / __| / __| | __| / _` | / __| | |/ / " +" | (__ \\__ \\ | |_ | (_| | | (__ | < " +" \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " +" " +" " +" ____ _____ " +" / __ \\ / ____| " +" | | | | | (___ " +" | | | | \\___ \\ " +" | |__| | ____) | " +" \\____/ |_____/ " +" " +" " +" " +" " +" " +" " +" " +" " +""; void kmain(uint32_t ebx) { // // GRUB passes info to the kernel through the ebx register // multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; if(ebx){}; - // clear_screen(); + clear_screen(); - // printf(welcome_string); + printf(welcome_string); serial_init(); log("\n--------------------\ncstackOS is booting!\n--------------------\n\nInitialized serial port.\n"); - while(1){}; - // initialize_gdt(); - // log("Loaded global descriptor table.\n"); + initialize_gdt(); + log("Loaded global descriptor table.\n"); - // initialize_idt(); - // log("Loaded interrupt descriptor table.\n"); + initialize_idt(); + log("Loaded interrupt descriptor table.\n"); - // log("Issuing test interrupt.\n"); - // interrupt(49); - // log("Returned from test interrupt()\n"); + log("Issuing test interrupt.\n"); + interrupt(49); + log("Returned from test interrupt()\n"); - // pic_init(); - // log("Initialized PIC\n"); + pic_init(); + log("Initialized PIC\n"); + while(1){}; // page_directory_t pd = initialize_page_directory(); // log("Initialized page directory.\n"); From 1de0757e4bb32f5e13f6840b9c2a438878408a62 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 15 Oct 2016 21:35:22 -0700 Subject: [PATCH 21/67] Fix grub boot info parsing. --- kmain.c | 16 +++++++--------- loader.h | 4 ++++ loader.s | 2 ++ multiboot_utils.c | 19 ++++++++++++------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/kmain.c b/kmain.c index 49fc374..6b5c8ec 100644 --- a/kmain.c +++ b/kmain.c @@ -38,9 +38,8 @@ static char *welcome_string = "" ""; void kmain(uint32_t ebx) { - // // GRUB passes info to the kernel through the ebx register - // multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; - if(ebx){}; + // GRUB passes info to the kernel through the ebx register + multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; clear_screen(); @@ -61,7 +60,6 @@ void kmain(uint32_t ebx) { pic_init(); log("Initialized PIC\n"); - while(1){}; // page_directory_t pd = initialize_page_directory(); // log("Initialized page directory.\n"); @@ -95,14 +93,14 @@ void kmain(uint32_t ebx) { // print_uint8(LOG, *unmapped_address); // log("\n. Successfully accessed."); - // log("\nMultiboot info passed to kernel from GRUB:\n"); - // print_multiboot_info(LOG, mbinfo); + log("\nMultiboot info passed to kernel from GRUB:\n"); + print_multiboot_info(LOG, mbinfo); // void_function_t start_program = first_module_as_a_function(mbinfo); // start_program(); // log("Got past call to start_program()\n"); - // // Loop forever - // // User input is accepted asynchronously via interrupts - // while(1){} + // Loop forever + // User input is accepted asynchronously via interrupts + while(1){} } \ No newline at end of file diff --git a/loader.h b/loader.h index 5865dd9..2eace00 100644 --- a/loader.h +++ b/loader.h @@ -1,6 +1,10 @@ #ifndef INCLUDE_LOADER_H #define INCLUDE_LOADER_H +#include "types.h" + +uint32_t KERNEL_VIRTUAL_BASE; + void * boot_pagedir; void * boot_pagetab1; diff --git a/loader.s b/loader.s index fe69c61..e0272d7 100644 --- a/loader.s +++ b/loader.s @@ -30,6 +30,7 @@ KERNEL_STACK_SIZE equ 4096 ; size of stack in bytes (1 kilobyte) ; addresses into physical addresses until paging is enabled. Note that this is not ; the virtual address where the kernel image itself is loaded -- just the amount that must ; be subtracted from a virtual address to get a physical address. +global KERNEL_VIRTUAL_BASE KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; Page directory index of kernel's 4MB PTE. @@ -95,6 +96,7 @@ StartInHigherHalf: mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the ; stack (end of memory area) + add ebx, KERNEL_VIRTUAL_BASE ; make the address virtual push ebx ; GRUB stores a pointer to a struct in the register ebx that, ; among other things, describes at which addresses the modules are loaded. ; Push ebx on the stack before calling kmain to make it an argument for kmain. diff --git a/multiboot_utils.c b/multiboot_utils.c index 652aa7f..0258ae1 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -1,13 +1,18 @@ #include "multiboot_utils.h" +#include "loader.h" + +uint32_t p_to_v(uint32_t physical_address) { + return physical_address + (uint32_t) &KERNEL_VIRTUAL_BASE; +} void print_module_info(FILE stream, struct module * m) { - fprintf(stream, (char*) m->string); + fprintf(stream, (char*) (p_to_v(m->string))); fprintf(stream, ":\n"); fprintf(stream, "mod_start: "); - print_uint32(stream, m->mod_start); + print_uint32(stream, p_to_v(m->mod_start)); fprintf(stream, "\n"); fprintf(stream, "mod_end: "); - print_uint32(stream, m->mod_end); + print_uint32(stream, p_to_v(m->mod_end)); fprintf(stream, "\n"); } @@ -17,10 +22,10 @@ void print_multiboot_info(FILE stream, multiboot_info_t* info) { fprintf(stream, "\n"); fprintf(stream, "mem_lower: "); - print_uint32(stream, info->mem_lower); + print_uint32(stream, p_to_v(info->mem_lower)); fprintf(stream, "\n"); fprintf(stream, "mem_upper: "); - print_uint32(stream, info->mem_upper); + print_uint32(stream, p_to_v(info->mem_upper)); fprintf(stream, "\n"); fprintf(stream, "boot_device: "); @@ -34,12 +39,12 @@ void print_multiboot_info(FILE stream, multiboot_info_t* info) { print_uint32(stream, info->mods_count); fprintf(stream, "\n"); fprintf(stream, "mods_addr: "); - print_uint32(stream, info->mods_addr); + print_uint32(stream, p_to_v(info->mods_addr)); fprintf(stream, "\n"); struct module * modules; if (info->mods_count > 0) { - modules = (struct module *) info->mods_addr; + modules = (struct module *) (p_to_v(info->mods_addr)); for (uint8_t i = 0; i < info->mods_count; i++) { fprintf(stream, "\n"); print_module_info(stream, &(modules[i])); From 4f825e9d74bf10828e23ecc0a014b354b5c459c8 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 15 Oct 2016 22:04:58 -0700 Subject: [PATCH 22/67] Access the page directory from C, change how we print it out. --- data_structures/page_table.c | 39 +++++++++----------------- data_structures/page_table.h | 3 +- kmain.c | 54 +++++++++++++----------------------- loader.h | 2 +- loader.s | 10 ++----- 5 files changed, 37 insertions(+), 71 deletions(-) diff --git a/data_structures/page_table.c b/data_structures/page_table.c index 04d1a97..d47ce45 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -55,32 +55,19 @@ uint32_t make_page_table_entry( // 1 page directory = 1024 page tables = 4 gB page_directory_t initialize_page_directory() { - page_directory_t pd = (page_directory_t) &boot_pagedir; - page_table_t pt = (page_table_t) &boot_pagetab1; - *pd = make_page_directory_entry( - (uint32_t) pt, - FOUR_KB, - false, - false, - SUPERVISOR, - READ_WRITE, - true - ); - for (int i = 0; i < 1024; i++) { - pt[i] = make_page_table_entry( - 4096*i, - false, - false, - false, - SUPERVISOR, - READ_WRITE, - true - ); - } + page_directory_t pd = (page_directory_t) &BootPageDirectory; return pd; } -page_table_t get_page_table(page_directory_t pd, int i) { - uint32_t entry = pd[i]; - return (page_table_t) (entry & 0xFFFFF000); -} \ No newline at end of file +void print_page_directory(FILE stream, page_directory_t pd) { + for (int i = 0; i < 1024; i++) { + uint32_t entry = pd[i]; + bool present = entry & 0x1; + + if (present) { + fprintf(stream, "page directory entry "); + print_uint32(stream, i); + fprintf(stream, " is present.\n"); + } + } +} diff --git a/data_structures/page_table.h b/data_structures/page_table.h index 95b64ac..9385f15 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -2,11 +2,12 @@ #define INCLUDE_PAGE_TABLE_H #include "../types.h" +#include "../stdio.h" typedef uint32_t * page_directory_t; typedef uint32_t * page_table_t; page_directory_t initialize_page_directory(); -page_table_t get_page_table(page_directory_t pd, int i); +void print_page_directory(FILE stream, page_directory_t pd); #endif /* INCLUDE_PAGE_TABLE_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index 6b5c8ec..79604c0 100644 --- a/kmain.c +++ b/kmain.c @@ -48,6 +48,10 @@ void kmain(uint32_t ebx) { serial_init(); log("\n--------------------\ncstackOS is booting!\n--------------------\n\nInitialized serial port.\n"); + log("\nMultiboot info passed to kernel from GRUB:\n"); + print_multiboot_info(LOG, mbinfo); + log("\n"); + initialize_gdt(); log("Loaded global descriptor table.\n"); @@ -61,44 +65,24 @@ void kmain(uint32_t ebx) { pic_init(); log("Initialized PIC\n"); - // page_directory_t pd = initialize_page_directory(); - // log("Initialized page directory.\n"); - // log("Address of page directory: "); - // print_uint32(LOG, (uint32_t) pd); - // log("\n"); - - // page_table_t pt = get_page_table(pd, 0); - // log("Address of first page table: "); - // print_uint32(LOG, (uint32_t) pt); - // log("\n"); - - // log("First 5 page table entries: "); - // for (int i = 0; i < 5; i++) { - // print_uint32(LOG, pt[i]); - // log("\n"); - // } + page_directory_t pd = initialize_page_directory(); + log("Initialized page directory.\n"); + log("Address of page directory: "); + print_uint32(LOG, (uint32_t) pd); + log("\n"); - // log("Setting page directory...\n"); - // set_page_directory(pd); - // log("Set page directory.\n"); + print_page_directory(LOG, pd); - // log("Enabling paging...\n"); - // enable_paging(); - // log("Paging enabled.\n"); - - // uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB - // log("Trying to access address "); - // print_uint32(LOG, (uint32_t) unmapped_address); - // log(":\n"); - // print_uint8(LOG, *unmapped_address); - // log("\n. Successfully accessed."); - - log("\nMultiboot info passed to kernel from GRUB:\n"); - print_multiboot_info(LOG, mbinfo); + uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB + log("Trying to access address "); + print_uint32(LOG, (uint32_t) unmapped_address); + log(":\n"); + print_uint8(LOG, *unmapped_address); + log("\n. Successfully accessed."); - // void_function_t start_program = first_module_as_a_function(mbinfo); - // start_program(); - // log("Got past call to start_program()\n"); + void_function_t start_program = first_module_as_a_function(mbinfo); + start_program(); + log("Got past call to start_program()\n"); // Loop forever // User input is accepted asynchronously via interrupts diff --git a/loader.h b/loader.h index 2eace00..09442e1 100644 --- a/loader.h +++ b/loader.h @@ -5,7 +5,7 @@ uint32_t KERNEL_VIRTUAL_BASE; -void * boot_pagedir; +void * BootPageDirectory; void * boot_pagetab1; #endif /* INCLUDE_LOADER_H */ \ No newline at end of file diff --git a/loader.s b/loader.s index e0272d7..5d44901 100644 --- a/loader.s +++ b/loader.s @@ -36,6 +36,7 @@ KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; Page directory index of ke section .data align 0x1000 +global BootPageDirectory BootPageDirectory: ; This page directory entry identity-maps the first 4MB of the 32-bit physical address space. ; All bits are clear except the following: @@ -104,15 +105,8 @@ StartInHigherHalf: call kmain ; use call rather than jmp so C function finds paramters in the correct place hlt ; should never get here. kmain should not return. -global boot_pagedir global boot_pagetab1 section .bss ; Use the 'bss' section for the stack align 4 ; align at 4 bytes for performance reasons kernel_stack: ; label points to beginning of memory - resb KERNEL_STACK_SIZE ; reserve stack for the kernel - - align 4096 - boot_pagedir: - resb 4096 - boot_pagetab1: - resb 4096 \ No newline at end of file + resb KERNEL_STACK_SIZE ; reserve stack for the kernel \ No newline at end of file From 664065531fa6d54ac90e989e47e5388b15135089 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 22 Oct 2016 12:26:11 -0700 Subject: [PATCH 23/67] Print primitive stack trace, and print parse ELF section header table. --- elf.h | 19 +++++++++++++++++++ interrupts.c | 10 ++++++++++ interrupts.h | 7 ------- kmain.c | 16 ++++++++++------ loader.s | 4 ++-- multiboot_utils.c | 44 ++++++++++++++++++++++++++++++++++++++------ 6 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 elf.h diff --git a/elf.h b/elf.h new file mode 100644 index 0000000..db4da05 --- /dev/null +++ b/elf.h @@ -0,0 +1,19 @@ +#ifndef INCLUDE_ELF_H +#define INCLUDE_ELF_H + +#include "types.h" + +struct elf_section_header_t { + uint32_t sh_name; + uint32_t attr1; + uint32_t attr2; + uint32_t sh_addr; + uint32_t attr4; + uint32_t sh_size; + uint32_t attr6; + uint32_t attr7; + uint32_t attr8; + uint32_t attr9; +}; + +#endif /* INCLUDE_ELF_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index b98e3fe..0153ac0 100644 --- a/interrupts.c +++ b/interrupts.c @@ -16,6 +16,16 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t log("\n"); } + log("Stack trace:\n"); + uint32_t ebp = cpu.ebp; + while (ebp & 0xC0100000) { + uint32_t eip = ((uint32_t*) ebp)[1]; + print_uint32(LOG, eip); + log("\n"); + + ebp = *((uint32_t*)ebp); + } + switch(interrupt_number) { case(INT_KEYBOARD): keyboard_interrupt_handler(); diff --git a/interrupts.h b/interrupts.h index 7f9f90d..42a548a 100644 --- a/interrupts.h +++ b/interrupts.h @@ -14,13 +14,6 @@ struct cpu_state { uint32_t eax; } __attribute__((packed)); -struct stack_state { - uint32_t error_code; - uint32_t eip; - uint32_t cs; - uint32_t eflags; -} __attribute__((packed)); - void enable_keyboard_interrupts(); void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code); diff --git a/kmain.c b/kmain.c index 79604c0..84bed02 100644 --- a/kmain.c +++ b/kmain.c @@ -37,6 +37,15 @@ static char *welcome_string = "" " " ""; +void bad_function() { + uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB + log("Trying to access address "); + print_uint32(LOG, (uint32_t) unmapped_address); + log(":\n"); + print_uint8(LOG, *unmapped_address); + log("\n. Successfully accessed."); +} + void kmain(uint32_t ebx) { // GRUB passes info to the kernel through the ebx register multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; @@ -73,12 +82,7 @@ void kmain(uint32_t ebx) { print_page_directory(LOG, pd); - uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB - log("Trying to access address "); - print_uint32(LOG, (uint32_t) unmapped_address); - log(":\n"); - print_uint8(LOG, *unmapped_address); - log("\n. Successfully accessed."); + bad_function(); void_function_t start_program = first_module_as_a_function(mbinfo); start_program(); diff --git a/loader.s b/loader.s index 5d44901..8edc1c3 100644 --- a/loader.s +++ b/loader.s @@ -91,8 +91,8 @@ _loader: StartInHigherHalf: ; Unmap the identity-mapped first 4MB of physical address space. It should not be needed ; anymore. - mov dword [BootPageDirectory], 0 - invlpg [0] + ; mov dword [BootPageDirectory], 0 + ; invlpg [0] mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the ; stack (end of memory area) diff --git a/multiboot_utils.c b/multiboot_utils.c index 0258ae1..452c6d4 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -1,5 +1,6 @@ #include "multiboot_utils.h" #include "loader.h" +#include "elf.h" uint32_t p_to_v(uint32_t physical_address) { return physical_address + (uint32_t) &KERNEL_VIRTUAL_BASE; @@ -8,23 +9,52 @@ uint32_t p_to_v(uint32_t physical_address) { void print_module_info(FILE stream, struct module * m) { fprintf(stream, (char*) (p_to_v(m->string))); fprintf(stream, ":\n"); - fprintf(stream, "mod_start: "); + fprintf(stream, "mod_start (virtual): "); print_uint32(stream, p_to_v(m->mod_start)); fprintf(stream, "\n"); - fprintf(stream, "mod_end: "); + fprintf(stream, "mod_end (virtual): "); print_uint32(stream, p_to_v(m->mod_end)); fprintf(stream, "\n"); } +void print_elf_section_header_table(FILE stream, elf_section_header_table_t table) { + fprintf(stream, "\nELF sections:\n"); + + uint32_t addr = p_to_v(table.addr); + uint32_t num = table.num; + uint32_t shndx = table.shndx; + + struct elf_section_header_t * section_header_table = (struct elf_section_header_t *) addr; + uint32_t string_table_start = section_header_table[shndx].sh_addr; + + for (uint32_t i = 0; i < num; i++) { + uint32_t sh_addr = section_header_table[i].sh_addr; + print_uint32(stream, sh_addr); + + fprintf(stream, " : "); + print_uint32(stream, section_header_table[i].sh_size); + + fprintf(stream, " : "); + uint32_t sh_name = section_header_table[i].sh_name; + if (sh_name != 0) { + char * name = (char*) (string_table_start + sh_name); + fprintf(stream, name); + } else { + fprintf(stream, "(NULL SECTION)"); + } + fprintf(stream, "\n"); + } +} + void print_multiboot_info(FILE stream, multiboot_info_t* info) { fprintf(stream, "flags: "); print_uint32(stream, info->flags); fprintf(stream, "\n"); - fprintf(stream, "mem_lower: "); + fprintf(stream, "mem_lower (virtual): "); print_uint32(stream, p_to_v(info->mem_lower)); fprintf(stream, "\n"); - fprintf(stream, "mem_upper: "); + fprintf(stream, "mem_upper (virtual): "); print_uint32(stream, p_to_v(info->mem_upper)); fprintf(stream, "\n"); @@ -38,18 +68,20 @@ void print_multiboot_info(FILE stream, multiboot_info_t* info) { fprintf(stream, "mods_count: "); print_uint32(stream, info->mods_count); fprintf(stream, "\n"); - fprintf(stream, "mods_addr: "); + fprintf(stream, "mods_addr (virtual): "); print_uint32(stream, p_to_v(info->mods_addr)); fprintf(stream, "\n"); + fprintf(stream, "\nGRUB modules: \n"); struct module * modules; if (info->mods_count > 0) { modules = (struct module *) (p_to_v(info->mods_addr)); for (uint8_t i = 0; i < info->mods_count; i++) { - fprintf(stream, "\n"); print_module_info(stream, &(modules[i])); } } + + print_elf_section_header_table(stream, info->u.elf_sec); } void_function_t first_module_as_a_function(multiboot_info_t* info) { From df4977f7258861d9f9335788cb8792355de9feee Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 22 Oct 2016 17:03:03 -0700 Subject: [PATCH 24/67] Add simple stack trace to interrupt handler. --- Makefile | 4 ++- data_structures/symbol_table.c | 50 ++++++++++++++++++++++++++++++++++ data_structures/symbol_table.h | 12 ++++++++ elf.h | 9 ++++++ interrupts.c | 31 +++++++++++++++------ interrupts.h | 2 +- kmain.c | 7 +++++ loader.s | 6 ++-- multiboot_utils.c | 28 ++++++++++++++++++- multiboot_utils.h | 3 +- string.c | 23 ++++++++++++++++ string.h | 6 ++++ 12 files changed, 165 insertions(+), 16 deletions(-) create mode 100644 data_structures/symbol_table.c create mode 100644 data_structures/symbol_table.h create mode 100644 string.c create mode 100644 string.h diff --git a/Makefile b/Makefile index 2b089a8..41d90b0 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ assembly_interface.o \ data_structures/global_descriptor_table.o \ data_structures/interrupt_descriptor_table.o \ data_structures/page_table.o \ +data_structures/symbol_table.o \ drivers/frame_buffer.o \ drivers/keyboard.o \ drivers/pic.o \ @@ -31,7 +32,8 @@ drivers/serial_port.o \ interrupts.o \ kmain.o \ multiboot_utils.o \ -stdio.o +stdio.o \ +string.o all: os.iso diff --git a/data_structures/symbol_table.c b/data_structures/symbol_table.c new file mode 100644 index 0000000..c1c51d6 --- /dev/null +++ b/data_structures/symbol_table.c @@ -0,0 +1,50 @@ +#include "symbol_table.h" +#include "../multiboot_utils.h" + +#include "../stdio.h" + +struct symbol_table_descriptor_t { + bool present; + uint32_t num_symbols; + Elf32_Sym * symbols; + char * string_table_addr; +}; + +struct symbol_table_descriptor_t symbol_table_descriptor; + +bool load_symbol_table(struct elf_section_header_t * symbol_table_section, struct elf_section_header_t * string_table_section) { + if (symbol_table_section == 0) { + symbol_table_descriptor.present = false; + return false; + } else { + symbol_table_descriptor.present = true; + symbol_table_descriptor.num_symbols = symbol_table_section->sh_size / sizeof(Elf32_Sym); + symbol_table_descriptor.symbols = (Elf32_Sym *) symbol_table_section->sh_addr; + symbol_table_descriptor.string_table_addr = (char*) string_table_section->sh_addr; + return true; + } +} + +char * address_to_symbol_name(uint32_t address) { + // Algorithm : Find symbol with greatest value <= address + + Elf32_Sym * symbol = 0; + uint32_t symbol_value = 0; + + if (symbol_table_descriptor.present) { + for (uint32_t i = 0; i < symbol_table_descriptor.num_symbols; i++) { + Elf32_Sym * candidate = symbol_table_descriptor.symbols + i; + if (candidate->st_value > symbol_value && candidate->st_value <= address) { + symbol = candidate; + symbol_value = candidate->st_value; + } + } + + uint32_t string_index = symbol->st_name; + char * name = symbol_table_descriptor.string_table_addr + string_index; + + return name; + } + + return 0; +} \ No newline at end of file diff --git a/data_structures/symbol_table.h b/data_structures/symbol_table.h new file mode 100644 index 0000000..a82904d --- /dev/null +++ b/data_structures/symbol_table.h @@ -0,0 +1,12 @@ +#ifndef INCLUDE_SYMBOL_TABLE_H +#define INCLUDE_SYMBOL_TABLE_H + +#include "../types.h" +#include "../elf.h" + +struct symbol_table_descriptor_t; + +bool load_symbol_table(struct elf_section_header_t * symbol_table_section, struct elf_section_header_t * string_table_section); +char * address_to_symbol_name(uint32_t address); + +#endif /* INCLUDE_SYMBOL_TABLE_H */ \ No newline at end of file diff --git a/elf.h b/elf.h index db4da05..5c75b5d 100644 --- a/elf.h +++ b/elf.h @@ -16,4 +16,13 @@ struct elf_section_header_t { uint32_t attr9; }; +typedef struct { + uint32_t st_name; + uint32_t st_value; + uint32_t st_size; + uint8_t st_info; + uint8_t st_other; + uint16_t st_shndx; +} Elf32_Sym; + #endif /* INCLUDE_ELF_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index 0153ac0..bb7ca97 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include "assembly_interface.h" +#include "data_structures/symbol_table.h" #include "drivers/keyboard.h" #include "drivers/pic.h" #include "stdio.h" @@ -9,29 +10,41 @@ #define INT_GENERAL_PROTECTION_FAULT 0x0000000D #define INT_PAGE_FAULT 0x0000000E -void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code) { - if (error_code) { - log("interrupt_handler() error_code "); - print_uint32(LOG, error_code); - log("\n"); - } +void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip) { + log("\n!!! Interrupt\n"); + log("interrupt_number: "); + print_uint32(LOG, interrupt_number); + log("\n"); + + log("error_code: "); + print_uint32(LOG, error_code); + log("\n"); - log("Stack trace:\n"); + log("\nStack trace:\n"); + print_uint32(LOG, eip); + log(" : "); + char * symbol_name = address_to_symbol_name(eip); + fprintf(LOG, symbol_name); + log("\n"); uint32_t ebp = cpu.ebp; while (ebp & 0xC0100000) { uint32_t eip = ((uint32_t*) ebp)[1]; print_uint32(LOG, eip); + log(" : "); + char * symbol_name = address_to_symbol_name(eip); + fprintf(LOG, symbol_name); log("\n"); ebp = *((uint32_t*)ebp); } + log("\n"); switch(interrupt_number) { case(INT_KEYBOARD): keyboard_interrupt_handler(); break; case(INT_PAGE_FAULT): - log("\nPage fault! Here's what I know:\n"); + log("Interrupt was a page fault. Here's what I know:\n"); log("- Tried to access linear address "); print_uint32(LOG, cpu.cr2); log("\n"); @@ -60,7 +73,7 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t break; default: - log("Unhandled Interrupt: "); + log("ERROR: Unabled to handle interrupt: "); print_uint32(LOG, interrupt_number); log("\n"); break; diff --git a/interrupts.h b/interrupts.h index 42a548a..5492da4 100644 --- a/interrupts.h +++ b/interrupts.h @@ -15,6 +15,6 @@ struct cpu_state { } __attribute__((packed)); void enable_keyboard_interrupts(); -void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code); +void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip); #endif /* INCLUDE_INTERRUPTS_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index 84bed02..52ab51c 100644 --- a/kmain.c +++ b/kmain.c @@ -2,6 +2,7 @@ #include "data_structures/global_descriptor_table.h" #include "data_structures/interrupt_descriptor_table.h" #include "data_structures/page_table.h" +#include "data_structures/symbol_table.h" #include "drivers/frame_buffer.h" #include "drivers/pic.h" #include "drivers/serial_port.h" @@ -61,6 +62,12 @@ void kmain(uint32_t ebx) { print_multiboot_info(LOG, mbinfo); log("\n"); + if (load_symbol_table(get_elf_section(mbinfo, ".symtab"), get_elf_section(mbinfo, ".strtab"))) { + log("Initialized symbol table.\n"); + } else { + log("ERROR: Could not initialize symbol table.\n"); + } + initialize_gdt(); log("Loaded global descriptor table.\n"); diff --git a/loader.s b/loader.s index 8edc1c3..f8260b8 100644 --- a/loader.s +++ b/loader.s @@ -83,12 +83,12 @@ _loader: ; Start fetching instructions in kernel space. ; Since eip at this point holds the physical address of this command (approximately 0x00100000) - ; we need to do a long jump to the correct virtual address of StartInHigherHalf which is + ; we need to do a long jump to the correct virtual address of higher_half_loader which is ; approximately 0xC0100000. - lea ecx, [StartInHigherHalf] + lea ecx, [higher_half_loader] jmp ecx -StartInHigherHalf: +higher_half_loader: ; Unmap the identity-mapped first 4MB of physical address space. It should not be needed ; anymore. ; mov dword [BootPageDirectory], 0 diff --git a/multiboot_utils.c b/multiboot_utils.c index 452c6d4..1cbf27b 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -1,6 +1,7 @@ #include "multiboot_utils.h" -#include "loader.h" #include "elf.h" +#include "loader.h" +#include "string.h" uint32_t p_to_v(uint32_t physical_address) { return physical_address + (uint32_t) &KERNEL_VIRTUAL_BASE; @@ -17,6 +18,31 @@ void print_module_info(FILE stream, struct module * m) { fprintf(stream, "\n"); } +struct elf_section_header_t * get_elf_section(multiboot_info_t* info, char * section_name) { + elf_section_header_table_t section_table = info->u.elf_sec; + + uint32_t addr = p_to_v(section_table.addr); + uint32_t num_sections = section_table.num; + uint32_t shndx = section_table.shndx; + + struct elf_section_header_t * section_header_table = (struct elf_section_header_t *) addr; + uint32_t string_table_start = section_header_table[shndx].sh_addr; + + for (uint32_t i = 0; i < num_sections; i++) { + uint32_t sh_name = section_header_table[i].sh_name; + if (sh_name != 0) { + char * name = (char*) (string_table_start + sh_name); + int diff = strcmp(name, section_name); + if (diff == 0) { + return section_header_table + i; + } + } + } + + return 0; +} + + void print_elf_section_header_table(FILE stream, elf_section_header_table_t table) { fprintf(stream, "\nELF sections:\n"); diff --git a/multiboot_utils.h b/multiboot_utils.h index 6895892..8c36da1 100644 --- a/multiboot_utils.h +++ b/multiboot_utils.h @@ -5,7 +5,8 @@ #include "stdio.h" #include "types.h" -void print_multiboot_info(FILE stream, multiboot_info_t* info); void_function_t first_module_as_a_function(multiboot_info_t* info); +struct elf_section_header_t * get_elf_section(multiboot_info_t* info, char * section_name); +void print_multiboot_info(FILE stream, multiboot_info_t* info); #endif diff --git a/string.c b/string.c new file mode 100644 index 0000000..e7f6a47 --- /dev/null +++ b/string.c @@ -0,0 +1,23 @@ +#include "string.h" + +/* +Returns an integral value indicating the relationship between the strings: +return value indicates +<0 the first character that does not match has a lower value in ptr1 than in ptr2 +0 the contents of both strings are equal +>0 the first character that does not match has a greater value in ptr1 than in ptr2 +*/ +int strcmp(const char * str1, const char * str2) { + while (*str1 != 0 && *str2 != 0) { + int diff = *str1 - *str2; + if (diff != 0) { + return diff; + } + + str1++; + str2++; + } + + // One of these points to 0 + return *str1 - *str2; +} \ No newline at end of file diff --git a/string.h b/string.h new file mode 100644 index 0000000..94775ca --- /dev/null +++ b/string.h @@ -0,0 +1,6 @@ +#ifndef STRING_H +#define STRING_H + +int strcmp (const char * str1, const char * str2); + +#endif /* STRING_H */ \ No newline at end of file From 222f1b0b06aaf63a65fa29fc6fc8c05e1b56fcbb Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 23 Oct 2016 15:54:49 -0700 Subject: [PATCH 25/67] Start page allocator. --- Makefile | 1 + kmain.c | 8 +++++++- link.ld | 6 ++++++ loader.s | 10 ++++++++++ multiboot.h | 6 +++++- multiboot_utils.c | 40 ++++++++++++++++++++++++++++++++++++---- page_allocator.c | 27 +++++++++++++++++++++++++++ page_allocator.h | 24 ++++++++++++++++++++++++ 8 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 page_allocator.c create mode 100644 page_allocator.h diff --git a/Makefile b/Makefile index 41d90b0..621dfc5 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ drivers/serial_port.o \ interrupts.o \ kmain.o \ multiboot_utils.o \ +page_allocator.o \ stdio.o \ string.o diff --git a/kmain.c b/kmain.c index 52ab51c..f704f9c 100644 --- a/kmain.c +++ b/kmain.c @@ -7,6 +7,7 @@ #include "drivers/pic.h" #include "drivers/serial_port.h" #include "multiboot_utils.h" +#include "page_allocator.h" #include "stdio.h" #include "types.h" @@ -47,7 +48,7 @@ void bad_function() { log("\n. Successfully accessed."); } -void kmain(uint32_t ebx) { +void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { // GRUB passes info to the kernel through the ebx register multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; @@ -89,6 +90,11 @@ void kmain(uint32_t ebx) { print_page_directory(LOG, pd); + uint32_t unallocated_bytes = initialize_page_allocator(kernel_memory, mbinfo); + log("Initialized page allocator.\n"); + print_uint32(LOG, unallocated_bytes); + log(" bytes unallocated\n"); + bad_function(); void_function_t start_program = first_module_as_a_function(mbinfo); diff --git a/link.ld b/link.ld index 233dc0f..bc3e119 100644 --- a/link.ld +++ b/link.ld @@ -12,6 +12,9 @@ ENTRY(loader) /* the name of the entry label */ SECTIONS { . = 0xC0100000; /* the code should be linked as though it were loaded at 3GB + 1MB. In actuality, it will be loaded at physical address 1MB, then we will map virtual addresses above 3GB to physical address starting at 0 */ + kernel_virtual_start = .; + kernel_physical_start = . - 0xC0000000; + .text ALIGN (0x1000) : AT(ADDR(.text)-0xC0000000) /* align at 4 KB, the size of a page */ { *(.text) /* all text sections from all files */ @@ -32,4 +35,7 @@ SECTIONS { *(COMMON) /* all COMMON sections from all files */ *(.bss) /* all bss sections from all files */ } + + kernel_virtual_end = .; + kernel_physical_end = . - 0xC0000000; } \ No newline at end of file diff --git a/loader.s b/loader.s index f8260b8..7489a71 100644 --- a/loader.s +++ b/loader.s @@ -6,6 +6,11 @@ global loader ; the entry symbol for ELF extern kmain ; the starting point in our C code +extern kernel_virtual_start +extern kernel_virtual_end +extern kernel_physical_start +extern kernel_physical_end + MAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant ; 'equ' is a pseduo-instruction which does not @@ -102,6 +107,11 @@ higher_half_loader: ; among other things, describes at which addresses the modules are loaded. ; Push ebx on the stack before calling kmain to make it an argument for kmain. + push kernel_physical_end + push kernel_physical_start + push kernel_virtual_end + push kernel_virtual_start + call kmain ; use call rather than jmp so C function finds paramters in the correct place hlt ; should never get here. kmain should not return. diff --git a/multiboot.h b/multiboot.h index 8ec8a24..bf9fed9 100644 --- a/multiboot.h +++ b/multiboot.h @@ -1,3 +1,5 @@ +#ifndef MULTIBOOT_H +#define MULTIBOOT_H // The following was copied from https://www.gnu.org/software/grub/manual/multiboot/html_node/multiboot.h.html /* multiboot.h - the header for Multiboot */ @@ -118,4 +120,6 @@ typedef struct memory_map unsigned long type; } memory_map_t; -#endif /* ! ASM */ \ No newline at end of file +#endif /* ! ASM */ + +#endif /* MULTIBOOT_H */ \ No newline at end of file diff --git a/multiboot_utils.c b/multiboot_utils.c index 1cbf27b..36dcde9 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -72,16 +72,46 @@ void print_elf_section_header_table(FILE stream, elf_section_header_table_t tabl } } +void print_memory_map(FILE stream, multiboot_info_t* info) { + fprintf(stream, "\nmemory map:\n"); + memory_map_t * memory_map = (memory_map_t *) info->mmap_addr; + uint32_t num_entries = info->mmap_length / sizeof(memory_map_t); + + for (uint32_t i = 0; i < num_entries; i++) { + fprintf(stream, "base_addr_low: "); + print_uint32(stream, memory_map[i].base_addr_low); + fprintf(stream, "\n"); + + fprintf(stream, "base_addr_high: "); + print_uint32(stream, memory_map[i].base_addr_high); + fprintf(stream, "\n"); + + fprintf(stream, "length_low: "); + print_uint32(stream, memory_map[i].length_low); + fprintf(stream, "\n"); + + fprintf(stream, "length_high: "); + print_uint32(stream, memory_map[i].length_high); + fprintf(stream, "\n"); + + fprintf(stream, "type: "); + print_uint32(stream, memory_map[i].type); + fprintf(stream, "\n"); + + fprintf(stream, "\n"); + } +} + void print_multiboot_info(FILE stream, multiboot_info_t* info) { fprintf(stream, "flags: "); print_uint32(stream, info->flags); fprintf(stream, "\n"); - fprintf(stream, "mem_lower (virtual): "); - print_uint32(stream, p_to_v(info->mem_lower)); + fprintf(stream, "mem_lower (kilobytes): "); + print_uint32(stream, info->mem_lower); fprintf(stream, "\n"); - fprintf(stream, "mem_upper (virtual): "); - print_uint32(stream, p_to_v(info->mem_upper)); + fprintf(stream, "mem_upper (kilobytes): "); + print_uint32(stream, info->mem_upper); fprintf(stream, "\n"); fprintf(stream, "boot_device: "); @@ -108,6 +138,8 @@ void print_multiboot_info(FILE stream, multiboot_info_t* info) { } print_elf_section_header_table(stream, info->u.elf_sec); + + print_memory_map(stream, info); } void_function_t first_module_as_a_function(multiboot_info_t* info) { diff --git a/page_allocator.c b/page_allocator.c new file mode 100644 index 0000000..921e683 --- /dev/null +++ b/page_allocator.c @@ -0,0 +1,27 @@ +#include "page_allocator.h" + +struct memory_stats_t memory_stats; + +uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo) { + if(kernel_memory.kernel_virtual_start){} + if(mbinfo){} + + memory_stats.unallocated_bytes = 0; + memory_stats.allocated_bytes = 0; + memory_stats.unavailable_bytes = 0; + + memory_map_t * memory_map = (memory_map_t *) mbinfo->mmap_addr; + uint32_t num_entries = mbinfo->mmap_length / sizeof(memory_map_t); + + for (uint32_t i = 0; i < num_entries; i++) { + if (memory_map[i].type == 1) { + // Available + memory_stats.unallocated_bytes += memory_map[i].length_low; + } else { + // Unavailable + memory_stats.unavailable_bytes += memory_map[i].length_low; + } + } + + return memory_stats.unallocated_bytes; +} \ No newline at end of file diff --git a/page_allocator.h b/page_allocator.h new file mode 100644 index 0000000..4bf923f --- /dev/null +++ b/page_allocator.h @@ -0,0 +1,24 @@ +#ifndef PAGE_ALLOCATOR_H +#define PAGE_ALLOCATOR_H + +#include "types.h" +#include "multiboot.h" + +struct kernel_memory_descriptor_t { + uint32_t kernel_virtual_start; + uint32_t kernel_virtual_end; + uint32_t kernel_physical_start; + uint32_t kernel_physical_end; +}; + +struct memory_stats_t +{ + uint32_t unallocated_bytes; + uint32_t allocated_bytes; + uint32_t unavailable_bytes; +}; + +bool allocate_page(uint32_t virtual_address); +uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); + +#endif /* PAGE_ALLOCATOR_H */ \ No newline at end of file From 225a154fe569fc9fc2d116be3f85e9c2966849d2 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Thu, 27 Oct 2016 23:41:37 -0700 Subject: [PATCH 26/67] Create bitmap of free pages. --- kmain.c | 8 +++-- page_allocator.c | 77 +++++++++++++++++++++++++++++++++++++++++++----- page_allocator.h | 7 ----- 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/kmain.c b/kmain.c index f704f9c..52adb96 100644 --- a/kmain.c +++ b/kmain.c @@ -90,10 +90,12 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_page_directory(LOG, pd); - uint32_t unallocated_bytes = initialize_page_allocator(kernel_memory, mbinfo); + uint32_t free_pages = initialize_page_allocator(kernel_memory, mbinfo); log("Initialized page allocator.\n"); - print_uint32(LOG, unallocated_bytes); - log(" bytes unallocated\n"); + print_uint32(LOG, free_pages); + log(" free pages ("); + print_uint32(LOG, free_pages / 256); + log(" MB)\n"); bad_function(); diff --git a/page_allocator.c b/page_allocator.c index 921e683..c00748c 100644 --- a/page_allocator.c +++ b/page_allocator.c @@ -1,27 +1,88 @@ #include "page_allocator.h" -struct memory_stats_t memory_stats; +#include "stdio.h" + +uint32_t free_pages; + +// 2^32 address space +// 2^12 page size +// 2^20 pages +// 2^17 bytes in bitmap +// 2^15 uint32_t's = 32768 + +// #define BITMAP_SIZE 32768 +// Enough room for 515 MB of RAM +// TODO: Find a more efficient way to initialize page allocator +#define BITMAP_SIZE 4096 +uint32_t free_page_bitmap[BITMAP_SIZE]; + +uint32_t round_up_to_nearest_page_start(uint32_t address) { + if ((address & 0xFFF) != 0) { + address &= 0xFFFFF000; + address += 0x00001000; + } + return address; +} + +uint32_t round_down_to_nearest_page_start(uint32_t address) { + if ((address & 0xFFF) != 0) { + address &= 0xFFFFF000; + address -= 0x00001000; + } + return address; +} + +uint32_t page_number(uint32_t address) { + return address >> 12; +} + +void mark_free(uint32_t page_number) { + uint32_t index = page_number >> 5; + uint32_t bit = page_number & 0b11111; + uint32_t value = free_page_bitmap[index]; + value |= (1 << bit); + free_page_bitmap[index] = value; + free_pages++; +} + +void mark_unavailable(uint32_t page_number) { + uint32_t index = page_number >> 5; + uint32_t bit = page_number & 0b11111; + uint32_t value = free_page_bitmap[index]; + value &= ~(1 << bit); + free_page_bitmap[index] = value; + free_pages--; +} uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo) { if(kernel_memory.kernel_virtual_start){} if(mbinfo){} - memory_stats.unallocated_bytes = 0; - memory_stats.allocated_bytes = 0; - memory_stats.unavailable_bytes = 0; - memory_map_t * memory_map = (memory_map_t *) mbinfo->mmap_addr; uint32_t num_entries = mbinfo->mmap_length / sizeof(memory_map_t); for (uint32_t i = 0; i < num_entries; i++) { if (memory_map[i].type == 1) { // Available - memory_stats.unallocated_bytes += memory_map[i].length_low; + uint32_t first_addr = memory_map[i].base_addr_low; + uint32_t one_past_last_addr = first_addr + memory_map[i].length_low; + uint32_t first_full_page = page_number(round_up_to_nearest_page_start(first_addr)); + uint32_t one_past_last_full_page = page_number(round_down_to_nearest_page_start(one_past_last_addr)); + + for(uint32_t i = first_full_page; i < one_past_last_full_page; i++) { + mark_free(i); + } } else { // Unavailable - memory_stats.unavailable_bytes += memory_map[i].length_low; } } - return memory_stats.unallocated_bytes; + uint32_t first_partial_page = page_number(round_down_to_nearest_page_start(kernel_memory.kernel_physical_start)); + uint32_t one_past_last_partial_page = page_number(round_up_to_nearest_page_start(kernel_memory.kernel_physical_end)); + + for(uint32_t i = first_partial_page; i < one_past_last_partial_page; i++) { + mark_unavailable(i); + } + + return free_pages; } \ No newline at end of file diff --git a/page_allocator.h b/page_allocator.h index 4bf923f..d0f8e07 100644 --- a/page_allocator.h +++ b/page_allocator.h @@ -11,13 +11,6 @@ struct kernel_memory_descriptor_t { uint32_t kernel_physical_end; }; -struct memory_stats_t -{ - uint32_t unallocated_bytes; - uint32_t allocated_bytes; - uint32_t unavailable_bytes; -}; - bool allocate_page(uint32_t virtual_address); uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); From e665c4352299f2580a1135812e313e19c17a9f71 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 30 Oct 2016 16:01:22 -0700 Subject: [PATCH 27/67] Set up recursive page table. --- Makefile | 1 - data_structures/page_table.c | 189 +++++++++++++++++++++++++++++++-- data_structures/page_table.h | 13 ++- data_structures/symbol_table.c | 7 +- kmain.c | 23 ++-- loader.h | 4 +- loader.s | 13 +-- multiboot_utils.c | 6 +- multiboot_utils.h | 1 + page_allocator.c | 88 --------------- page_allocator.h | 17 --- 11 files changed, 220 insertions(+), 142 deletions(-) delete mode 100644 page_allocator.c delete mode 100644 page_allocator.h diff --git a/Makefile b/Makefile index 621dfc5..41d90b0 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,6 @@ drivers/serial_port.o \ interrupts.o \ kmain.o \ multiboot_utils.o \ -page_allocator.o \ stdio.o \ string.o diff --git a/data_structures/page_table.c b/data_structures/page_table.c index d47ce45..eeb2806 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -1,17 +1,34 @@ #include "page_table.h" #include "../loader.h" +#include "../multiboot_utils.h" +#define PAGE_DIRECTORY_OFFSET_BITS 10 +#define PAGE_TABLE_OFFSET_BITS 10 +#define PAGE_OFFSET_BITS 12 + +#define PAGE_SIZE_BYTES 4096 +#define PAGE_SIZE_DWORDS 1024 + +#define KERNEL_PAGE_TABLE_NUMBER 768 + +// #define BITMAP_SIZE 32768 +// Enough room for 512 MB of RAM +// TODO: Find a more efficient way to initialize page allocator +#define BITMAP_SIZE 4096 + +uint32_t free_pages; +uint32_t free_page_bitmap[BITMAP_SIZE]; + +void mark_free(uint32_t page_number); +void mark_unavailable(uint32_t page_number); +uint32_t page_number(uint32_t address); enum page_size_t {FOUR_KB, FOUR_MB}; enum page_privilege_t {SUPERVISOR, USER}; enum page_permissions_t {READ_ONLY, READ_WRITE}; -struct page_directory_entry_t { - uint32_t page_table_address; -} __attribute__((packed)); - uint32_t make_page_directory_entry( - uint32_t page_table_address, + void* page_table_physical_address, enum page_size_t page_size, bool cache_disabled, bool write_through, @@ -19,7 +36,7 @@ uint32_t make_page_directory_entry( enum page_permissions_t permissions, bool present ) { - uint32_t entry = page_table_address; + uint32_t entry = (uint32_t) page_table_physical_address; entry |= page_size << 7; entry |= cache_disabled << 4; entry |= write_through << 3; @@ -31,7 +48,7 @@ uint32_t make_page_directory_entry( } uint32_t make_page_table_entry( - uint32_t page_frame_address, + void* page_frame_address, bool global, bool cache_disabled, bool write_through, @@ -39,7 +56,7 @@ uint32_t make_page_table_entry( enum page_permissions_t permissions, bool present ) { - uint32_t entry = page_frame_address; + uint32_t entry = (uint32_t) page_frame_address; entry |= global << 8; entry |= cache_disabled << 6; entry |= write_through << 3; @@ -54,8 +71,83 @@ uint32_t make_page_table_entry( // 1 page table = 1024 pages = 4 mB // 1 page directory = 1024 page tables = 4 gB +// Find a free physical page and return it's physical address +// This does NOT zero out the page +void* allocate_physical_page() { + for (uint32_t index = 0; index < BITMAP_SIZE; index++) { + if (free_page_bitmap[index] != 0) { + // There is at least one free page in this chunk + for (uint8_t bit = 0; bit < 32; bit++) { + if ((free_page_bitmap[index] & (1 << bit)) != 0) { + uint32_t page_number = index * 32 + bit; + mark_unavailable(page_number); + void* page_start = (void*) (page_number << PAGE_OFFSET_BITS); + return page_start; + } + } + } + } + + // Out of physical memory + // TODO: Evict a page + return 0; +} + +// Assumes we are using recursive page tables. +// Last entry in page directory points to itself +void* page_table_virtual_address(uint16_t page_table_number) { + // First 10 bits are set to 1 + uint32_t virtual_address = 0xFFC00000; + + // Next 10 bits index index into page directory + virtual_address |= (page_table_number << PAGE_OFFSET_BITS); + + return (void*) virtual_address; +} + page_directory_t initialize_page_directory() { - page_directory_t pd = (page_directory_t) &BootPageDirectory; + page_directory_t pd = (page_directory_t) &PageDirectoryVirtualAddress; + + // Make the last entry in the pd a pointer to itself + uint32_t pde = make_page_directory_entry( + (void*) &PageDirectoryPhysicalAddress, + FOUR_KB, + false, + false, + SUPERVISOR, + READ_WRITE, + true + ); + pd[1023] = pde; + + // dedicate one page table for memory for the kernel + void* page_table_physical_address = allocate_physical_page(); + pd[KERNEL_PAGE_TABLE_NUMBER] = make_page_directory_entry( + page_table_physical_address, + FOUR_KB, + false, + false, + SUPERVISOR, + READ_WRITE, + true + ); + + // From here on out, we can access page tables with `page_table_virtual_address()` + // Fill in the kernel page table entirely. + page_table_t pt = (page_table_t) page_table_virtual_address(KERNEL_PAGE_TABLE_NUMBER); + for (uint16_t i = 0; i < 1024; i++) { + void* page_physical_address = allocate_physical_page(); + pt[i] = make_page_table_entry( + page_physical_address, + false, + false, + false, + SUPERVISOR, + READ_WRITE, + true + ); + } + return pd; } @@ -71,3 +163,82 @@ void print_page_directory(FILE stream, page_directory_t pd) { } } } + +uint32_t round_up_to_nearest_page_start(uint32_t address) { + if ((address & 0xFFFFF000) != address) { + address &= 0xFFFFF000; + address += 0x00001000; + } + + return address; +} + +uint32_t round_down_to_nearest_page_start(uint32_t address) { + return address & 0xFFFFF000; +} + +uint32_t page_number(uint32_t address) { + return address >> PAGE_OFFSET_BITS; +} + +void mark_free(uint32_t page_number) { + uint32_t index = page_number >> 5; + uint32_t bit = page_number & 0b11111; + uint32_t value = free_page_bitmap[index]; + + if ((value & (1 << bit)) == 0) { + // Page was not free before. Update statistics. + free_pages++; + } + + value |= (1 << bit); + free_page_bitmap[index] = value; +} + +void mark_unavailable(uint32_t physical_page_number) { + uint32_t index = physical_page_number >> 5; + uint32_t bit = physical_page_number & 0b11111; + + uint32_t value = free_page_bitmap[index]; + + if ((value & (1 << bit)) == 1) { + // Page was free. Update statistics. + free_pages--; + } + + value &= ~(1 << bit); + free_page_bitmap[index] = value; +} + +uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo) { + memory_map_t * memory_map = (memory_map_t *) p_to_v(mbinfo->mmap_addr); + uint32_t num_entries = mbinfo->mmap_length / sizeof(memory_map_t); + + // Mark physical pages as free according to memory map passed by GRUB + for (uint32_t i = 0; i < num_entries; i++) { + if (memory_map[i].type == 1) { + // Available + uint32_t first_addr = memory_map[i].base_addr_low; + uint32_t one_past_last_addr = first_addr + memory_map[i].length_low; + uint32_t first_full_page = page_number(round_up_to_nearest_page_start(first_addr)); + uint32_t one_past_last_full_page = page_number(round_down_to_nearest_page_start(one_past_last_addr)); + + for(uint32_t i = first_full_page; i < one_past_last_full_page; i++) { + mark_free(i); + } + } else { + // Unavailable + // Not currently keeping track of these regions + } + } + + // Mark physical pages as unavailable where kernel code is loaded + uint32_t first_partial_page = page_number(round_down_to_nearest_page_start(kernel_memory.kernel_physical_start)); + uint32_t one_past_last_partial_page = page_number(round_up_to_nearest_page_start(kernel_memory.kernel_physical_end)); + + for(uint32_t i = first_partial_page; i < one_past_last_partial_page; i++) { + mark_unavailable(i); + } + + return free_pages; +} diff --git a/data_structures/page_table.h b/data_structures/page_table.h index 9385f15..54ba6a7 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -1,8 +1,19 @@ #ifndef INCLUDE_PAGE_TABLE_H #define INCLUDE_PAGE_TABLE_H -#include "../types.h" +#include "../multiboot.h" #include "../stdio.h" +#include "../types.h" + + +struct kernel_memory_descriptor_t { + uint32_t kernel_virtual_start; + uint32_t kernel_virtual_end; + uint32_t kernel_physical_start; + uint32_t kernel_physical_end; +}; + +uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); typedef uint32_t * page_directory_t; typedef uint32_t * page_table_t; diff --git a/data_structures/symbol_table.c b/data_structures/symbol_table.c index c1c51d6..ed79f8c 100644 --- a/data_structures/symbol_table.c +++ b/data_structures/symbol_table.c @@ -1,6 +1,7 @@ #include "symbol_table.h" -#include "../multiboot_utils.h" +#include "../loader.h" +#include "../multiboot_utils.h" #include "../stdio.h" struct symbol_table_descriptor_t { @@ -19,8 +20,8 @@ bool load_symbol_table(struct elf_section_header_t * symbol_table_section, struc } else { symbol_table_descriptor.present = true; symbol_table_descriptor.num_symbols = symbol_table_section->sh_size / sizeof(Elf32_Sym); - symbol_table_descriptor.symbols = (Elf32_Sym *) symbol_table_section->sh_addr; - symbol_table_descriptor.string_table_addr = (char*) string_table_section->sh_addr; + symbol_table_descriptor.symbols = (Elf32_Sym *) p_to_v(symbol_table_section->sh_addr); + symbol_table_descriptor.string_table_addr = (char*) p_to_v(string_table_section->sh_addr); return true; } } diff --git a/kmain.c b/kmain.c index 52adb96..2e2d089 100644 --- a/kmain.c +++ b/kmain.c @@ -7,7 +7,6 @@ #include "drivers/pic.h" #include "drivers/serial_port.h" #include "multiboot_utils.h" -#include "page_allocator.h" #include "stdio.h" #include "types.h" @@ -82,6 +81,13 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { pic_init(); log("Initialized PIC\n"); + uint32_t free_pages = initialize_page_allocator(kernel_memory, mbinfo); + log("Initialized page allocator.\n"); + print_uint32(LOG, free_pages); + log(" free pages ("); + print_uint32(LOG, free_pages / 256); + log(" MB)\n"); + page_directory_t pd = initialize_page_directory(); log("Initialized page directory.\n"); log("Address of page directory: "); @@ -90,18 +96,11 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_page_directory(LOG, pd); - uint32_t free_pages = initialize_page_allocator(kernel_memory, mbinfo); - log("Initialized page allocator.\n"); - print_uint32(LOG, free_pages); - log(" free pages ("); - print_uint32(LOG, free_pages / 256); - log(" MB)\n"); - - bad_function(); + // bad_function(); - void_function_t start_program = first_module_as_a_function(mbinfo); - start_program(); - log("Got past call to start_program()\n"); + // void_function_t start_program = first_module_as_a_function(mbinfo); + // start_program(); + // log("Got past call to start_program()\n"); // Loop forever // User input is accepted asynchronously via interrupts diff --git a/loader.h b/loader.h index 09442e1..4c25a11 100644 --- a/loader.h +++ b/loader.h @@ -5,7 +5,7 @@ uint32_t KERNEL_VIRTUAL_BASE; -void * BootPageDirectory; -void * boot_pagetab1; +void * PageDirectoryVirtualAddress; +void * PageDirectoryPhysicalAddress; #endif /* INCLUDE_LOADER_H */ \ No newline at end of file diff --git a/loader.s b/loader.s index 7489a71..fa2251e 100644 --- a/loader.s +++ b/loader.s @@ -41,8 +41,8 @@ KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; Page directory index of ke section .data align 0x1000 -global BootPageDirectory -BootPageDirectory: +global PageDirectoryVirtualAddress +PageDirectoryVirtualAddress: ; This page directory entry identity-maps the first 4MB of the 32-bit physical address space. ; All bits are clear except the following: ; bit 7: PS The kernel page is 4MB. @@ -75,7 +75,9 @@ loader equ (_loader - KERNEL_VIRTUAL_BASE) _loader: ; NOTE: Until paging is set up, the code must be position-independent and use physical ; addresses, not virtual ones! - mov ecx, (BootPageDirectory - KERNEL_VIRTUAL_BASE) ; 0x104000 + global PageDirectoryPhysicalAddress + PageDirectoryPhysicalAddress equ (PageDirectoryVirtualAddress - KERNEL_VIRTUAL_BASE) ; 0x104000 + mov ecx, PageDirectoryPhysicalAddress mov cr3, ecx ; Load Page Directory Base Register. mov ecx, cr4 @@ -96,8 +98,8 @@ _loader: higher_half_loader: ; Unmap the identity-mapped first 4MB of physical address space. It should not be needed ; anymore. - ; mov dword [BootPageDirectory], 0 - ; invlpg [0] + mov dword [PageDirectoryVirtualAddress], 0 + invlpg [0] mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the ; stack (end of memory area) @@ -115,7 +117,6 @@ higher_half_loader: call kmain ; use call rather than jmp so C function finds paramters in the correct place hlt ; should never get here. kmain should not return. -global boot_pagetab1 section .bss ; Use the 'bss' section for the stack align 4 ; align at 4 bytes for performance reasons kernel_stack: ; label points to beginning of memory diff --git a/multiboot_utils.c b/multiboot_utils.c index 36dcde9..ed79d80 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -26,7 +26,7 @@ struct elf_section_header_t * get_elf_section(multiboot_info_t* info, char * sec uint32_t shndx = section_table.shndx; struct elf_section_header_t * section_header_table = (struct elf_section_header_t *) addr; - uint32_t string_table_start = section_header_table[shndx].sh_addr; + uint32_t string_table_start = p_to_v(section_header_table[shndx].sh_addr); for (uint32_t i = 0; i < num_sections; i++) { uint32_t sh_name = section_header_table[i].sh_name; @@ -51,7 +51,7 @@ void print_elf_section_header_table(FILE stream, elf_section_header_table_t tabl uint32_t shndx = table.shndx; struct elf_section_header_t * section_header_table = (struct elf_section_header_t *) addr; - uint32_t string_table_start = section_header_table[shndx].sh_addr; + uint32_t string_table_start = p_to_v(section_header_table[shndx].sh_addr); for (uint32_t i = 0; i < num; i++) { uint32_t sh_addr = section_header_table[i].sh_addr; @@ -74,7 +74,7 @@ void print_elf_section_header_table(FILE stream, elf_section_header_table_t tabl void print_memory_map(FILE stream, multiboot_info_t* info) { fprintf(stream, "\nmemory map:\n"); - memory_map_t * memory_map = (memory_map_t *) info->mmap_addr; + memory_map_t * memory_map = (memory_map_t *) p_to_v(info->mmap_addr); uint32_t num_entries = info->mmap_length / sizeof(memory_map_t); for (uint32_t i = 0; i < num_entries; i++) { diff --git a/multiboot_utils.h b/multiboot_utils.h index 8c36da1..ea3bc90 100644 --- a/multiboot_utils.h +++ b/multiboot_utils.h @@ -7,6 +7,7 @@ void_function_t first_module_as_a_function(multiboot_info_t* info); struct elf_section_header_t * get_elf_section(multiboot_info_t* info, char * section_name); +uint32_t p_to_v(uint32_t physical_address); void print_multiboot_info(FILE stream, multiboot_info_t* info); #endif diff --git a/page_allocator.c b/page_allocator.c deleted file mode 100644 index c00748c..0000000 --- a/page_allocator.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "page_allocator.h" - -#include "stdio.h" - -uint32_t free_pages; - -// 2^32 address space -// 2^12 page size -// 2^20 pages -// 2^17 bytes in bitmap -// 2^15 uint32_t's = 32768 - -// #define BITMAP_SIZE 32768 -// Enough room for 515 MB of RAM -// TODO: Find a more efficient way to initialize page allocator -#define BITMAP_SIZE 4096 -uint32_t free_page_bitmap[BITMAP_SIZE]; - -uint32_t round_up_to_nearest_page_start(uint32_t address) { - if ((address & 0xFFF) != 0) { - address &= 0xFFFFF000; - address += 0x00001000; - } - return address; -} - -uint32_t round_down_to_nearest_page_start(uint32_t address) { - if ((address & 0xFFF) != 0) { - address &= 0xFFFFF000; - address -= 0x00001000; - } - return address; -} - -uint32_t page_number(uint32_t address) { - return address >> 12; -} - -void mark_free(uint32_t page_number) { - uint32_t index = page_number >> 5; - uint32_t bit = page_number & 0b11111; - uint32_t value = free_page_bitmap[index]; - value |= (1 << bit); - free_page_bitmap[index] = value; - free_pages++; -} - -void mark_unavailable(uint32_t page_number) { - uint32_t index = page_number >> 5; - uint32_t bit = page_number & 0b11111; - uint32_t value = free_page_bitmap[index]; - value &= ~(1 << bit); - free_page_bitmap[index] = value; - free_pages--; -} - -uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo) { - if(kernel_memory.kernel_virtual_start){} - if(mbinfo){} - - memory_map_t * memory_map = (memory_map_t *) mbinfo->mmap_addr; - uint32_t num_entries = mbinfo->mmap_length / sizeof(memory_map_t); - - for (uint32_t i = 0; i < num_entries; i++) { - if (memory_map[i].type == 1) { - // Available - uint32_t first_addr = memory_map[i].base_addr_low; - uint32_t one_past_last_addr = first_addr + memory_map[i].length_low; - uint32_t first_full_page = page_number(round_up_to_nearest_page_start(first_addr)); - uint32_t one_past_last_full_page = page_number(round_down_to_nearest_page_start(one_past_last_addr)); - - for(uint32_t i = first_full_page; i < one_past_last_full_page; i++) { - mark_free(i); - } - } else { - // Unavailable - } - } - - uint32_t first_partial_page = page_number(round_down_to_nearest_page_start(kernel_memory.kernel_physical_start)); - uint32_t one_past_last_partial_page = page_number(round_up_to_nearest_page_start(kernel_memory.kernel_physical_end)); - - for(uint32_t i = first_partial_page; i < one_past_last_partial_page; i++) { - mark_unavailable(i); - } - - return free_pages; -} \ No newline at end of file diff --git a/page_allocator.h b/page_allocator.h deleted file mode 100644 index d0f8e07..0000000 --- a/page_allocator.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef PAGE_ALLOCATOR_H -#define PAGE_ALLOCATOR_H - -#include "types.h" -#include "multiboot.h" - -struct kernel_memory_descriptor_t { - uint32_t kernel_virtual_start; - uint32_t kernel_virtual_end; - uint32_t kernel_physical_start; - uint32_t kernel_physical_end; -}; - -bool allocate_page(uint32_t virtual_address); -uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); - -#endif /* PAGE_ALLOCATOR_H */ \ No newline at end of file From a543cda5592d0fe7e574e32fba3305a841a09494 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 30 Oct 2016 17:58:51 -0700 Subject: [PATCH 28/67] Page in when we get a page fault. --- data_structures/page_table.c | 54 ++++++++++++++++++++++++++++++++++++ data_structures/page_table.h | 5 ++-- interrupts.c | 9 ++++-- kmain.c | 4 +-- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/data_structures/page_table.c b/data_structures/page_table.c index eeb2806..5b3fd3c 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -17,6 +17,9 @@ // TODO: Find a more efficient way to initialize page allocator #define BITMAP_SIZE 4096 +// With a recursive page tables, the address of the page directory is constant +#define PAGE_DIRECTORY_ADDRESS 0xFFFFF000 + uint32_t free_pages; uint32_t free_page_bitmap[BITMAP_SIZE]; @@ -47,6 +50,10 @@ uint32_t make_page_directory_entry( return entry; } +bool get_present_from_pde(uint32_t pde) { + return (pde & 0b1); +} + uint32_t make_page_table_entry( void* page_frame_address, bool global, @@ -67,6 +74,10 @@ uint32_t make_page_table_entry( return entry; } +bool get_present_from_pte(uint32_t pte) { + return (pte & 0b1); +} + // 1 page = 1024 * 4 bytes = 4 kB // 1 page table = 1024 pages = 4 mB // 1 page directory = 1024 page tables = 4 gB @@ -242,3 +253,46 @@ uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memo return free_pages; } + +void page_in(void* virtual_address) { + uint32_t page_directory_offset = ((uint32_t) virtual_address) >> PAGE_OFFSET_BITS >> PAGE_TABLE_OFFSET_BITS; + + page_directory_t pd = (page_directory_t) PAGE_DIRECTORY_ADDRESS; + uint32_t pde = pd[page_directory_offset]; + + if (!get_present_from_pde(pde)) { + // Allocate a physical page to hold the page table + void* page_table_physical_address = allocate_physical_page(); + + pde = make_page_directory_entry( + page_table_physical_address, + FOUR_KB, + false, + false, + SUPERVISOR, + READ_WRITE, + true + ); + pd[page_directory_offset] = pde; + } + + page_table_t pt = (page_table_t) page_table_virtual_address(page_directory_offset); + uint32_t page_table_offset = (((uint32_t) virtual_address) >> PAGE_OFFSET_BITS) & 0x3FF; + uint32_t pte = pt[page_table_offset]; + + if (!get_present_from_pte(pte)) { + // Allocate a physical page to hold the virtual page + void* page_physical_address = allocate_physical_page(); + + pte = make_page_table_entry( + page_physical_address, + false, + false, + false, + SUPERVISOR, + READ_WRITE, + true + ); + pt[page_table_offset] = pte; + } +} diff --git a/data_structures/page_table.h b/data_structures/page_table.h index 54ba6a7..4c63dda 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -5,7 +5,6 @@ #include "../stdio.h" #include "../types.h" - struct kernel_memory_descriptor_t { uint32_t kernel_virtual_start; uint32_t kernel_virtual_end; @@ -13,12 +12,12 @@ struct kernel_memory_descriptor_t { uint32_t kernel_physical_end; }; -uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); - typedef uint32_t * page_directory_t; typedef uint32_t * page_table_t; +uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); page_directory_t initialize_page_directory(); +void page_in(void* virtual_address); void print_page_directory(FILE stream, page_directory_t pd); #endif /* INCLUDE_PAGE_TABLE_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index bb7ca97..ee7a499 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include "assembly_interface.h" +#include "data_structures/page_table.h" #include "data_structures/symbol_table.h" #include "drivers/keyboard.h" #include "drivers/pic.h" @@ -44,8 +45,13 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t keyboard_interrupt_handler(); break; case(INT_PAGE_FAULT): + if ((error_code & 0b1) == 0) { + // Caused by page-not-present + page_in((void*) cpu.cr2); + break; + } log("Interrupt was a page fault. Here's what I know:\n"); - log("- Tried to access linear address "); + log("- Tried to access virtual address "); print_uint32(LOG, cpu.cr2); log("\n"); if (error_code & 0b1) { @@ -69,7 +75,6 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t if (error_code & 0b10000) { log("- caused by an instruction fetch.\n"); } - while(1){}; break; default: diff --git a/kmain.c b/kmain.c index 2e2d089..dd8f107 100644 --- a/kmain.c +++ b/kmain.c @@ -38,7 +38,7 @@ static char *welcome_string = "" " " ""; -void bad_function() { +void trigger_page_fault() { uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB log("Trying to access address "); print_uint32(LOG, (uint32_t) unmapped_address); @@ -96,7 +96,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_page_directory(LOG, pd); - // bad_function(); + trigger_page_fault(); // void_function_t start_program = first_module_as_a_function(mbinfo); // start_program(); From 4d0438b0855bae0faae6b4157bfb1ad0e3b495d1 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Mon, 31 Oct 2016 21:14:47 -0700 Subject: [PATCH 29/67] Get project building on new laptop. --- assembly_interface.h | 4 ++-- assembly_interface.s | 6 +++--- data_structures/global_descriptor_table.c | 2 +- loader.s | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assembly_interface.h b/assembly_interface.h index ad88310..4bc2018 100644 --- a/assembly_interface.h +++ b/assembly_interface.h @@ -19,13 +19,13 @@ void outb(unsigned short port, unsigned char data); */ unsigned char inb(unsigned short port); -/** lgdt: +/** asm_lgdt: * Loads the global descriptor table * * @param gdt The address of a gdt description structure * http://wiki.osdev.org/Global_Descriptor_Table#Structure */ -void lgdt(void * gdt); +void asm_lgdt(void * gdt); /** load_idt: * Loads the interrupt descriptor table diff --git a/assembly_interface.s b/assembly_interface.s index 07dee22..7c9720b 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -20,12 +20,12 @@ inb: in al, dx ; read a byte from the I/O port and store it in the al register ret -global lgdt +global asm_lgdt -; lgdt - load global descriptor table +; asm_lgdt - load global descriptor table ; stack: [esp + 4] the address of the gdt description structure ; [esp ] return address -lgdt: +asm_lgdt: mov edx, [esp + 4] lgdt [edx] ret diff --git a/data_structures/global_descriptor_table.c b/data_structures/global_descriptor_table.c index f9222c3..306d10d 100644 --- a/data_structures/global_descriptor_table.c +++ b/data_structures/global_descriptor_table.c @@ -48,7 +48,7 @@ void initialize_gdt() { gdt[KERNAL_DATA_SEGMENT_INDEX].flags_and_limit_16_19 = 0xCF; gdt[KERNAL_DATA_SEGMENT_INDEX].base_24_31 = 0x00; - lgdt(&gdt_description_structure); + asm_lgdt(&gdt_description_structure); // Grub has already loaded the segment registers // with the correct values (0x8 for cs, 0x10 for the others) diff --git a/loader.s b/loader.s index fa2251e..fc1c112 100644 --- a/loader.s +++ b/loader.s @@ -71,8 +71,8 @@ align 4 ; the code must be 4 byte aligned dd FLAGS ; the flags, dd CHECKSUM ; and the checksum -loader equ (_loader - KERNEL_VIRTUAL_BASE) _loader: +loader equ (_loader - KERNEL_VIRTUAL_BASE) ; NOTE: Until paging is set up, the code must be position-independent and use physical ; addresses, not virtual ones! global PageDirectoryPhysicalAddress From a75b8c2692b55fe2105033a1af76f31a2c06cf19 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 12 Nov 2016 10:52:59 -0800 Subject: [PATCH 30/67] Add user segments. --- data_structures/global_descriptor_table.c | 25 ++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/data_structures/global_descriptor_table.c b/data_structures/global_descriptor_table.c index 306d10d..9780585 100644 --- a/data_structures/global_descriptor_table.c +++ b/data_structures/global_descriptor_table.c @@ -2,8 +2,9 @@ #include "../assembly_interface.h" +// As described here: http://wiki.osdev.org/Global_Descriptor_Table#Structure struct segment_descriptor_t { - uint16_t limit_0_15; // bits o-15 of limit + uint16_t limit_0_15; // bits 0-15 of limit uint16_t base_0_15; uint8_t base_16_23; uint8_t access_byte; @@ -14,13 +15,17 @@ struct segment_descriptor_t { const uint16_t NULL_SEGMENT_SELECTOR = 0x0; const uint16_t KERNAL_CODE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 1; const uint16_t KERNAL_DATA_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 2; +const uint16_t USER_CODE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 3; +const uint16_t USER_DATA_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 4; -struct segment_descriptor_t gdt[3]; +struct segment_descriptor_t gdt[5]; enum segment_selector_t { NULL_DESCRIPTOR, // Not used but has to be here KERNAL_CODE_SEGMENT_INDEX, // Offset 0x8 - KERNAL_DATA_SEGMENT_INDEX // Offset 0x10 + KERNAL_DATA_SEGMENT_INDEX, // Offset 0x10 + USER_CODE_SEGMENT_INDEX, // Offset 0x18 + USER_DATA_SEGMENT_INDEX // Offset 0x20 }; // a pointer to the global descriptor table @@ -48,6 +53,20 @@ void initialize_gdt() { gdt[KERNAL_DATA_SEGMENT_INDEX].flags_and_limit_16_19 = 0xCF; gdt[KERNAL_DATA_SEGMENT_INDEX].base_24_31 = 0x00; + gdt[USER_CODE_SEGMENT_INDEX].limit_0_15 = 0xFFFF; + gdt[USER_CODE_SEGMENT_INDEX].base_0_15 = 0x0000; + gdt[USER_CODE_SEGMENT_INDEX].base_16_23 = 0x00; + gdt[USER_CODE_SEGMENT_INDEX].access_byte = 0b11111010; + gdt[USER_CODE_SEGMENT_INDEX].flags_and_limit_16_19 = 0xCF; + gdt[USER_CODE_SEGMENT_INDEX].base_24_31 = 0x00; + + gdt[USER_DATA_SEGMENT_INDEX].limit_0_15 = 0xFFFF; + gdt[USER_DATA_SEGMENT_INDEX].base_0_15 = 0x0000; + gdt[USER_DATA_SEGMENT_INDEX].base_16_23 = 0x00; + gdt[USER_DATA_SEGMENT_INDEX].access_byte = 0b11110010; + gdt[USER_DATA_SEGMENT_INDEX].flags_and_limit_16_19 = 0xCF; + gdt[USER_DATA_SEGMENT_INDEX].base_24_31 = 0x00; + asm_lgdt(&gdt_description_structure); // Grub has already loaded the segment registers From bc845590f2a9a56b66d8977f4a0e246a8beeca03 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 12 Nov 2016 11:42:32 -0800 Subject: [PATCH 31/67] Super-simple malloc. --- Makefile | 1 + kmain.c | 28 +++++++++++++++++++++++++++- loader.h | 2 ++ loader.s | 5 +++-- stdlib.c | 15 +++++++++++++++ stdlib.h | 8 ++++++++ 6 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 stdlib.c create mode 100644 stdlib.h diff --git a/Makefile b/Makefile index 41d90b0..8eaaf56 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ interrupts.o \ kmain.o \ multiboot_utils.o \ stdio.o \ +stdlib.o \ string.o all: os.iso diff --git a/kmain.c b/kmain.c index dd8f107..af07db5 100644 --- a/kmain.c +++ b/kmain.c @@ -8,6 +8,7 @@ #include "drivers/serial_port.h" #include "multiboot_utils.h" #include "stdio.h" +#include "stdlib.h" #include "types.h" static char *welcome_string = "" @@ -44,9 +45,15 @@ void trigger_page_fault() { print_uint32(LOG, (uint32_t) unmapped_address); log(":\n"); print_uint8(LOG, *unmapped_address); - log("\n. Successfully accessed."); + log("\n. Successfully accessed.\n"); } +struct test_struct_t { + uint32_t integer; + char character; + char* string; +}; + void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { // GRUB passes info to the kernel through the ebx register multiboot_info_t *mbinfo = (multiboot_info_t *) ebx; @@ -98,6 +105,25 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { trigger_page_fault(); + struct test_struct_t* test = (struct test_struct_t*) malloc(sizeof(struct test_struct_t)); + + log("Dynamically allocated a struct\nAddress is: "); + print_uint32(LOG, (uint32_t) test); + log("\n"); + + log("test->integer started as: "); + print_uint32(LOG, (uint32_t) test->integer); + log("\n"); + + test->integer = 10; + + log("now test->integer is: "); + print_uint32(LOG, (uint32_t) test->integer); + log("\n"); + + test->character = 'A'; + test->string = "Hello World"; + // void_function_t start_program = first_module_as_a_function(mbinfo); // start_program(); // log("Got past call to start_program()\n"); diff --git a/loader.h b/loader.h index 4c25a11..f1c6910 100644 --- a/loader.h +++ b/loader.h @@ -4,7 +4,9 @@ #include "types.h" uint32_t KERNEL_VIRTUAL_BASE; +uint32_t KERNEL_STACK_SIZE; +void * kernel_stack_lowest_address; void * PageDirectoryVirtualAddress; void * PageDirectoryPhysicalAddress; diff --git a/loader.s b/loader.s index fc1c112..57a56fb 100644 --- a/loader.s +++ b/loader.s @@ -101,7 +101,7 @@ higher_half_loader: mov dword [PageDirectoryVirtualAddress], 0 invlpg [0] - mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the + mov esp, kernel_stack_lowest_address + KERNEL_STACK_SIZE ; point esp to the start of the ; stack (end of memory area) add ebx, KERNEL_VIRTUAL_BASE ; make the address virtual @@ -117,7 +117,8 @@ higher_half_loader: call kmain ; use call rather than jmp so C function finds paramters in the correct place hlt ; should never get here. kmain should not return. +global kernel_stack_lowest_address section .bss ; Use the 'bss' section for the stack align 4 ; align at 4 bytes for performance reasons - kernel_stack: ; label points to beginning of memory + kernel_stack_lowest_address: ; label points to beginning of memory resb KERNEL_STACK_SIZE ; reserve stack for the kernel \ No newline at end of file diff --git a/stdlib.c b/stdlib.c new file mode 100644 index 0000000..f086b42 --- /dev/null +++ b/stdlib.c @@ -0,0 +1,15 @@ +#include "stdlib.h" + +#include "data_structures/page_table.h" +#include "loader.h" + +// naive strategy for now: keep track of highest allocated +// address, don't worry about freeing memory. + +void* lowest_free_memory = &kernel_stack_lowest_address; + +void* malloc(uint32_t bytes) { + void* chunk_start = lowest_free_memory; + lowest_free_memory += bytes; + return chunk_start; +} \ No newline at end of file diff --git a/stdlib.h b/stdlib.h new file mode 100644 index 0000000..5429d03 --- /dev/null +++ b/stdlib.h @@ -0,0 +1,8 @@ +#ifndef STDLIB_H +#define STDLIB_H + +#include "types.h" + +void* malloc(uint32_t bytes); + +#endif /* STDLIB_H */ \ No newline at end of file From 1ca5454b508ff8ee50aff2706ad7b0eed81841ce Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 12 Nov 2016 12:24:16 -0800 Subject: [PATCH 32/67] Function to get current stack pointer. --- assembly_interface.h | 2 ++ assembly_interface.s | 5 +++++ kmain.c | 22 +++++++++++++--------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/assembly_interface.h b/assembly_interface.h index 4bc2018..b28b367 100644 --- a/assembly_interface.h +++ b/assembly_interface.h @@ -58,4 +58,6 @@ void set_page_directory(); */ void enable_paging(); +void* current_stack_pointer(); + #endif /* INCLUDE_ASSEMBLY_INTERFACE_H */ \ No newline at end of file diff --git a/assembly_interface.s b/assembly_interface.s index 7c9720b..31bae92 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -70,3 +70,8 @@ enable_paging: or eax, 0x80000000 mov cr0, eax ret + +global current_stack_pointer +current_stack_pointer: + mov eax, esp + ret diff --git a/kmain.c b/kmain.c index af07db5..4008620 100644 --- a/kmain.c +++ b/kmain.c @@ -111,18 +111,22 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_uint32(LOG, (uint32_t) test); log("\n"); - log("test->integer started as: "); - print_uint32(LOG, (uint32_t) test->integer); - log("\n"); - - test->integer = 10; + test->character = 'A'; + test->string = "Hello World"; + + uint32_t local = 0xDEADBEEF; - log("now test->integer is: "); - print_uint32(LOG, (uint32_t) test->integer); + log("local variable at: "); + print_uint32(LOG, (uint32_t) &local); + log("\n"); + log("local variable value: "); + print_uint32(LOG, (uint32_t) local); log("\n"); - test->character = 'A'; - test->string = "Hello World"; + void* sp = current_stack_pointer(); + log("stack pointer is: "); + print_uint32(LOG, (uint32_t) sp); + log("\n"); // void_function_t start_program = first_module_as_a_function(mbinfo); // start_program(); From 24fdef2a62d1237a77d1d2d48869f57ab6702a04 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 12 Nov 2016 13:08:46 -0800 Subject: [PATCH 33/67] Clean up and organize boot logging. --- data_structures/page_table.c | 8 ++--- data_structures/page_table.h | 2 +- interrupts.c | 25 ++++++++----- kmain.c | 69 +++++++++++++++++++++--------------- 4 files changed, 62 insertions(+), 42 deletions(-) diff --git a/data_structures/page_table.c b/data_structures/page_table.c index 5b3fd3c..c0fcbe6 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -162,17 +162,17 @@ page_directory_t initialize_page_directory() { return pd; } -void print_page_directory(FILE stream, page_directory_t pd) { +uint32_t num_present_pages(page_directory_t pd) { + uint32_t num = 0; for (int i = 0; i < 1024; i++) { uint32_t entry = pd[i]; bool present = entry & 0x1; if (present) { - fprintf(stream, "page directory entry "); - print_uint32(stream, i); - fprintf(stream, " is present.\n"); + num += 1; } } + return num; } uint32_t round_up_to_nearest_page_start(uint32_t address) { diff --git a/data_structures/page_table.h b/data_structures/page_table.h index 4c63dda..e17f6d3 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -17,7 +17,7 @@ typedef uint32_t * page_table_t; uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); page_directory_t initialize_page_directory(); +uint32_t num_present_pages(page_directory_t pd); void page_in(void* virtual_address); -void print_page_directory(FILE stream, page_directory_t pd); #endif /* INCLUDE_PAGE_TABLE_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index ee7a499..7c44a75 100644 --- a/interrupts.c +++ b/interrupts.c @@ -10,13 +10,15 @@ #define INT_KEYBOARD 0x00000009 #define INT_GENERAL_PROTECTION_FAULT 0x0000000D #define INT_PAGE_FAULT 0x0000000E +#define INT_SOFTWARE 0x00000031 -void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip) { - log("\n!!! Interrupt\n"); - log("interrupt_number: "); - print_uint32(LOG, interrupt_number); - log("\n"); +void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, struct cpu_state* cpu) { + if(cpu->ebp){} + log("--------------------\n"); + log("Interrupt : "); + log(int_name); + log("\n"); log("error_code: "); print_uint32(LOG, error_code); log("\n"); @@ -27,9 +29,9 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t char * symbol_name = address_to_symbol_name(eip); fprintf(LOG, symbol_name); log("\n"); - uint32_t ebp = cpu.ebp; + uint32_t ebp = cpu->ebp; while (ebp & 0xC0100000) { - uint32_t eip = ((uint32_t*) ebp)[1]; + eip = ((uint32_t*) ebp)[1]; print_uint32(LOG, eip); log(" : "); char * symbol_name = address_to_symbol_name(eip); @@ -38,8 +40,11 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t ebp = *((uint32_t*)ebp); } - log("\n"); + log("--------------------\n"); +} + +void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip) { switch(interrupt_number) { case(INT_KEYBOARD): keyboard_interrupt_handler(); @@ -77,6 +82,10 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t } break; + case(INT_SOFTWARE): + log_interrupt_details("INT_SOFTWARE", error_code, eip, &cpu); + break; + default: log("ERROR: Unabled to handle interrupt: "); print_uint32(LOG, interrupt_number); diff --git a/kmain.c b/kmain.c index 4008620..8d967a8 100644 --- a/kmain.c +++ b/kmain.c @@ -39,13 +39,9 @@ static char *welcome_string = "" " " ""; -void trigger_page_fault() { - uint32_t * unmapped_address = (uint32_t *) 0x400000; // 4 MB - log("Trying to access address "); - print_uint32(LOG, (uint32_t) unmapped_address); - log(":\n"); - print_uint8(LOG, *unmapped_address); - log("\n. Successfully accessed.\n"); +uint32_t trigger_page_fault() { + uint32_t* unmapped_address = (uint32_t *) 0x400000; // 4 MB + return *unmapped_address; } struct test_struct_t { @@ -63,68 +59,83 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { printf(welcome_string); serial_init(); - log("\n--------------------\ncstackOS is booting!\n--------------------\n\nInitialized serial port.\n"); + log("\n--------------------\ncstackOS is booting!\n--------------------\n\n"); + #ifdef DEBUG log("\nMultiboot info passed to kernel from GRUB:\n"); print_multiboot_info(LOG, mbinfo); log("\n"); + #endif + log("- Initializing symbol table...\n"); if (load_symbol_table(get_elf_section(mbinfo, ".symtab"), get_elf_section(mbinfo, ".strtab"))) { - log("Initialized symbol table.\n"); + log(" - done\n"); } else { log("ERROR: Could not initialize symbol table.\n"); + while(1){} } + log("- Initializing global descriptor table...\n"); initialize_gdt(); - log("Loaded global descriptor table.\n"); + log(" - done\n"); + log("- Initializing interrupt descriptor table...\n"); initialize_idt(); - log("Loaded interrupt descriptor table.\n"); + log(" - done\n"); - log("Issuing test interrupt.\n"); + log("- Issuing test interrupt...\n"); interrupt(49); - log("Returned from test interrupt()\n"); + log(" - done\n"); + log("- Initializing programable interrupt controller...\n"); pic_init(); - log("Initialized PIC\n"); + log(" - done\n"); + log("- Initializing page allocator...\n"); uint32_t free_pages = initialize_page_allocator(kernel_memory, mbinfo); - log("Initialized page allocator.\n"); + log(" - done\n"); + log(" - "); print_uint32(LOG, free_pages); log(" free pages ("); print_uint32(LOG, free_pages / 256); log(" MB)\n"); + log("- Initializing page directory...\n"); page_directory_t pd = initialize_page_directory(); - log("Initialized page directory.\n"); - log("Address of page directory: "); + log(" - done\n"); + log(" - Address of page directory: "); print_uint32(LOG, (uint32_t) pd); log("\n"); + uint32_t num_pages = num_present_pages(pd); + log(" - "); + print_uint32(LOG, num_pages); + log(" present pages\n"); + + log("- Triggering a page fault...\n"); + uint32_t value = trigger_page_fault(); + log(" - done\n"); + log(" - value at unmapped address was "); + print_uint32(LOG, value); + log("\n"); - print_page_directory(LOG, pd); - - trigger_page_fault(); - + log("- Dynamically allocating a struct...\n"); struct test_struct_t* test = (struct test_struct_t*) malloc(sizeof(struct test_struct_t)); - - log("Dynamically allocated a struct\nAddress is: "); + log(" - done\n"); + log(" - address is: "); print_uint32(LOG, (uint32_t) test); log("\n"); - - test->character = 'A'; - test->string = "Hello World"; uint32_t local = 0xDEADBEEF; - log("local variable at: "); + log(" - local variable at: "); print_uint32(LOG, (uint32_t) &local); log("\n"); - log("local variable value: "); + log(" - local variable value: "); print_uint32(LOG, (uint32_t) local); log("\n"); void* sp = current_stack_pointer(); - log("stack pointer is: "); + log(" - stack pointer is: "); print_uint32(LOG, (uint32_t) sp); log("\n"); From 8d36aa6ab2d7545c74f4fb2e72eafdab0adfab1d Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 12 Nov 2016 15:03:45 -0800 Subject: [PATCH 34/67] Fix bugs with stack trace. --- assembly_interface.s | 5 ++++- interrupts.c | 21 +++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/assembly_interface.s b/assembly_interface.s index 31bae92..ed60fed 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -45,8 +45,11 @@ global interrupt ; stack: [esp + 4] the software interrupt that should be generated (0-255) ; [esp ] the return address interrupt: - mov eax, [esp+4] + mov eax, [esp+4] ; TODO: figure out how to pass this parameter to the int instruction + push ebp ; make the caller show up in the stack trace + mov ebp, esp int 49 + pop ebp global enable_hardware_interrupts ; enable_hardware_interrupts diff --git a/interrupts.c b/interrupts.c index 7c44a75..42d2681 100644 --- a/interrupts.c +++ b/interrupts.c @@ -12,6 +12,14 @@ #define INT_PAGE_FAULT 0x0000000E #define INT_SOFTWARE 0x00000031 +void log_stack_trace_line(uint32_t eip) { + print_uint32(LOG, eip); + log(" : "); + char * symbol_name = address_to_symbol_name(eip); + fprintf(LOG, symbol_name); + log("\n"); +} + void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, struct cpu_state* cpu) { if(cpu->ebp){} log("--------------------\n"); @@ -24,19 +32,12 @@ void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, st log("\n"); log("\nStack trace:\n"); - print_uint32(LOG, eip); - log(" : "); - char * symbol_name = address_to_symbol_name(eip); - fprintf(LOG, symbol_name); - log("\n"); + eip -= 4; // eip actually points one past the instruction that triggered interrupt + log_stack_trace_line(eip); uint32_t ebp = cpu->ebp; while (ebp & 0xC0100000) { eip = ((uint32_t*) ebp)[1]; - print_uint32(LOG, eip); - log(" : "); - char * symbol_name = address_to_symbol_name(eip); - fprintf(LOG, symbol_name); - log("\n"); + log_stack_trace_line(eip); ebp = *((uint32_t*)ebp); } From 041e88a4c34972ec209917b1b5f7d1a329116e46 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 13 Nov 2016 13:51:09 -0800 Subject: [PATCH 35/67] Raise interrupt if malloc() runs out of memory. --- assembly_interface.h | 1 + assembly_interface.s | 9 +++++++++ interrupts.c | 9 ++++++++- kmain.c | 6 ++++++ script/sorted-symbol-table | 10 ++++++++++ stdlib.c | 6 ++++++ 6 files changed, 40 insertions(+), 1 deletion(-) create mode 100755 script/sorted-symbol-table diff --git a/assembly_interface.h b/assembly_interface.h index b28b367..234f1e3 100644 --- a/assembly_interface.h +++ b/assembly_interface.h @@ -40,6 +40,7 @@ void load_idt(void * idt); * @param interrupt_number The number of the interrupt of generate */ void interrupt(uint32_t interrupt_number); +void interrupt_out_of_memory(); /** enable_hardware_interrupts: * Sets the Interrupt bit in the FLAGS diff --git a/assembly_interface.s b/assembly_interface.s index ed60fed..39159a6 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -50,6 +50,15 @@ interrupt: mov ebp, esp int 49 pop ebp + ret + +global interrupt_out_of_memory +interrupt_out_of_memory: + push ebp ; make the caller show up in the stack trace + mov ebp, esp + int 50 + pop ebp + ret global enable_hardware_interrupts ; enable_hardware_interrupts diff --git a/interrupts.c b/interrupts.c index 42d2681..5813c44 100644 --- a/interrupts.c +++ b/interrupts.c @@ -11,6 +11,7 @@ #define INT_GENERAL_PROTECTION_FAULT 0x0000000D #define INT_PAGE_FAULT 0x0000000E #define INT_SOFTWARE 0x00000031 +#define INT_OUT_OF_MEMORY 0x00000032 void log_stack_trace_line(uint32_t eip) { print_uint32(LOG, eip); @@ -87,10 +88,16 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t log_interrupt_details("INT_SOFTWARE", error_code, eip, &cpu); break; + case(INT_OUT_OF_MEMORY): + log_interrupt_details("INT_OUT_OF_MEMORY", error_code, eip, &cpu); + while(true){} + break; + default: - log("ERROR: Unabled to handle interrupt: "); + log("ERROR: Unable to handle interrupt: "); print_uint32(LOG, interrupt_number); log("\n"); + log_interrupt_details("INT_UNKNOWN", error_code, eip, &cpu); break; } diff --git a/kmain.c b/kmain.c index 8d967a8..3474080 100644 --- a/kmain.c +++ b/kmain.c @@ -139,6 +139,12 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_uint32(LOG, (uint32_t) sp); log("\n"); + log("- Dynamically allocating 1000 structs...\n"); + for (uint32_t i = 0; i < 1000; i++) { + test = (struct test_struct_t*) malloc(sizeof(struct test_struct_t)); + } + log(" - done\n"); + // void_function_t start_program = first_module_as_a_function(mbinfo); // start_program(); // log("Got past call to start_program()\n"); diff --git a/script/sorted-symbol-table b/script/sorted-symbol-table new file mode 100755 index 0000000..3460ba2 --- /dev/null +++ b/script/sorted-symbol-table @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby +raw = `greadelf --symbols kernel.elf` + +lines = raw.split("\n").drop(3) + +formatted_lines = lines.map do |line| + line.split(":").drop(1).join("").strip +end + +puts formatted_lines.sort.join("\n") \ No newline at end of file diff --git a/stdlib.c b/stdlib.c index f086b42..dfa6670 100644 --- a/stdlib.c +++ b/stdlib.c @@ -1,5 +1,6 @@ #include "stdlib.h" +#include "assembly_interface.h" #include "data_structures/page_table.h" #include "loader.h" @@ -11,5 +12,10 @@ void* lowest_free_memory = &kernel_stack_lowest_address; void* malloc(uint32_t bytes) { void* chunk_start = lowest_free_memory; lowest_free_memory += bytes; + + if (lowest_free_memory >= current_stack_pointer()) { + interrupt_out_of_memory(); + } + return chunk_start; } \ No newline at end of file From fda1cda89965bdc0a877a633b2af585a791186d9 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 13 Nov 2016 13:54:11 -0800 Subject: [PATCH 36/67] Can't pass a paramter to interrupt() --- assembly_interface.h | 4 +--- assembly_interface.s | 3 --- kmain.c | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/assembly_interface.h b/assembly_interface.h index 234f1e3..300a282 100644 --- a/assembly_interface.h +++ b/assembly_interface.h @@ -36,10 +36,8 @@ void load_idt(void * idt); /** interrupt: * Generates a software interrupt - * - * @param interrupt_number The number of the interrupt of generate */ -void interrupt(uint32_t interrupt_number); +void interrupt(); void interrupt_out_of_memory(); /** enable_hardware_interrupts: diff --git a/assembly_interface.s b/assembly_interface.s index 39159a6..f1d45b8 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -42,10 +42,7 @@ load_idt: global interrupt ; interrupt - Generates a software interrupt -; stack: [esp + 4] the software interrupt that should be generated (0-255) -; [esp ] the return address interrupt: - mov eax, [esp+4] ; TODO: figure out how to pass this parameter to the int instruction push ebp ; make the caller show up in the stack trace mov ebp, esp int 49 diff --git a/kmain.c b/kmain.c index 3474080..a701351 100644 --- a/kmain.c +++ b/kmain.c @@ -84,7 +84,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { log(" - done\n"); log("- Issuing test interrupt...\n"); - interrupt(49); + interrupt(); log(" - done\n"); log("- Initializing programable interrupt controller...\n"); From e74bb17d856398948343e223928d1ce0ec4cd82b Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 13 Nov 2016 15:06:33 -0800 Subject: [PATCH 37/67] Allocate a page for the new page directory. --- Makefile | 1 + data_structures/page_table.c | 22 +++++++++++++++++----- data_structures/page_table.h | 5 +++-- kmain.c | 9 ++++----- memory.h | 10 ++++++++++ process.c | 35 +++++++++++++++++++++++++++++++++++ process.h | 8 ++++++++ 7 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 memory.h create mode 100644 process.c create mode 100644 process.h diff --git a/Makefile b/Makefile index 8eaaf56..ca29550 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ drivers/serial_port.o \ interrupts.o \ kmain.o \ multiboot_utils.o \ +process.o \ stdio.o \ stdlib.o \ string.o diff --git a/data_structures/page_table.c b/data_structures/page_table.c index c0fcbe6..027f6f5 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -1,6 +1,7 @@ #include "page_table.h" #include "../loader.h" +#include "../memory.h" #include "../multiboot_utils.h" #define PAGE_DIRECTORY_OFFSET_BITS 10 @@ -17,9 +18,6 @@ // TODO: Find a more efficient way to initialize page allocator #define BITMAP_SIZE 4096 -// With a recursive page tables, the address of the page directory is constant -#define PAGE_DIRECTORY_ADDRESS 0xFFFFF000 - uint32_t free_pages; uint32_t free_page_bitmap[BITMAP_SIZE]; @@ -116,7 +114,7 @@ void* page_table_virtual_address(uint16_t page_table_number) { return (void*) virtual_address; } -page_directory_t initialize_page_directory() { +page_directory_t initialize_kernel_page_directory() { page_directory_t pd = (page_directory_t) &PageDirectoryVirtualAddress; // Make the last entry in the pd a pointer to itself @@ -254,7 +252,7 @@ uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memo return free_pages; } -void page_in(void* virtual_address) { +void page_in(const void* virtual_address) { uint32_t page_directory_offset = ((uint32_t) virtual_address) >> PAGE_OFFSET_BITS >> PAGE_TABLE_OFFSET_BITS; page_directory_t pd = (page_directory_t) PAGE_DIRECTORY_ADDRESS; @@ -296,3 +294,17 @@ void page_in(void* virtual_address) { pt[page_table_offset] = pte; } } + +void* virtual_to_physical(const void* addr) { + uint32_t addr_as_int = (uint32_t) addr; + uint32_t page_directory_offset = (addr_as_int & 0xFFC00000) >> 22; + uint32_t page_table_offset = (addr_as_int & 0x003FF000) >> 12; + uint32_t page_offset = (addr_as_int & 0x00000FFF); + + uint32_t* page_table_addr = (uint32_t*) (FIRST_PAGE_TABLE_ADDRESS + (PAGE_SIZE_BYTES * page_directory_offset)); + uint32_t page_table_entry = page_table_addr[page_table_offset]; + + uint32_t physical_address = ((page_table_entry >> 12) << 12) | page_offset; + + return (void*) physical_address; +} diff --git a/data_structures/page_table.h b/data_structures/page_table.h index e17f6d3..d1418bd 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -16,8 +16,9 @@ typedef uint32_t * page_directory_t; typedef uint32_t * page_table_t; uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); -page_directory_t initialize_page_directory(); +page_directory_t initialize_kernel_page_directory(); uint32_t num_present_pages(page_directory_t pd); -void page_in(void* virtual_address); +void page_in(const void* virtual_address); +void* virtual_to_physical(const void* addr); #endif /* INCLUDE_PAGE_TABLE_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index a701351..15c3534 100644 --- a/kmain.c +++ b/kmain.c @@ -7,6 +7,7 @@ #include "drivers/pic.h" #include "drivers/serial_port.h" #include "multiboot_utils.h" +#include "process.h" #include "stdio.h" #include "stdlib.h" #include "types.h" @@ -101,7 +102,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { log(" MB)\n"); log("- Initializing page directory...\n"); - page_directory_t pd = initialize_page_directory(); + page_directory_t pd = initialize_kernel_page_directory(); log(" - done\n"); log(" - Address of page directory: "); print_uint32(LOG, (uint32_t) pd); @@ -139,10 +140,8 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_uint32(LOG, (uint32_t) sp); log("\n"); - log("- Dynamically allocating 1000 structs...\n"); - for (uint32_t i = 0; i < 1000; i++) { - test = (struct test_struct_t*) malloc(sizeof(struct test_struct_t)); - } + log("- Creating a user process...\n"); + create_process(); log(" - done\n"); // void_function_t start_program = first_module_as_a_function(mbinfo); diff --git a/memory.h b/memory.h new file mode 100644 index 0000000..653eb51 --- /dev/null +++ b/memory.h @@ -0,0 +1,10 @@ +#ifndef INCLUDE_MEMORY_H +#define INCLUDE_MEMORY_H + +#define UPPER_GB_START (const void*) 0xC0000000 +#define TMP_PAGE_TABLE_0 (const void*) 0xFFBFE000 +#define TMP_PAGE_TABLE_1 (const void*) 0xFFBFF000 +#define FIRST_PAGE_TABLE_ADDRESS (const void*) 0xFFC00000 // 4 MB from end +#define PAGE_DIRECTORY_ADDRESS (const void*) 0xFFFFF000 // 4 KB from end + +#endif /* INCLUDE_MEMORY_H */ \ No newline at end of file diff --git a/process.c b/process.c new file mode 100644 index 0000000..9466826 --- /dev/null +++ b/process.c @@ -0,0 +1,35 @@ +#include "process.h" + +#include "data_structures/page_table.h" +#include "memory.h" +#include "stdio.h" +#include "stdlib.h" + +uint32_t next_pid = 0; + +struct process_t { + uint32_t pid; + page_directory_t pd; +}; + +void create_process() { + struct process_t* p = malloc(sizeof(struct process_t)); + p->pid = next_pid; + next_pid += 1; + + log("Created process descriptor:\n"); + log("Virtual address: "); + print_uint32(LOG, (uint32_t) p); + log("\n"); + + log("pid: "); + print_uint32(LOG, (uint32_t) p->pid); + log("\n"); + + log("Allocating a physical page for the new page directory\n"); + page_in(TMP_PAGE_TABLE_0); + log("Paged into TMP_PAGE_TABLE_0\n"); + log("Physical address: "); + print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_TABLE_0)); + log("\n"); +} \ No newline at end of file diff --git a/process.h b/process.h new file mode 100644 index 0000000..bc6c47d --- /dev/null +++ b/process.h @@ -0,0 +1,8 @@ +#ifndef INCLUDE_PROCESS_H +#define INCLUDE_PROCESS_H + +#include "types.h" + +void create_process(); + +#endif /* INCLUDE_PROCESS_H */ \ No newline at end of file From 7ecb6c80fb758140fef2d053f89e173f3e5552be Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 13 Nov 2016 15:31:41 -0800 Subject: [PATCH 38/67] Allocate pages for code page table and code page frame. --- data_structures/page_table.c | 3 --- data_structures/page_table.h | 33 +++++++++++++++++++++++++---- memory.h | 11 +++++----- process.c | 41 +++++++++++++++++++++++++++++++++--- 4 files changed, 73 insertions(+), 15 deletions(-) diff --git a/data_structures/page_table.c b/data_structures/page_table.c index 027f6f5..8e92ea2 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -24,9 +24,6 @@ uint32_t free_page_bitmap[BITMAP_SIZE]; void mark_free(uint32_t page_number); void mark_unavailable(uint32_t page_number); uint32_t page_number(uint32_t address); -enum page_size_t {FOUR_KB, FOUR_MB}; -enum page_privilege_t {SUPERVISOR, USER}; -enum page_permissions_t {READ_ONLY, READ_WRITE}; uint32_t make_page_directory_entry( void* page_table_physical_address, diff --git a/data_structures/page_table.h b/data_structures/page_table.h index d1418bd..798462b 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -15,10 +15,35 @@ struct kernel_memory_descriptor_t { typedef uint32_t * page_directory_t; typedef uint32_t * page_table_t; -uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo); +enum page_permissions_t {READ_ONLY, READ_WRITE}; +enum page_privilege_t {SUPERVISOR, USER}; +enum page_size_t {FOUR_KB, FOUR_MB}; + page_directory_t initialize_kernel_page_directory(); -uint32_t num_present_pages(page_directory_t pd); -void page_in(const void* virtual_address); -void* virtual_to_physical(const void* addr); +uint32_t initialize_page_allocator( + struct kernel_memory_descriptor_t kernel_memory, + multiboot_info_t* mbinfo + ); +uint32_t make_page_directory_entry( + void* page_table_physical_address, + enum page_size_t page_size, + bool cache_disabled, + bool write_through, + enum page_privilege_t privelage, + enum page_permissions_t permissions, + bool present + ); +uint32_t make_page_table_entry( + void* page_frame_address, + bool global, + bool cache_disabled, + bool write_through, + enum page_privilege_t privelage, + enum page_permissions_t permissions, + bool present + ); +uint32_t num_present_pages(page_directory_t pd); +void page_in(const void* virtual_address); +void* virtual_to_physical(const void* addr); #endif /* INCLUDE_PAGE_TABLE_H */ \ No newline at end of file diff --git a/memory.h b/memory.h index 653eb51..2962a1d 100644 --- a/memory.h +++ b/memory.h @@ -1,10 +1,11 @@ #ifndef INCLUDE_MEMORY_H #define INCLUDE_MEMORY_H -#define UPPER_GB_START (const void*) 0xC0000000 -#define TMP_PAGE_TABLE_0 (const void*) 0xFFBFE000 -#define TMP_PAGE_TABLE_1 (const void*) 0xFFBFF000 -#define FIRST_PAGE_TABLE_ADDRESS (const void*) 0xFFC00000 // 4 MB from end -#define PAGE_DIRECTORY_ADDRESS (const void*) 0xFFFFF000 // 4 KB from end +#define UPPER_GB_START (void*) 0xC0000000 +#define TMP_PAGE_0 (void*) 0xFFBFD000 +#define TMP_PAGE_1 (void*) 0xFFBFE000 +#define TMP_PAGE_2 (void*) 0xFFBFF000 +#define FIRST_PAGE_TABLE_ADDRESS (void*) 0xFFC00000 // 4 MB from end +#define PAGE_DIRECTORY_ADDRESS (void*) 0xFFFFF000 // 4 KB from end #endif /* INCLUDE_MEMORY_H */ \ No newline at end of file diff --git a/process.c b/process.c index 9466826..b1b8820 100644 --- a/process.c +++ b/process.c @@ -27,9 +27,44 @@ void create_process() { log("\n"); log("Allocating a physical page for the new page directory\n"); - page_in(TMP_PAGE_TABLE_0); - log("Paged into TMP_PAGE_TABLE_0\n"); + page_in(TMP_PAGE_0); + page_directory_t pd = TMP_PAGE_0; + p->pd = pd; + log("Paged into TMP_PAGE_0\n"); log("Physical address: "); - print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_TABLE_0)); + print_uint32(LOG, (uint32_t) virtual_to_physical(pd)); log("\n"); + + log("Allocating a page table for user code\n"); + page_in(TMP_PAGE_1); + page_table_t code_pt = TMP_PAGE_1; + uint32_t pde = make_page_directory_entry( + virtual_to_physical(code_pt), + FOUR_KB, + false, + false, + USER, + READ_ONLY, + true + ); + pd[0] = pde; + log("Allocated physical page "); + print_uint32(LOG, (uint32_t) virtual_to_physical(code_pt)); + log(" and set entry in page directory\n"); + + log("Allocating a page for user code\n"); + page_in(TMP_PAGE_2); + uint32_t pte = make_page_table_entry( + virtual_to_physical(TMP_PAGE_2), + false, + false, + false, + USER, + READ_ONLY, + true + ); + code_pt[0] = pte; + log("Allocated physical page "); + print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_2)); + log(" and set entry in code page table\n"); } \ No newline at end of file From 82751d245b0b812d79ef19dd09f12778e032c88e Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 13 Nov 2016 15:57:10 -0800 Subject: [PATCH 39/67] Allocate pages for the user stack. --- data_structures/page_table.c | 45 +++++++++++++++++++++++++----------- data_structures/page_table.h | 3 +++ memory.h | 8 ++++--- process.c | 36 +++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/data_structures/page_table.c b/data_structures/page_table.c index 8e92ea2..f5f5a18 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -250,10 +250,9 @@ uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memo } void page_in(const void* virtual_address) { - uint32_t page_directory_offset = ((uint32_t) virtual_address) >> PAGE_OFFSET_BITS >> PAGE_TABLE_OFFSET_BITS; - + uint32_t pd_offset = page_directory_offset(virtual_address); page_directory_t pd = (page_directory_t) PAGE_DIRECTORY_ADDRESS; - uint32_t pde = pd[page_directory_offset]; + uint32_t pde = pd[pd_offset]; if (!get_present_from_pde(pde)) { // Allocate a physical page to hold the page table @@ -268,12 +267,12 @@ void page_in(const void* virtual_address) { READ_WRITE, true ); - pd[page_directory_offset] = pde; + pd[pd_offset] = pde; } - page_table_t pt = (page_table_t) page_table_virtual_address(page_directory_offset); - uint32_t page_table_offset = (((uint32_t) virtual_address) >> PAGE_OFFSET_BITS) & 0x3FF; - uint32_t pte = pt[page_table_offset]; + page_table_t pt = (page_table_t) page_table_virtual_address(pd_offset); + uint32_t pt_offset = page_table_offset(virtual_address); + uint32_t pte = pt[pt_offset]; if (!get_present_from_pte(pte)) { // Allocate a physical page to hold the virtual page @@ -288,20 +287,38 @@ void page_in(const void* virtual_address) { READ_WRITE, true ); - pt[page_table_offset] = pte; + pt[pt_offset] = pte; } } void* virtual_to_physical(const void* addr) { - uint32_t addr_as_int = (uint32_t) addr; - uint32_t page_directory_offset = (addr_as_int & 0xFFC00000) >> 22; - uint32_t page_table_offset = (addr_as_int & 0x003FF000) >> 12; - uint32_t page_offset = (addr_as_int & 0x00000FFF); + uint32_t pd_offset = page_directory_offset(addr); + uint32_t pt_offset = page_table_offset(addr); + uint32_t page_offset = ((uint32_t) addr & 0x00000FFF); - uint32_t* page_table_addr = (uint32_t*) (FIRST_PAGE_TABLE_ADDRESS + (PAGE_SIZE_BYTES * page_directory_offset)); - uint32_t page_table_entry = page_table_addr[page_table_offset]; + uint32_t* page_table_addr = (uint32_t*) (FIRST_PAGE_TABLE_ADDRESS + (PAGE_SIZE_BYTES * pd_offset)); + uint32_t page_table_entry = page_table_addr[pt_offset]; uint32_t physical_address = ((page_table_entry >> 12) << 12) | page_offset; return (void*) physical_address; } + +uint32_t page_directory_offset(const void* virtual_address) { + return ((uint32_t) virtual_address) >> PAGE_OFFSET_BITS >> PAGE_TABLE_OFFSET_BITS; +} + +uint32_t page_table_offset(const void* virtual_address) { + return (((uint32_t) virtual_address) >> PAGE_OFFSET_BITS) & 0x3FF; +} + +void print_page_table(FILE file, const uint32_t* pt) { + fprintf(file, "---\n"); + for (uint32_t i = 0; i < PAGE_SIZE_DWORDS; i++) { + if (get_present_from_pte(pt[i])) { + print_uint32(file, i); + fprintf(file, " is present\n"); + } + } + fprintf(file, "---\n"); +} diff --git a/data_structures/page_table.h b/data_structures/page_table.h index 798462b..1dc7e96 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -43,7 +43,10 @@ uint32_t make_page_table_entry( bool present ); uint32_t num_present_pages(page_directory_t pd); +uint32_t page_directory_offset(const void* virtual_address); void page_in(const void* virtual_address); +uint32_t page_table_offset(const void* virtual_address); +void print_page_table(FILE file, const uint32_t*); void* virtual_to_physical(const void* addr); #endif /* INCLUDE_PAGE_TABLE_H */ \ No newline at end of file diff --git a/memory.h b/memory.h index 2962a1d..f86ca1e 100644 --- a/memory.h +++ b/memory.h @@ -2,9 +2,11 @@ #define INCLUDE_MEMORY_H #define UPPER_GB_START (void*) 0xC0000000 -#define TMP_PAGE_0 (void*) 0xFFBFD000 -#define TMP_PAGE_1 (void*) 0xFFBFE000 -#define TMP_PAGE_2 (void*) 0xFFBFF000 +#define TMP_PAGE_0 (void*) 0xFFBFB000 +#define TMP_PAGE_1 (void*) 0xFFBFC000 +#define TMP_PAGE_2 (void*) 0xFFBFD000 +#define TMP_PAGE_3 (void*) 0xFFBFE000 +#define TMP_PAGE_4 (void*) 0xFFBFF000 #define FIRST_PAGE_TABLE_ADDRESS (void*) 0xFFC00000 // 4 MB from end #define PAGE_DIRECTORY_ADDRESS (void*) 0xFFFFF000 // 4 KB from end diff --git a/process.c b/process.c index b1b8820..b58a3cc 100644 --- a/process.c +++ b/process.c @@ -67,4 +67,40 @@ void create_process() { log("Allocated physical page "); print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_2)); log(" and set entry in code page table\n"); + + log("Allocating a page table for user stack\n"); + page_in(TMP_PAGE_3); + page_table_t stack_pt = TMP_PAGE_3; + pde = make_page_directory_entry( + virtual_to_physical(stack_pt), + FOUR_KB, + false, + false, + USER, + READ_ONLY, + true + ); + pd[page_directory_offset(UPPER_GB_START) - 1] = pde; + log("Allocated physical page "); + print_uint32(LOG, (uint32_t) virtual_to_physical(stack_pt)); + log(" and set entry in page directory\n"); + + log("Allocating a page for user stack\n"); + page_in(TMP_PAGE_4); + pte = make_page_table_entry( + virtual_to_physical(TMP_PAGE_4), + false, + false, + false, + USER, + READ_ONLY, + true + ); + stack_pt[page_table_offset(UPPER_GB_START) - 1] = pte; + log("Allocated physical page "); + print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_4)); + log(" and set entry in stack page table\n"); + + log("Page directory:\n"); + print_page_table(LOG, pd); } \ No newline at end of file From 3b0c69fe771f6c726d268703f7cc66d805f49611 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 13 Nov 2016 16:02:07 -0800 Subject: [PATCH 40/67] Map kernel into page directory. --- data_structures/page_table.c | 7 +++++++ data_structures/page_table.h | 1 + process.c | 3 +++ 3 files changed, 11 insertions(+) diff --git a/data_structures/page_table.c b/data_structures/page_table.c index f5f5a18..915ba05 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -322,3 +322,10 @@ void print_page_table(FILE file, const uint32_t* pt) { } fprintf(file, "---\n"); } + +void map_kernel_into_page_directory(page_directory_t new_pd) { + page_directory_t pd = (page_directory_t) PAGE_DIRECTORY_ADDRESS; + for (uint32_t i = KERNEL_PAGE_TABLE_NUMBER; i < PAGE_SIZE_DWORDS; i++) { + new_pd[i] = pd[i]; + } +} diff --git a/data_structures/page_table.h b/data_structures/page_table.h index 1dc7e96..ba0902b 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -19,6 +19,7 @@ enum page_permissions_t {READ_ONLY, READ_WRITE}; enum page_privilege_t {SUPERVISOR, USER}; enum page_size_t {FOUR_KB, FOUR_MB}; +void map_kernel_into_page_directory(page_directory_t new_pd); page_directory_t initialize_kernel_page_directory(); uint32_t initialize_page_allocator( struct kernel_memory_descriptor_t kernel_memory, diff --git a/process.c b/process.c index b58a3cc..b3afbaf 100644 --- a/process.c +++ b/process.c @@ -101,6 +101,9 @@ void create_process() { print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_4)); log(" and set entry in stack page table\n"); + log("Mapping in kernel. Copying entries from current page directory.\n"); + map_kernel_into_page_directory(pd); + log("Page directory:\n"); print_page_table(LOG, pd); } \ No newline at end of file From 868d278be6d5eb76358ba5eaea693324619115db Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 13 Nov 2016 22:45:58 -0800 Subject: [PATCH 41/67] Copy user code into user page. --- data_structures/page_table.c | 31 +++++++++++++++++++------------ kmain.c | 6 +----- multiboot_utils.c | 6 +++--- multiboot_utils.h | 2 +- process.c | 23 ++++++++++++++++++++--- process.h | 3 ++- 6 files changed, 46 insertions(+), 25 deletions(-) diff --git a/data_structures/page_table.c b/data_structures/page_table.c index 915ba05..efc39a0 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -140,9 +140,10 @@ page_directory_t initialize_kernel_page_directory() { // From here on out, we can access page tables with `page_table_virtual_address()` // Fill in the kernel page table entirely. + // Map the kernel's 4MB to the first 4MB of physical memory page_table_t pt = (page_table_t) page_table_virtual_address(KERNEL_PAGE_TABLE_NUMBER); for (uint16_t i = 0; i < 1024; i++) { - void* page_physical_address = allocate_physical_page(); + void* page_physical_address = (void*) (i * PAGE_SIZE_BYTES); pt[i] = make_page_table_entry( page_physical_address, false, @@ -230,7 +231,9 @@ uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memo uint32_t one_past_last_full_page = page_number(round_down_to_nearest_page_start(one_past_last_addr)); for(uint32_t i = first_full_page; i < one_past_last_full_page; i++) { - mark_free(i); + if (i > PAGE_SIZE_DWORDS) { // First 4MB are where the kernel lives + mark_free(i); + } } } else { // Unavailable @@ -291,27 +294,31 @@ void page_in(const void* virtual_address) { } } +uint32_t page_directory_offset(const void* virtual_address) { + return ((uint32_t) virtual_address) >> PAGE_OFFSET_BITS >> PAGE_TABLE_OFFSET_BITS; +} + +uint32_t page_table_offset(const void* virtual_address) { + return (((uint32_t) virtual_address) >> PAGE_OFFSET_BITS) & 0x3FF; +} + +uint32_t page_offset(const void* addr) { + return ((uint32_t) addr & 0x00000FFF); +} + void* virtual_to_physical(const void* addr) { uint32_t pd_offset = page_directory_offset(addr); uint32_t pt_offset = page_table_offset(addr); - uint32_t page_offset = ((uint32_t) addr & 0x00000FFF); + uint32_t p_offset = page_offset(addr); uint32_t* page_table_addr = (uint32_t*) (FIRST_PAGE_TABLE_ADDRESS + (PAGE_SIZE_BYTES * pd_offset)); uint32_t page_table_entry = page_table_addr[pt_offset]; - uint32_t physical_address = ((page_table_entry >> 12) << 12) | page_offset; + uint32_t physical_address = ((page_table_entry >> 12) << 12) | p_offset; return (void*) physical_address; } -uint32_t page_directory_offset(const void* virtual_address) { - return ((uint32_t) virtual_address) >> PAGE_OFFSET_BITS >> PAGE_TABLE_OFFSET_BITS; -} - -uint32_t page_table_offset(const void* virtual_address) { - return (((uint32_t) virtual_address) >> PAGE_OFFSET_BITS) & 0x3FF; -} - void print_page_table(FILE file, const uint32_t* pt) { fprintf(file, "---\n"); for (uint32_t i = 0; i < PAGE_SIZE_DWORDS; i++) { diff --git a/kmain.c b/kmain.c index 15c3534..ae2c944 100644 --- a/kmain.c +++ b/kmain.c @@ -141,13 +141,9 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { log("\n"); log("- Creating a user process...\n"); - create_process(); + create_process(first_module(mbinfo)); log(" - done\n"); - // void_function_t start_program = first_module_as_a_function(mbinfo); - // start_program(); - // log("Got past call to start_program()\n"); - // Loop forever // User input is accepted asynchronously via interrupts while(1){} diff --git a/multiboot_utils.c b/multiboot_utils.c index ed79d80..b83cee0 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -142,11 +142,11 @@ void print_multiboot_info(FILE stream, multiboot_info_t* info) { print_memory_map(stream, info); } -void_function_t first_module_as_a_function(multiboot_info_t* info) { +struct module* first_module(multiboot_info_t* info) { if (info->mods_count == 0) { return 0; } - struct module * module_info = (struct module *) info->mods_addr; - return (void_function_t) module_info->mod_start; + struct module* module_info = (struct module*) (p_to_v(info->mods_addr)); + return module_info; } diff --git a/multiboot_utils.h b/multiboot_utils.h index ea3bc90..e97a6b5 100644 --- a/multiboot_utils.h +++ b/multiboot_utils.h @@ -5,7 +5,7 @@ #include "stdio.h" #include "types.h" -void_function_t first_module_as_a_function(multiboot_info_t* info); +struct module* first_module(multiboot_info_t* info); struct elf_section_header_t * get_elf_section(multiboot_info_t* info, char * section_name); uint32_t p_to_v(uint32_t physical_address); void print_multiboot_info(FILE stream, multiboot_info_t* info); diff --git a/process.c b/process.c index b3afbaf..a42e42c 100644 --- a/process.c +++ b/process.c @@ -12,7 +12,7 @@ struct process_t { page_directory_t pd; }; -void create_process() { +void create_process(struct module* mod) { struct process_t* p = malloc(sizeof(struct process_t)); p->pid = next_pid; next_pid += 1; @@ -54,8 +54,9 @@ void create_process() { log("Allocating a page for user code\n"); page_in(TMP_PAGE_2); + void* user_code = TMP_PAGE_2; uint32_t pte = make_page_table_entry( - virtual_to_physical(TMP_PAGE_2), + virtual_to_physical(user_code), false, false, false, @@ -65,7 +66,7 @@ void create_process() { ); code_pt[0] = pte; log("Allocated physical page "); - print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_2)); + print_uint32(LOG, (uint32_t) virtual_to_physical(user_code)); log(" and set entry in code page table\n"); log("Allocating a page table for user stack\n"); @@ -106,4 +107,20 @@ void create_process() { log("Page directory:\n"); print_page_table(LOG, pd); + + log("Copying user program into code section:\n"); + uint32_t program_length_bytes = mod->mod_end - mod->mod_start; + void* mod_virtual_start = (void*) (mod->mod_start + UPPER_GB_START); + + log("Copying "); + print_uint32(LOG, program_length_bytes); + log(" bytes from "); + print_uint32(LOG, (uint32_t) mod_virtual_start); + log("\n"); + for (uint32_t i = 0; i < program_length_bytes; i++) { + ((uint8_t*)user_code)[i] = ((uint8_t*)mod_virtual_start)[i]; + print_uint8(LOG, ((uint8_t*)mod_virtual_start)[i]); + log("\n"); + } + log("Done copying code.\n"); } \ No newline at end of file diff --git a/process.h b/process.h index bc6c47d..1c41e0c 100644 --- a/process.h +++ b/process.h @@ -1,8 +1,9 @@ #ifndef INCLUDE_PROCESS_H #define INCLUDE_PROCESS_H +#include "multiboot.h" #include "types.h" -void create_process(); +void create_process(struct module* mod); #endif /* INCLUDE_PROCESS_H */ \ No newline at end of file From ad5be133c9e3de4be97e5174771fafbb266ae90e Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Mon, 14 Nov 2016 19:56:29 -0800 Subject: [PATCH 42/67] Stack should be writable. --- process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process.c b/process.c index a42e42c..d935f52 100644 --- a/process.c +++ b/process.c @@ -94,7 +94,7 @@ void create_process(struct module* mod) { false, false, USER, - READ_ONLY, + READ_WRITE, true ); stack_pt[page_table_offset(UPPER_GB_START) - 1] = pte; From 767288ac4af9cbabc5a14184fb1a6e927ae70026 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Tue, 15 Nov 2016 20:41:19 -0800 Subject: [PATCH 43/67] Enter user mode. --- assembly_interface.h | 4 ++++ assembly_interface.s | 28 ++++++++++++++++++++++++++-- data_structures/page_table.c | 8 ++++---- process.c | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 65 insertions(+), 8 deletions(-) diff --git a/assembly_interface.h b/assembly_interface.h index 300a282..a33efdb 100644 --- a/assembly_interface.h +++ b/assembly_interface.h @@ -47,6 +47,8 @@ void interrupt_out_of_memory(); */ void enable_hardware_interrupts(); +void disable_hardware_interrupts(); + /** set_page_directory: * Sets control register 3 to the physical address of a page directory */ @@ -59,4 +61,6 @@ void enable_paging(); void* current_stack_pointer(); +void enter_user_mode(); + #endif /* INCLUDE_ASSEMBLY_INTERFACE_H */ \ No newline at end of file diff --git a/assembly_interface.s b/assembly_interface.s index f1d45b8..b1bf8cf 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -1,3 +1,6 @@ +extern USER_DATA_SEGMENT_SELECTOR +extern USER_CODE_SEGMENT_SELECTOR + global outb ; make the label outb visible outside this file ; outb - send a byte to an I/O port @@ -63,6 +66,12 @@ enable_hardware_interrupts: sti ret +global disable_hardware_interrupts +; disable_hardware_interrupts +disable_hardware_interrupts: + cli + ret + global set_page_directory ; sets cr3 to the physical address of a page directory ; page_directory: [esp + 4] the physical address of the page directory @@ -82,5 +91,20 @@ enable_paging: global current_stack_pointer current_stack_pointer: - mov eax, esp - ret + mov eax, esp + ret + +global enter_user_mode +enter_user_mode: + mov ax,0x23 ;user data segment with bottom 2 bits set for ring 3 + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax ;we don't need to worry about SS. it's handled by iret + + push 0x23 ;user data segment with bottom 2 bits set for ring 3 + push 0xBFFFFFFB ; the user mode stack pointer + pushf ; push current eflags + push 0x1B ; user code segment with bottom 2 bits set for ring 3 + push 0x0 ; the instruction pointer of user mode code to execute + iret ; this copies values from the stack into the appropriate registers diff --git a/data_structures/page_table.c b/data_structures/page_table.c index efc39a0..322bdda 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -324,7 +324,9 @@ void print_page_table(FILE file, const uint32_t* pt) { for (uint32_t i = 0; i < PAGE_SIZE_DWORDS; i++) { if (get_present_from_pte(pt[i])) { print_uint32(file, i); - fprintf(file, " is present\n"); + fprintf(file, " -> "); + print_uint32(file, pt[i] & (uint32_t) PAGE_DIRECTORY_ADDRESS); + fprintf(file, "\n"); } } fprintf(file, "---\n"); @@ -332,7 +334,5 @@ void print_page_table(FILE file, const uint32_t* pt) { void map_kernel_into_page_directory(page_directory_t new_pd) { page_directory_t pd = (page_directory_t) PAGE_DIRECTORY_ADDRESS; - for (uint32_t i = KERNEL_PAGE_TABLE_NUMBER; i < PAGE_SIZE_DWORDS; i++) { - new_pd[i] = pd[i]; - } + new_pd[KERNEL_PAGE_TABLE_NUMBER] = pd[KERNEL_PAGE_TABLE_NUMBER]; } diff --git a/process.c b/process.c index d935f52..1c86e13 100644 --- a/process.c +++ b/process.c @@ -1,5 +1,6 @@ #include "process.h" +#include "assembly_interface.h" #include "data_structures/page_table.h" #include "memory.h" #include "stdio.h" @@ -32,13 +33,26 @@ void create_process(struct module* mod) { p->pd = pd; log("Paged into TMP_PAGE_0\n"); log("Physical address: "); - print_uint32(LOG, (uint32_t) virtual_to_physical(pd)); + void* pd_physical_address = virtual_to_physical(pd); + print_uint32(LOG, (uint32_t) pd_physical_address); log("\n"); + log("Make page table recursive\n"); + uint32_t pde = make_page_directory_entry( + pd_physical_address, + FOUR_KB, + false, + false, + SUPERVISOR, + READ_WRITE, + true + ); + pd[1023] = pde; + log("Allocating a page table for user code\n"); page_in(TMP_PAGE_1); page_table_t code_pt = TMP_PAGE_1; - uint32_t pde = make_page_directory_entry( + pde = make_page_directory_entry( virtual_to_physical(code_pt), FOUR_KB, false, @@ -123,4 +137,19 @@ void create_process(struct module* mod) { log("\n"); } log("Done copying code.\n"); + + log("Disabling hardware interrupts.\n"); + disable_hardware_interrupts(); + + log("Page directory starts as "); + print_uint32(LOG, (uint32_t) virtual_to_physical(PAGE_DIRECTORY_ADDRESS)); + log("\n"); + log("Setting page directory\n"); + set_page_directory(virtual_to_physical(pd)); + log("Page directory physical address is now "); + print_uint32(LOG, (uint32_t) virtual_to_physical(PAGE_DIRECTORY_ADDRESS)); + log("\n"); + + log("Entering user mode...\n"); + enter_user_mode(); } \ No newline at end of file From 54ed87f03fa084a3533a3610706793e93e77ca3a Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 19 Nov 2016 11:29:19 -0800 Subject: [PATCH 44/67] Write user program in C. Known bug crashes when accessing stack. --- Makefile | 16 +++++++++++----- link_user_program.ld | 22 ++++++++++++++++++++++ menu.lst | 2 +- process.c | 6 ++++++ start_user_program.s | 17 +++++++++++++++++ user_program.c | 6 ++++++ 6 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 link_user_program.ld create mode 100644 start_user_program.s create mode 100644 user_program.c diff --git a/Makefile b/Makefile index ca29550..e8ae014 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ all: os.iso %.o: %.c # Compile c files with gcc - $(GCC) $(CFLAGS) $< -o $@ + $(GCC) $(CFLAGS) $< -o $@ %.o: %.s # assemble s files with nasm @@ -50,15 +50,21 @@ all: os.iso kernel.elf: $(OBJECTS) $(LD) -T link.ld -melf_i386 $(OBJECTS) -o kernel.elf # Link to make an executable for the kernel. -program.bin: program.s - $(NASM) -f bin $< -o $@ # `-f bin` creates a flat binary +start_user_program.o: start_user_program.s + $(NASM) $(ASFLAGS) $< -o $@ + +user_program.o: user_program.c + $(GCC) $(CFLAGS) $< -o $@ + +user_program.bin: user_program.o start_user_program.o + $(LD) -T link_user_program.ld -melf_i386 $^ -o $@ -os.iso: kernel.elf program.bin menu.lst +os.iso: kernel.elf user_program.bin menu.lst mkdir -p iso/boot/grub # create the folder structure mkdir -p iso/modules cp stage2_eltorito iso/boot/grub/ # copy the bootloader cp kernel.elf iso/boot/ # copy the kernel - cp program.bin iso/modules # copy the 'user' program + cp user_program.bin iso/modules # copy the 'user' program cp menu.lst iso/boot/grub # copy the grub configuration file mkisofs -R \ -b boot/grub/stage2_eltorito \ diff --git a/link_user_program.ld b/link_user_program.ld new file mode 100644 index 0000000..a759645 --- /dev/null +++ b/link_user_program.ld @@ -0,0 +1,22 @@ +OUTPUT_FORMAT("binary") /* output flat binary */ + +SECTIONS +{ + . = 0; /* relocate to address 0 */ + + .text ALIGN(4): + { + start_user_program.o(.text) /* include the .text section of start_user_program.o */ + *(.text) /* include all other .text sections */ + } + + .data ALIGN(4): + { + *(.data) + } + + .rodata ALIGN(4): + { + *(.rodata*) + } +} \ No newline at end of file diff --git a/menu.lst b/menu.lst index 2ba530e..336bddf 100644 --- a/menu.lst +++ b/menu.lst @@ -3,4 +3,4 @@ timeout=0 title os kernel /boot/kernel.elf -module /modules/program.bin \ No newline at end of file +module /modules/user_program.bin \ No newline at end of file diff --git a/process.c b/process.c index 1c86e13..d76c8f5 100644 --- a/process.c +++ b/process.c @@ -150,6 +150,12 @@ void create_process(struct module* mod) { print_uint32(LOG, (uint32_t) virtual_to_physical(PAGE_DIRECTORY_ADDRESS)); log("\n"); + uint32_t* stack_highest_address = (uint32_t*) 0xbffffffb; + uint32_t value_on_stack = *stack_highest_address; + log("Value on stack: "); + print_uint32(LOG, value_on_stack); + log("\n"); + log("Entering user mode...\n"); enter_user_mode(); } \ No newline at end of file diff --git a/start_user_program.s b/start_user_program.s new file mode 100644 index 0000000..d47382a --- /dev/null +++ b/start_user_program.s @@ -0,0 +1,17 @@ +section .text +extern main + mov eax, 0xCAFEBABE + ; push argv + ; push argc + ; mov eax, [esp] ; accessing the stack currently causes a crash + jmp $ + call main2 + jmp $ + ; main has returned, eax is return value + mov eax, 0xDEADBEEF + jmp $ ; loop forever + + main2: + jmp $ + mov eax, 0x11111111 + jmp $ \ No newline at end of file diff --git a/user_program.c b/user_program.c new file mode 100644 index 0000000..be9449d --- /dev/null +++ b/user_program.c @@ -0,0 +1,6 @@ +int main() { + while(1){} + if (1) { + return 1; + } +} \ No newline at end of file From 8db9e6fd0d0084f44d4619996e48b32385ccdf8a Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 19 Nov 2016 13:01:30 -0800 Subject: [PATCH 45/67] Fix bugs with user page directory, actually call C main function. --- process.c | 4 ++-- start_user_program.s | 11 ++--------- user_program.c | 1 - 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/process.c b/process.c index d76c8f5..cef17ae 100644 --- a/process.c +++ b/process.c @@ -92,7 +92,7 @@ void create_process(struct module* mod) { false, false, USER, - READ_ONLY, + READ_WRITE, true ); pd[page_directory_offset(UPPER_GB_START) - 1] = pde; @@ -111,7 +111,7 @@ void create_process(struct module* mod) { READ_WRITE, true ); - stack_pt[page_table_offset(UPPER_GB_START) - 1] = pte; + stack_pt[1023] = pte; log("Allocated physical page "); print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_4)); log(" and set entry in stack page table\n"); diff --git a/start_user_program.s b/start_user_program.s index d47382a..95c8fe0 100644 --- a/start_user_program.s +++ b/start_user_program.s @@ -3,15 +3,8 @@ extern main mov eax, 0xCAFEBABE ; push argv ; push argc - ; mov eax, [esp] ; accessing the stack currently causes a crash - jmp $ - call main2 + call main jmp $ ; main has returned, eax is return value mov eax, 0xDEADBEEF - jmp $ ; loop forever - - main2: - jmp $ - mov eax, 0x11111111 - jmp $ \ No newline at end of file + jmp $ ; loop forever \ No newline at end of file diff --git a/user_program.c b/user_program.c index be9449d..a690102 100644 --- a/user_program.c +++ b/user_program.c @@ -1,5 +1,4 @@ int main() { - while(1){} if (1) { return 1; } From a5b9565fb68c22b27113442f892c18a26288eeb2 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 19 Nov 2016 13:18:55 -0800 Subject: [PATCH 46/67] Fibonacci user program. --- user_program.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/user_program.c b/user_program.c index a690102..fe5cdc1 100644 --- a/user_program.c +++ b/user_program.c @@ -1,5 +1,17 @@ +int fib(unsigned int n) { + if (n == 0) { + return 0; + } + + if (n == 1) { + return 1; + } + + return fib(n-1) + fib(n-2); +} + int main() { if (1) { - return 1; + return fib(20); // Should return 0x1a6d } -} \ No newline at end of file +} From 13e97cbaaf6f794715440de1ea967f0371d3d2f2 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 20 Nov 2016 15:14:54 -0800 Subject: [PATCH 47/67] Trigger interrupt to enter kernel mode. --- assembly_interface.h | 2 + assembly_interface.s | 9 ++ data_structures/global_descriptor_table.c | 99 ++++++++++++++++++-- data_structures/global_descriptor_table.h | 1 + data_structures/interrupt_descriptor_table.c | 6 +- interrupts.c | 17 ++-- interrupts.h | 7 ++ kmain.c | 4 + loader.h | 1 - loader.s | 1 - memory.h | 2 + start_user_program.s | 14 ++- 12 files changed, 140 insertions(+), 23 deletions(-) diff --git a/assembly_interface.h b/assembly_interface.h index a33efdb..e133914 100644 --- a/assembly_interface.h +++ b/assembly_interface.h @@ -27,6 +27,8 @@ unsigned char inb(unsigned short port); */ void asm_lgdt(void * gdt); +void tss_flush(); + /** load_idt: * Loads the interrupt descriptor table * diff --git a/assembly_interface.s b/assembly_interface.s index b1bf8cf..e5079c5 100644 --- a/assembly_interface.s +++ b/assembly_interface.s @@ -33,6 +33,15 @@ asm_lgdt: lgdt [edx] ret +GLOBAL tss_flush ; Allows our C code to call tss_flush(). +tss_flush: + mov ax, 0x2B ; Load the index of our TSS structure - The index is + ; 0x28, as it is the 5th selector and each is 8 bytes + ; long, but we set the bottom two bits (making 0x2B) + ; so that it has an RPL of 3, not zero. + ltr ax ; Load 0x2B into the task state register. + ret + global load_idt ; load_idt - Loads the interrupt descriptor table (IDT). diff --git a/data_structures/global_descriptor_table.c b/data_structures/global_descriptor_table.c index 9780585..2b31f1f 100644 --- a/data_structures/global_descriptor_table.c +++ b/data_structures/global_descriptor_table.c @@ -1,6 +1,43 @@ #include "global_descriptor_table.h" #include "../assembly_interface.h" +#include "../loader.h" +#include "../stdio.h" +#include "../memory.h" + +// A struct describing a Task State Segment. +struct tss_entry_struct +{ + uint32_t prev_tss; // The previous TSS - if we used hardware task switching this would form a linked list. + uint32_t esp0; // The stack pointer to load when we change to kernel mode. + uint32_t ss0; // The stack segment to load when we change to kernel mode. + uint32_t esp1; // everything below here is unusued now.. + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; +} __packed; +typedef struct tss_entry_struct tss_entry_t; +tss_entry_t tss; // As described here: http://wiki.osdev.org/Global_Descriptor_Table#Structure struct segment_descriptor_t { @@ -12,22 +49,24 @@ struct segment_descriptor_t { uint8_t base_24_31; } __attribute__((packed)); -const uint16_t NULL_SEGMENT_SELECTOR = 0x0; -const uint16_t KERNAL_CODE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 1; -const uint16_t KERNAL_DATA_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 2; -const uint16_t USER_CODE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 3; -const uint16_t USER_DATA_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * 4; - -struct segment_descriptor_t gdt[5]; - enum segment_selector_t { NULL_DESCRIPTOR, // Not used but has to be here KERNAL_CODE_SEGMENT_INDEX, // Offset 0x8 KERNAL_DATA_SEGMENT_INDEX, // Offset 0x10 USER_CODE_SEGMENT_INDEX, // Offset 0x18 - USER_DATA_SEGMENT_INDEX // Offset 0x20 + USER_DATA_SEGMENT_INDEX, // Offset 0x20 + TASK_STATE_SEGMENT_INDEX // Offset 0x28 }; +const uint16_t NULL_SEGMENT_SELECTOR = 0x0; +const uint16_t KERNAL_CODE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * KERNAL_CODE_SEGMENT_INDEX; +const uint16_t KERNAL_DATA_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * KERNAL_DATA_SEGMENT_INDEX; +const uint16_t USER_CODE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * USER_CODE_SEGMENT_INDEX; +const uint16_t USER_DATA_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * USER_DATA_SEGMENT_INDEX; +const uint16_t TASK_STATE_SEGMENT_SELECTOR = sizeof(struct segment_descriptor_t) * TASK_STATE_SEGMENT_INDEX; + +struct segment_descriptor_t gdt[6]; + // a pointer to the global descriptor table // passed by reference to the LGDT instruction struct gdt_description_structure_t { @@ -35,6 +74,48 @@ struct gdt_description_structure_t { uint32_t offset; } __attribute__((packed)) gdt_description_structure; +void initialize_tss() { + uint32_t tss_base = (uint32_t) &tss; + uint32_t tss_limit = sizeof(tss); + log("tss_base: "); + print_uint32(LOG, tss_base); + log("\n"); + log("tss_limit: "); + print_uint32(LOG, tss_limit); + log("\n"); + gdt[TASK_STATE_SEGMENT_INDEX].limit_0_15 = tss_limit & 0xFFFF; + gdt[TASK_STATE_SEGMENT_INDEX].base_0_15 = tss_base & 0xFFFF; + gdt[TASK_STATE_SEGMENT_INDEX].base_16_23 = (tss_base & 0xFF0000) >> 16; + gdt[TASK_STATE_SEGMENT_INDEX].access_byte = 0b11101001; + gdt[TASK_STATE_SEGMENT_INDEX].flags_and_limit_16_19 = tss_limit & 0xF0000; + gdt[TASK_STATE_SEGMENT_INDEX].base_24_31 = (tss_base & 0xFF000000) >> 24; + + tss.ss0 = KERNAL_DATA_SEGMENT_SELECTOR; + tss.esp0 = ((uint32_t) &kernel_stack_lowest_address + KERNEL_STACK_SIZE) - 4; + + log("KERNEL_STACK_SIZE: "); + print_uint32(LOG, (uint32_t) KERNEL_STACK_SIZE); + log("\n"); + + log("kernel_stack_lowest_address: "); + print_uint32(LOG, (uint32_t) kernel_stack_lowest_address); + log("\n"); + + log("&kernel_stack_lowest_address: "); + print_uint32(LOG, (uint32_t) (&kernel_stack_lowest_address)); + log("\n"); + + log("tss.ss0: "); + print_uint32(LOG, tss.ss0); + log("\n"); + + log("tss.esp0: "); + print_uint32(LOG, tss.esp0); + log("\n"); + + tss_flush(); +} + void initialize_gdt() { gdt_description_structure.size = sizeof(gdt) - 1; gdt_description_structure.offset = (uint32_t) gdt; diff --git a/data_structures/global_descriptor_table.h b/data_structures/global_descriptor_table.h index f0c7025..6cf4f73 100644 --- a/data_structures/global_descriptor_table.h +++ b/data_structures/global_descriptor_table.h @@ -8,5 +8,6 @@ const uint16_t KERNAL_CODE_SEGMENT_SELECTOR; const uint16_t KERNAL_DATA_SEGMENT_SELECTOR; void initialize_gdt(); +void initialize_tss(); #endif /* INCLUDE_GLOBAL_DESCRIPTOR_TABLE_H */ \ No newline at end of file diff --git a/data_structures/interrupt_descriptor_table.c b/data_structures/interrupt_descriptor_table.c index 3a6b925..66a752f 100644 --- a/data_structures/interrupt_descriptor_table.c +++ b/data_structures/interrupt_descriptor_table.c @@ -4,6 +4,7 @@ #include "../assembly_interface.h" #include "../types.h" #include "global_descriptor_table.h" +#include "../interrupts.h" // a pointer to the interrupt descriptor table // passed by reference to the LIDT instruction @@ -288,7 +289,8 @@ void initialize_idt() { uint16_t selector = KERNAL_CODE_SEGMENT_SELECTOR; uint8_t zero = 0x00; - uint8_t type_attr = 0x8E; + uint8_t type_attr = 0b10001110; + uint8_t user_type_attr = 0b11101110; for (int i = 0; i < 256; i++) { uint32_t interrupt_handler_address = interrupt_handler_addresses[i]; @@ -302,5 +304,7 @@ void initialize_idt() { idt[i].offset_16_31 = offset_16_31; } + idt[INT_SYSCALL].type_attr = user_type_attr; + load_idt(&idt_description_structure); } \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index 5813c44..81a3e64 100644 --- a/interrupts.c +++ b/interrupts.c @@ -5,14 +5,10 @@ #include "data_structures/symbol_table.h" #include "drivers/keyboard.h" #include "drivers/pic.h" +#include "loader.h" +#include "memory.h" #include "stdio.h" -#define INT_KEYBOARD 0x00000009 -#define INT_GENERAL_PROTECTION_FAULT 0x0000000D -#define INT_PAGE_FAULT 0x0000000E -#define INT_SOFTWARE 0x00000031 -#define INT_OUT_OF_MEMORY 0x00000032 - void log_stack_trace_line(uint32_t eip) { print_uint32(LOG, eip); log(" : "); @@ -36,7 +32,8 @@ void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, st eip -= 4; // eip actually points one past the instruction that triggered interrupt log_stack_trace_line(eip); uint32_t ebp = cpu->ebp; - while (ebp & 0xC0100000) { + uint32_t kernel_stack_highest_address = ((uint32_t) &kernel_stack_lowest_address + KERNEL_STACK_SIZE - 4); + while (ebp <= kernel_stack_highest_address && ebp >= ((uint32_t) &kernel_stack_lowest_address)) { eip = ((uint32_t*) ebp)[1]; log_stack_trace_line(eip); @@ -52,6 +49,7 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t keyboard_interrupt_handler(); break; case(INT_PAGE_FAULT): + log_interrupt_details("INT_PAGE_FAULT", error_code, eip, &cpu); if ((error_code & 0b1) == 0) { // Caused by page-not-present page_in((void*) cpu.cr2); @@ -88,6 +86,10 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t log_interrupt_details("INT_SOFTWARE", error_code, eip, &cpu); break; + case(INT_SYSCALL): + log_interrupt_details("INT_SYSCALL", error_code, eip, &cpu); + break; + case(INT_OUT_OF_MEMORY): log_interrupt_details("INT_OUT_OF_MEMORY", error_code, eip, &cpu); while(true){} @@ -98,6 +100,7 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t print_uint32(LOG, interrupt_number); log("\n"); log_interrupt_details("INT_UNKNOWN", error_code, eip, &cpu); + while(1){} break; } diff --git a/interrupts.h b/interrupts.h index 5492da4..cfc48b5 100644 --- a/interrupts.h +++ b/interrupts.h @@ -3,6 +3,13 @@ #include "types.h" +#define INT_KEYBOARD 0x00000009 +#define INT_GENERAL_PROTECTION_FAULT 0x0000000D +#define INT_PAGE_FAULT 0x0000000E +#define INT_SOFTWARE 0x00000031 +#define INT_OUT_OF_MEMORY 0x00000032 +#define INT_SYSCALL 0x00000080 + struct cpu_state { uint32_t cr2; uint32_t ebp; diff --git a/kmain.c b/kmain.c index ae2c944..d1728d8 100644 --- a/kmain.c +++ b/kmain.c @@ -119,6 +119,10 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_uint32(LOG, value); log("\n"); + log("- Initializing task state segment...\n"); + initialize_tss(); + log(" - done\n"); + log("- Dynamically allocating a struct...\n"); struct test_struct_t* test = (struct test_struct_t*) malloc(sizeof(struct test_struct_t)); log(" - done\n"); diff --git a/loader.h b/loader.h index f1c6910..dd9fa55 100644 --- a/loader.h +++ b/loader.h @@ -4,7 +4,6 @@ #include "types.h" uint32_t KERNEL_VIRTUAL_BASE; -uint32_t KERNEL_STACK_SIZE; void * kernel_stack_lowest_address; void * PageDirectoryVirtualAddress; diff --git a/loader.s b/loader.s index 57a56fb..3571b7b 100644 --- a/loader.s +++ b/loader.s @@ -103,7 +103,6 @@ higher_half_loader: mov esp, kernel_stack_lowest_address + KERNEL_STACK_SIZE ; point esp to the start of the ; stack (end of memory area) - add ebx, KERNEL_VIRTUAL_BASE ; make the address virtual push ebx ; GRUB stores a pointer to a struct in the register ebx that, ; among other things, describes at which addresses the modules are loaded. diff --git a/memory.h b/memory.h index f86ca1e..18cee9c 100644 --- a/memory.h +++ b/memory.h @@ -10,4 +10,6 @@ #define FIRST_PAGE_TABLE_ADDRESS (void*) 0xFFC00000 // 4 MB from end #define PAGE_DIRECTORY_ADDRESS (void*) 0xFFFFF000 // 4 KB from end +#define KERNEL_STACK_SIZE 4096 + #endif /* INCLUDE_MEMORY_H */ \ No newline at end of file diff --git a/start_user_program.s b/start_user_program.s index 95c8fe0..90bc463 100644 --- a/start_user_program.s +++ b/start_user_program.s @@ -3,8 +3,14 @@ extern main mov eax, 0xCAFEBABE ; push argv ; push argc - call main - jmp $ - ; main has returned, eax is return value + call interrupt mov eax, 0xDEADBEEF - jmp $ ; loop forever \ No newline at end of file + ; main has returned, eax is return value + jmp $ ; loop forever + +interrupt: + push ebp ; make the caller show up in the stack trace + mov ebp, esp + int 0x80 + pop ebp + ret \ No newline at end of file From c9379bb8067dde0ef3036d95095a4539111669e4 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 12:50:59 -0800 Subject: [PATCH 48/67] Make a syscall. --- Makefile | 2 +- interrupts.c | 23 +++++++++++++++++++++++ process.c | 2 -- start_user_program.s | 12 ++---------- stdlib/assembly_functions.h | 8 ++++++++ stdlib/assembly_functions.s | 10 ++++++++++ user_program.c | 10 +++++++--- 7 files changed, 51 insertions(+), 16 deletions(-) create mode 100644 stdlib/assembly_functions.h create mode 100644 stdlib/assembly_functions.s diff --git a/Makefile b/Makefile index e8ae014..afba80a 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ start_user_program.o: start_user_program.s user_program.o: user_program.c $(GCC) $(CFLAGS) $< -o $@ -user_program.bin: user_program.o start_user_program.o +user_program.bin: user_program.o start_user_program.o stdlib/assembly_functions.o $(LD) -T link_user_program.ld -melf_i386 $^ -o $@ os.iso: kernel.elf user_program.bin menu.lst diff --git a/interrupts.c b/interrupts.c index 81a3e64..ff8cb9e 100644 --- a/interrupts.c +++ b/interrupts.c @@ -43,6 +43,28 @@ void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, st log("--------------------\n"); } +void sys_write_to_screen(char* s) { + log("sys_write_to_screen("); + print_uint32(LOG, (uint32_t) s); + log(")\n"); + printf(s); +} + +void handle_syscall(struct cpu_state* cpu) { + uint32_t syscall_num = cpu->eax; + + switch (syscall_num) { + case (1): + sys_write_to_screen((char*) cpu->ebx); + break; + default: + log("Unknown syscall: "); + print_uint32(LOG, syscall_num); + log("\n"); + while(1){} + } +} + void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip) { switch(interrupt_number) { case(INT_KEYBOARD): @@ -88,6 +110,7 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t case(INT_SYSCALL): log_interrupt_details("INT_SYSCALL", error_code, eip, &cpu); + handle_syscall(&cpu); break; case(INT_OUT_OF_MEMORY): diff --git a/process.c b/process.c index cef17ae..62e1b5a 100644 --- a/process.c +++ b/process.c @@ -133,8 +133,6 @@ void create_process(struct module* mod) { log("\n"); for (uint32_t i = 0; i < program_length_bytes; i++) { ((uint8_t*)user_code)[i] = ((uint8_t*)mod_virtual_start)[i]; - print_uint8(LOG, ((uint8_t*)mod_virtual_start)[i]); - log("\n"); } log("Done copying code.\n"); diff --git a/start_user_program.s b/start_user_program.s index 90bc463..79d2163 100644 --- a/start_user_program.s +++ b/start_user_program.s @@ -3,14 +3,6 @@ extern main mov eax, 0xCAFEBABE ; push argv ; push argc - call interrupt - mov eax, 0xDEADBEEF + call main ; main has returned, eax is return value - jmp $ ; loop forever - -interrupt: - push ebp ; make the caller show up in the stack trace - mov ebp, esp - int 0x80 - pop ebp - ret \ No newline at end of file + jmp $ ; loop forever \ No newline at end of file diff --git a/stdlib/assembly_functions.h b/stdlib/assembly_functions.h new file mode 100644 index 0000000..5f34db8 --- /dev/null +++ b/stdlib/assembly_functions.h @@ -0,0 +1,8 @@ +#ifndef INCLUDE_ASSEMBLY_FUNCTIONS_H +#define INCLUDE_ASSEMBLY_FUNCTIONS_H + +#include "../types.h" + +void write_to_screen(char* s); + +#endif /* INCLUDE_ASSEMBLY_FUNCTIONS_H */ \ No newline at end of file diff --git a/stdlib/assembly_functions.s b/stdlib/assembly_functions.s new file mode 100644 index 0000000..4a5a55c --- /dev/null +++ b/stdlib/assembly_functions.s @@ -0,0 +1,10 @@ +section .text +global write_to_screen +; write_to_screen +; stack: [esp + 4] string +; [esp ] return address +write_to_screen: + mov eax, 1 + mov ebx, [esp+4] + int 0x80 + ret ; return to the calling function diff --git a/user_program.c b/user_program.c index fe5cdc1..51f069d 100644 --- a/user_program.c +++ b/user_program.c @@ -1,3 +1,5 @@ +#include "stdlib/assembly_functions.h" + int fib(unsigned int n) { if (n == 0) { return 0; @@ -11,7 +13,9 @@ int fib(unsigned int n) { } int main() { - if (1) { - return fib(20); // Should return 0x1a6d - } + int result = fib(20); // Should be 0x1a6d + + write_to_screen("Hello World\n"); + + return result; } From 31153309a248d0582dc460276aff0965d9e459c8 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 12:59:20 -0800 Subject: [PATCH 49/67] Make message show up on screen. --- kmain.c | 56 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/kmain.c b/kmain.c index d1728d8..1e93815 100644 --- a/kmain.c +++ b/kmain.c @@ -12,33 +12,33 @@ #include "stdlib.h" #include "types.h" -static char *welcome_string = "" -" " -" " -" " -" " -" | | | | " -" ___ ___ | |_ __ _ ___ | | __ " -" / __| / __| | __| / _` | / __| | |/ / " -" | (__ \\__ \\ | |_ | (_| | | (__ | < " -" \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " -" " -" " -" ____ _____ " -" / __ \\ / ____| " -" | | | | | (___ " -" | | | | \\___ \\ " -" | |__| | ____) | " -" \\____/ |_____/ " -" " -" " -" " -" " -" " -" " -" " -" " -""; +// static char *welcome_string = "" +// " " +// " " +// " " +// " " +// " | | | | " +// " ___ ___ | |_ __ _ ___ | | __ " +// " / __| / __| | __| / _` | / __| | |/ / " +// " | (__ \\__ \\ | |_ | (_| | | (__ | < " +// " \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " +// " " +// " " +// " ____ _____ " +// " / __ \\ / ____| " +// " | | | | | (___ " +// " | | | | \\___ \\ " +// " | |__| | ____) | " +// " \\____/ |_____/ " +// " " +// " " +// " " +// " " +// " " +// " " +// " " +// " " +// ""; uint32_t trigger_page_fault() { uint32_t* unmapped_address = (uint32_t *) 0x400000; // 4 MB @@ -57,7 +57,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { clear_screen(); - printf(welcome_string); + // printf(welcome_string); serial_init(); log("\n--------------------\ncstackOS is booting!\n--------------------\n\n"); From afc5ac15e8936f5c85289f90e3af33f0fce4c764 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 15:10:56 -0800 Subject: [PATCH 50/67] Scroll screen when new line goes off the screen. --- drivers/frame_buffer.c | 45 +++++++++++++++++++++++++++------ kmain.c | 56 +++++++++++++++++++++--------------------- user_program.c | 2 +- 3 files changed, 66 insertions(+), 37 deletions(-) diff --git a/drivers/frame_buffer.c b/drivers/frame_buffer.c index beb71b2..cd3b7da 100644 --- a/drivers/frame_buffer.c +++ b/drivers/frame_buffer.c @@ -18,6 +18,8 @@ char *fb = (char *) 0xC00B8000; uint16_t cursor_pos = 0; +uint8_t buffer[FB_CELLS*2]; + /** fb_write_cell: * Writes a character with the given foreground and background to position i * in the framebuffer. @@ -30,8 +32,24 @@ uint16_t cursor_pos = 0; void fb_write_cell(unsigned int cell, char c, unsigned char fg, unsigned char bg) { int i = cell*2; - fb[i] = c; - fb[i + 1] = ((bg & 0x0F) << 4) | (fg & 0x0F); + buffer[i] = fb[i] = c; + + buffer[i+1] = fb[i + 1] = ((bg & 0x0F) << 4) | (fg & 0x0F); +} + +void scroll() +{ + uint32_t num_cells_to_copy = FB_CELLS - FB_COLS; + for (uint32_t cell = 0; cell < num_cells_to_copy; cell++) { + int i = cell*2; + buffer[i] = fb[i] = buffer[i+FB_COLS*2]; + buffer[i+1] = fb[i+1] = buffer[i+1+FB_COLS*2]; + } + uint32_t bytes_per_row = FB_COLS*2; + uint32_t last_byte_index = FB_CELLS*2 - 1; + for (uint32_t i = 0; i < bytes_per_row; i++) { + buffer[last_byte_index - i] = fb[last_byte_index - i] = 0; + } } void clear_screen() @@ -54,14 +72,25 @@ void move_cursor_to_pos(unsigned short pos) outb(FB_DATA_PORT, pos & 0x00FF); } -void fb_write_byte(uint8_t b) { - fb_write_cell(cursor_pos, b, FB_WHITE, FB_BLACK); - cursor_pos++; +uint16_t beginning_of_line(uint16_t pos) { + return pos / FB_COLS * FB_COLS; +} - // Stop the cursor from going off the screen - // TODO: advance the screen - if (cursor_pos < FB_CELLS) { +uint16_t beginning_of_next_line(uint16_t pos) { + return beginning_of_line(pos + FB_COLS); +} + +void fb_write_byte(uint8_t b) { + if (b == '\n') { + cursor_pos = beginning_of_next_line(cursor_pos); + while (cursor_pos >= FB_CELLS) { + scroll(); + cursor_pos -= FB_COLS; + } move_cursor_to_pos(cursor_pos); + } else { + fb_write_cell(cursor_pos, b, FB_WHITE, FB_BLACK); + cursor_pos++; } } diff --git a/kmain.c b/kmain.c index 1e93815..d1728d8 100644 --- a/kmain.c +++ b/kmain.c @@ -12,33 +12,33 @@ #include "stdlib.h" #include "types.h" -// static char *welcome_string = "" -// " " -// " " -// " " -// " " -// " | | | | " -// " ___ ___ | |_ __ _ ___ | | __ " -// " / __| / __| | __| / _` | / __| | |/ / " -// " | (__ \\__ \\ | |_ | (_| | | (__ | < " -// " \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " -// " " -// " " -// " ____ _____ " -// " / __ \\ / ____| " -// " | | | | | (___ " -// " | | | | \\___ \\ " -// " | |__| | ____) | " -// " \\____/ |_____/ " -// " " -// " " -// " " -// " " -// " " -// " " -// " " -// " " -// ""; +static char *welcome_string = "" +" " +" " +" " +" " +" | | | | " +" ___ ___ | |_ __ _ ___ | | __ " +" / __| / __| | __| / _` | / __| | |/ / " +" | (__ \\__ \\ | |_ | (_| | | (__ | < " +" \\___| |___/ \\__| \\__,_| \\___| |_|\\_\\ " +" " +" " +" ____ _____ " +" / __ \\ / ____| " +" | | | | | (___ " +" | | | | \\___ \\ " +" | |__| | ____) | " +" \\____/ |_____/ " +" " +" " +" " +" " +" " +" " +" " +" " +""; uint32_t trigger_page_fault() { uint32_t* unmapped_address = (uint32_t *) 0x400000; // 4 MB @@ -57,7 +57,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { clear_screen(); - // printf(welcome_string); + printf(welcome_string); serial_init(); log("\n--------------------\ncstackOS is booting!\n--------------------\n\n"); diff --git a/user_program.c b/user_program.c index 51f069d..368ed70 100644 --- a/user_program.c +++ b/user_program.c @@ -15,7 +15,7 @@ int fib(unsigned int n) { int main() { int result = fib(20); // Should be 0x1a6d - write_to_screen("Hello World\n"); + write_to_screen("\n----\nHello World!\n----\n"); return result; } From 62635e97a8c932400051b5e8a398e55500b08cfb Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 15:32:37 -0800 Subject: [PATCH 51/67] Detect % in format string. --- kmain.c | 2 ++ process.c | 56 ------------------------------------------------------- stdio.c | 21 ++++++++++++++++++++- 3 files changed, 22 insertions(+), 57 deletions(-) diff --git a/kmain.c b/kmain.c index d1728d8..bb96794 100644 --- a/kmain.c +++ b/kmain.c @@ -144,6 +144,8 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_uint32(LOG, (uint32_t) sp); log("\n"); + fprintf(LOG, "%%s -> %s\n", "test"); + log("- Creating a user process...\n"); create_process(first_module(mbinfo)); log(" - done\n"); diff --git a/process.c b/process.c index 62e1b5a..42aa3b2 100644 --- a/process.c +++ b/process.c @@ -18,26 +18,11 @@ void create_process(struct module* mod) { p->pid = next_pid; next_pid += 1; - log("Created process descriptor:\n"); - log("Virtual address: "); - print_uint32(LOG, (uint32_t) p); - log("\n"); - - log("pid: "); - print_uint32(LOG, (uint32_t) p->pid); - log("\n"); - - log("Allocating a physical page for the new page directory\n"); page_in(TMP_PAGE_0); page_directory_t pd = TMP_PAGE_0; p->pd = pd; - log("Paged into TMP_PAGE_0\n"); - log("Physical address: "); void* pd_physical_address = virtual_to_physical(pd); - print_uint32(LOG, (uint32_t) pd_physical_address); - log("\n"); - log("Make page table recursive\n"); uint32_t pde = make_page_directory_entry( pd_physical_address, FOUR_KB, @@ -49,7 +34,6 @@ void create_process(struct module* mod) { ); pd[1023] = pde; - log("Allocating a page table for user code\n"); page_in(TMP_PAGE_1); page_table_t code_pt = TMP_PAGE_1; pde = make_page_directory_entry( @@ -62,11 +46,7 @@ void create_process(struct module* mod) { true ); pd[0] = pde; - log("Allocated physical page "); - print_uint32(LOG, (uint32_t) virtual_to_physical(code_pt)); - log(" and set entry in page directory\n"); - log("Allocating a page for user code\n"); page_in(TMP_PAGE_2); void* user_code = TMP_PAGE_2; uint32_t pte = make_page_table_entry( @@ -79,11 +59,7 @@ void create_process(struct module* mod) { true ); code_pt[0] = pte; - log("Allocated physical page "); - print_uint32(LOG, (uint32_t) virtual_to_physical(user_code)); - log(" and set entry in code page table\n"); - log("Allocating a page table for user stack\n"); page_in(TMP_PAGE_3); page_table_t stack_pt = TMP_PAGE_3; pde = make_page_directory_entry( @@ -96,11 +72,7 @@ void create_process(struct module* mod) { true ); pd[page_directory_offset(UPPER_GB_START) - 1] = pde; - log("Allocated physical page "); - print_uint32(LOG, (uint32_t) virtual_to_physical(stack_pt)); - log(" and set entry in page directory\n"); - log("Allocating a page for user stack\n"); page_in(TMP_PAGE_4); pte = make_page_table_entry( virtual_to_physical(TMP_PAGE_4), @@ -112,47 +84,19 @@ void create_process(struct module* mod) { true ); stack_pt[1023] = pte; - log("Allocated physical page "); - print_uint32(LOG, (uint32_t) virtual_to_physical(TMP_PAGE_4)); - log(" and set entry in stack page table\n"); - log("Mapping in kernel. Copying entries from current page directory.\n"); map_kernel_into_page_directory(pd); - log("Page directory:\n"); - print_page_table(LOG, pd); - - log("Copying user program into code section:\n"); uint32_t program_length_bytes = mod->mod_end - mod->mod_start; void* mod_virtual_start = (void*) (mod->mod_start + UPPER_GB_START); - log("Copying "); - print_uint32(LOG, program_length_bytes); - log(" bytes from "); - print_uint32(LOG, (uint32_t) mod_virtual_start); - log("\n"); for (uint32_t i = 0; i < program_length_bytes; i++) { ((uint8_t*)user_code)[i] = ((uint8_t*)mod_virtual_start)[i]; } - log("Done copying code.\n"); - log("Disabling hardware interrupts.\n"); disable_hardware_interrupts(); - log("Page directory starts as "); - print_uint32(LOG, (uint32_t) virtual_to_physical(PAGE_DIRECTORY_ADDRESS)); - log("\n"); - log("Setting page directory\n"); set_page_directory(virtual_to_physical(pd)); - log("Page directory physical address is now "); - print_uint32(LOG, (uint32_t) virtual_to_physical(PAGE_DIRECTORY_ADDRESS)); - log("\n"); - - uint32_t* stack_highest_address = (uint32_t*) 0xbffffffb; - uint32_t value_on_stack = *stack_highest_address; - log("Value on stack: "); - print_uint32(LOG, value_on_stack); - log("\n"); log("Entering user mode...\n"); enter_user_mode(); diff --git a/stdio.c b/stdio.c index 2aa19e0..392fec7 100644 --- a/stdio.c +++ b/stdio.c @@ -28,12 +28,31 @@ void print_bytes(FILE stream, uint8_t * bytes, uint32_t num_bytes) { } } +enum format_string_mode {NORMAL, COMMAND}; int fprintf (FILE stream, const char * format, ...) { write_byte_t write_byte = write_byte_function(stream); int i = 0; + enum format_string_mode mode = NORMAL; while (format[i]) { - write_byte(format[i]); + switch (mode) { + case (NORMAL): + if (format[i] == '%') { + mode = COMMAND; + } else { + write_byte(format[i]); + } + break; + case (COMMAND): + if (format[i] == '%') { + write_byte('%'); + mode = NORMAL; + } else { + write_byte('?'); + mode = NORMAL; + } + break; + } i++; } return i; From b1c91bdca0999871e1ac428a4b8cbba81abff44b Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 17:10:34 -0800 Subject: [PATCH 52/67] Support varargs, string command. --- stdarg.h | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ stdio.c | 15 +++++++ 2 files changed, 148 insertions(+) create mode 100644 stdarg.h diff --git a/stdarg.h b/stdarg.h new file mode 100644 index 0000000..8be7b67 --- /dev/null +++ b/stdarg.h @@ -0,0 +1,133 @@ +/* Copyright (C) 1989, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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, or (at your option) +any later version. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you include this header file into source + files compiled by GCC, this header file does not by itself cause + the resulting executable to be covered by the GNU General Public + License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General + Public License. */ + +/* + * ISO C Standard: 7.15 Variable arguments + */ + +#ifndef _STDARG_H +#ifndef _ANSI_STDARG_H_ +#ifndef __need___va_list +#define _STDARG_H +#define _ANSI_STDARG_H_ +#endif /* not __need___va_list */ +#undef __need___va_list + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +/* Define the standard macros for the user, + if this invocation was from the user program. */ +#ifdef _STDARG_H + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L +#define va_copy(d,s) __builtin_va_copy(d,s) +#endif +#define __va_copy(d,s) __builtin_va_copy(d,s) + +/* Define va_list, if desired, from __gnuc_va_list. */ +/* We deliberately do not define va_list when called from + stdio.h, because ANSI C says that stdio.h is not supposed to define + va_list. stdio.h needs to have access to that data type, + but must not use that name. It should use the name __gnuc_va_list, + which is safe because it is reserved for the implementation. */ + +#ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */ +#undef _VA_LIST +#endif + +#ifdef _BSD_VA_LIST +#undef _BSD_VA_LIST +#endif + +#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST)) +/* SVR4.2 uses _VA_LIST for an internal alias for va_list, + so we must avoid testing it and setting it here. + SVR4 uses _VA_LIST as a flag in stdarg.h, but we should + have no conflict with that. */ +#ifndef _VA_LIST_ +#define _VA_LIST_ +#ifdef __i860__ +#ifndef _VA_LIST +#define _VA_LIST va_list +#endif +#endif /* __i860__ */ +typedef __gnuc_va_list va_list; +#ifdef _SCO_DS +#define __VA_LIST +#endif +#endif /* _VA_LIST_ */ +#else /* not __svr4__ || _SCO_DS */ + +/* The macro _VA_LIST_ is the same thing used by this file in Ultrix. + But on BSD NET2 we must not test or define or undef it. + (Note that the comments in NET 2's ansi.h + are incorrect for _VA_LIST_--see stdio.h!) */ +#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) +/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */ +#ifndef _VA_LIST_DEFINED +/* The macro _VA_LIST is used in SCO Unix 3.2. */ +#ifndef _VA_LIST +/* The macro _VA_LIST_T_H is used in the Bull dpx2 */ +#ifndef _VA_LIST_T_H +/* The macro __va_list__ is used by BeOS. */ +#ifndef __va_list__ +typedef __gnuc_va_list va_list; +#endif /* not __va_list__ */ +#endif /* not _VA_LIST_T_H */ +#endif /* not _VA_LIST */ +#endif /* not _VA_LIST_DEFINED */ +#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)) +#define _VA_LIST_ +#endif +#ifndef _VA_LIST +#define _VA_LIST +#endif +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED +#endif +#ifndef _VA_LIST_T_H +#define _VA_LIST_T_H +#endif +#ifndef __va_list__ +#define __va_list__ +#endif + +#endif /* not _VA_LIST_, except on certain systems */ + +#endif /* not __svr4__ */ + +#endif /* _STDARG_H */ + +#endif /* not _ANSI_STDARG_H_ */ +#endif /* not _STDARG_H */ \ No newline at end of file diff --git a/stdio.c b/stdio.c index 392fec7..44860a8 100644 --- a/stdio.c +++ b/stdio.c @@ -2,6 +2,8 @@ #include "drivers/frame_buffer.h" #include "drivers/serial_port.h" +#include "stdarg.h" + typedef void (*write_byte_t)(uint8_t); write_byte_t write_byte_function(FILE stream) { @@ -28,10 +30,20 @@ void print_bytes(FILE stream, uint8_t * bytes, uint32_t num_bytes) { } } +void write_string(write_byte_t write_byte, char* s) { + while(*s) { + write_byte(*s); + s++; + } +} + enum format_string_mode {NORMAL, COMMAND}; int fprintf (FILE stream, const char * format, ...) { write_byte_t write_byte = write_byte_function(stream); + va_list vl; + va_start(vl,format); + int i = 0; enum format_string_mode mode = NORMAL; while (format[i]) { @@ -47,6 +59,9 @@ int fprintf (FILE stream, const char * format, ...) { if (format[i] == '%') { write_byte('%'); mode = NORMAL; + } else if (format[i] == 's') { + write_string(write_byte, (char*) va_arg(vl,char*)); + mode = NORMAL; } else { write_byte('?'); mode = NORMAL; From ef8ec250a3c2a96b4f14125a228d916fe0527123 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 18:05:33 -0800 Subject: [PATCH 53/67] Add more printf options. --- kmain.c | 2 +- stdio.c | 112 +++++++++++++++++++++++++++++++++----------------------- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/kmain.c b/kmain.c index bb96794..44024a3 100644 --- a/kmain.c +++ b/kmain.c @@ -144,7 +144,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_uint32(LOG, (uint32_t) sp); log("\n"); - fprintf(LOG, "%%s -> %s\n", "test"); + fprintf(LOG, "%%s -> %s, %%c -> %c, %%x -> %x, %%X -> %X\n", "test", 'A', 0xDEADBEEF, 0xDEADBEEF); log("- Creating a user process...\n"); create_process(first_module(mbinfo)); diff --git a/stdio.c b/stdio.c index 44860a8..d0d0a2a 100644 --- a/stdio.c +++ b/stdio.c @@ -37,43 +37,7 @@ void write_string(write_byte_t write_byte, char* s) { } } -enum format_string_mode {NORMAL, COMMAND}; -int fprintf (FILE stream, const char * format, ...) { - write_byte_t write_byte = write_byte_function(stream); - - va_list vl; - va_start(vl,format); - - int i = 0; - enum format_string_mode mode = NORMAL; - while (format[i]) { - switch (mode) { - case (NORMAL): - if (format[i] == '%') { - mode = COMMAND; - } else { - write_byte(format[i]); - } - break; - case (COMMAND): - if (format[i] == '%') { - write_byte('%'); - mode = NORMAL; - } else if (format[i] == 's') { - write_string(write_byte, (char*) va_arg(vl,char*)); - mode = NORMAL; - } else { - write_byte('?'); - mode = NORMAL; - } - break; - } - i++; - } - return i; -} - -void print_half_byte(write_byte_t write_byte, uint8_t half_byte) { +void write_half_byte(write_byte_t write_byte, uint8_t half_byte, bool upcase) { switch (half_byte) { case 0x0: write_byte('0'); @@ -106,26 +70,82 @@ void print_half_byte(write_byte_t write_byte, uint8_t half_byte) { write_byte('9'); break; case 0xA: - write_byte('A'); + write_byte(upcase ? 'A' : 'a'); break; case 0xB: - write_byte('B'); + write_byte(upcase ? 'B' : 'b'); break; case 0xC: - write_byte('C'); + write_byte(upcase ? 'C' : 'c'); break; case 0xD: - write_byte('D'); + write_byte(upcase ? 'D' : 'd'); break; case 0xE: - write_byte('E'); + write_byte(upcase ? 'E' : 'e'); break; case 0xF: - write_byte('F'); + write_byte(upcase ? 'F' : 'f'); break; } } +enum format_string_mode {NORMAL, COMMAND}; +int fprintf (FILE stream, const char * format, ...) { + write_byte_t write_byte = write_byte_function(stream); + + va_list vl; + va_start(vl,format); + + int i = 0; + enum format_string_mode mode = NORMAL; + uint32_t vararg; + while (format[i]) { + switch (mode) { + case (NORMAL): + if (format[i] == '%') { + mode = COMMAND; + } else { + write_byte(format[i]); + } + break; + case (COMMAND): + if (format[i] == '%') { + write_byte('%'); + mode = NORMAL; + } else if (format[i] == 'c') { + write_byte((uint32_t) va_arg(vl,uint32_t)); + mode = NORMAL; + } else if (format[i] == 's') { + write_string(write_byte, (char*) va_arg(vl,char*)); + mode = NORMAL; + } else if (format[i] == 'x') { + write_byte('0'); + write_byte('x'); + vararg = va_arg(vl,uint32_t); + for (int i = 7; i >=0; i--) { + write_half_byte(write_byte, (vararg >> (4*i)) & 0x0F, false); + } + mode = NORMAL; + } else if (format[i] == 'X') { + write_byte('0'); + write_byte('x'); + vararg = va_arg(vl,uint32_t); + for (int i = 7; i >=0; i--) { + write_half_byte(write_byte, (vararg >> (4*i)) & 0x0F, true); + } + mode = NORMAL; + } else { + write_byte('?'); + mode = NORMAL; + } + break; + } + i++; + } + return i; +} + void print_uint8(FILE stream, uint8_t data) { write_byte_t write_byte = write_byte_function(stream); @@ -134,7 +154,7 @@ void print_uint8(FILE stream, uint8_t data) { write_byte('x'); for (int i = 1; i >=0; i--) { half_byte = (data >> (4*i)) & 0x0F; - print_half_byte(write_byte, half_byte); + write_half_byte(write_byte, half_byte, true); } } @@ -146,7 +166,7 @@ void print_uint16(FILE stream, uint16_t data) { write_byte('x'); for (int i = 3; i >=0; i--) { half_byte = (data >> (4*i)) & 0x0F; - print_half_byte(write_byte, half_byte); + write_half_byte(write_byte, half_byte, true); } } @@ -158,7 +178,7 @@ void print_uint32(FILE stream, uint32_t data) { write_byte('x'); for (int i = 7; i >=0; i--) { half_byte = (data >> (4*i)) & 0x0F; - print_half_byte(write_byte, half_byte); + write_half_byte(write_byte, half_byte, true); } } From 78414ea6d6c2510ebd637a8b860415507c99fc0f Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 18:33:27 -0800 Subject: [PATCH 54/67] Add more printf types. --- kmain.c | 6 +++++- stdio.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/kmain.c b/kmain.c index 44024a3..0ba88a1 100644 --- a/kmain.c +++ b/kmain.c @@ -144,7 +144,11 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { print_uint32(LOG, (uint32_t) sp); log("\n"); - fprintf(LOG, "%%s -> %s, %%c -> %c, %%x -> %x, %%X -> %X\n", "test", 'A', 0xDEADBEEF, 0xDEADBEEF); + fprintf( + LOG, + "%%s -> %s, %%c -> %c, %%x -> %x, %%X -> %X, %%u -> %u, %%i -> %i, %%o -> %o\n", + "test", 'A', 0xDEADBEEF, 0xDEADBEEF, 12345, -12345, 12345 + ); log("- Creating a user process...\n"); create_process(first_module(mbinfo)); diff --git a/stdio.c b/stdio.c index d0d0a2a..695b9bf 100644 --- a/stdio.c +++ b/stdio.c @@ -90,6 +90,54 @@ void write_half_byte(write_byte_t write_byte, uint8_t half_byte, bool upcase) { } } +void write_uint(write_byte_t write_byte, uint32_t value) { + char output[10]; + for (int place = 0; place < 10; place++) { + output[place] = value % 10; + value = value / 10; + } + + bool past_leading_zeroes = false; + for (int place = 10; place >= 0; place--) { + if (output[place] > 0) { + past_leading_zeroes = true; + } + + if (past_leading_zeroes) { + write_byte(output[place] + '0'); + } + } +} + +void write_int(write_byte_t write_byte, int value) { + if (value < 0) { + write_byte('-'); + value *= -1; + } + write_uint(write_byte, value); +} + +void write_octal(write_byte_t write_byte, uint32_t value) { + write_byte('0'); + write_byte('o'); + bool past_leading_zeroes = false; + uint8_t part = (value >> 30) & 0b11; + if (part > 0) { + write_half_byte(write_byte, part, true); + past_leading_zeroes = true; + } + for (int i = 10; i >=0; i--) { + part = (value >> (3*i)) & 0b111; + if (part > 0) { + past_leading_zeroes = true; + } + + if (past_leading_zeroes) { + write_half_byte(write_byte, part, true); + } + } +} + enum format_string_mode {NORMAL, COMMAND}; int fprintf (FILE stream, const char * format, ...) { write_byte_t write_byte = write_byte_function(stream); @@ -112,13 +160,16 @@ int fprintf (FILE stream, const char * format, ...) { case (COMMAND): if (format[i] == '%') { write_byte('%'); - mode = NORMAL; } else if (format[i] == 'c') { write_byte((uint32_t) va_arg(vl,uint32_t)); - mode = NORMAL; + } else if (format[i] == 'i' || format[i] == 'd') { + write_int(write_byte, va_arg(vl, int)); + } else if (format[i] == 'o') { + write_octal(write_byte, va_arg(vl, int)); } else if (format[i] == 's') { write_string(write_byte, (char*) va_arg(vl,char*)); - mode = NORMAL; + } else if (format[i] == 'u') { + write_uint(write_byte, va_arg(vl, uint32_t)); } else if (format[i] == 'x') { write_byte('0'); write_byte('x'); @@ -126,7 +177,6 @@ int fprintf (FILE stream, const char * format, ...) { for (int i = 7; i >=0; i--) { write_half_byte(write_byte, (vararg >> (4*i)) & 0x0F, false); } - mode = NORMAL; } else if (format[i] == 'X') { write_byte('0'); write_byte('x'); @@ -134,11 +184,11 @@ int fprintf (FILE stream, const char * format, ...) { for (int i = 7; i >=0; i--) { write_half_byte(write_byte, (vararg >> (4*i)) & 0x0F, true); } - mode = NORMAL; } else { write_byte('?'); mode = NORMAL; } + mode = NORMAL; break; } i++; From 268b47a55f8f8c7ac139a6cc46fb8db77374fe10 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 18:53:12 -0800 Subject: [PATCH 55/67] Use format strings everywhere. --- data_structures/global_descriptor_table.c | 28 ++------ data_structures/page_table.c | 5 +- drivers/keyboard.c | 4 +- interrupts.c | 53 +++++--------- kmain.c | 88 +++++++++-------------- multiboot_utils.c | 70 ++++-------------- process.c | 2 +- stdio.c | 77 +++++--------------- stdio.h | 6 -- 9 files changed, 99 insertions(+), 234 deletions(-) diff --git a/data_structures/global_descriptor_table.c b/data_structures/global_descriptor_table.c index 2b31f1f..e87e100 100644 --- a/data_structures/global_descriptor_table.c +++ b/data_structures/global_descriptor_table.c @@ -77,12 +77,8 @@ struct gdt_description_structure_t { void initialize_tss() { uint32_t tss_base = (uint32_t) &tss; uint32_t tss_limit = sizeof(tss); - log("tss_base: "); - print_uint32(LOG, tss_base); - log("\n"); - log("tss_limit: "); - print_uint32(LOG, tss_limit); - log("\n"); + fprintf(LOG, "tss_base: %x\n", tss_base); + fprintf(LOG, "tss_limit: %x\n", tss_limit); gdt[TASK_STATE_SEGMENT_INDEX].limit_0_15 = tss_limit & 0xFFFF; gdt[TASK_STATE_SEGMENT_INDEX].base_0_15 = tss_base & 0xFFFF; gdt[TASK_STATE_SEGMENT_INDEX].base_16_23 = (tss_base & 0xFF0000) >> 16; @@ -93,25 +89,15 @@ void initialize_tss() { tss.ss0 = KERNAL_DATA_SEGMENT_SELECTOR; tss.esp0 = ((uint32_t) &kernel_stack_lowest_address + KERNEL_STACK_SIZE) - 4; - log("KERNEL_STACK_SIZE: "); - print_uint32(LOG, (uint32_t) KERNEL_STACK_SIZE); - log("\n"); + log("KERNEL_STACK_SIZE: %x\n", (uint32_t) KERNEL_STACK_SIZE); - log("kernel_stack_lowest_address: "); - print_uint32(LOG, (uint32_t) kernel_stack_lowest_address); - log("\n"); + log("kernel_stack_lowest_address: %x\n", (uint32_t) kernel_stack_lowest_address); - log("&kernel_stack_lowest_address: "); - print_uint32(LOG, (uint32_t) (&kernel_stack_lowest_address)); - log("\n"); + log("&kernel_stack_lowest_address: %x\n", (uint32_t) (&kernel_stack_lowest_address)); - log("tss.ss0: "); - print_uint32(LOG, tss.ss0); - log("\n"); + log("tss.ss0: %x\n", tss.ss0); - log("tss.esp0: "); - print_uint32(LOG, tss.esp0); - log("\n"); + log("tss.esp0: %x\n", tss.esp0); tss_flush(); } diff --git a/data_structures/page_table.c b/data_structures/page_table.c index 322bdda..73797d8 100644 --- a/data_structures/page_table.c +++ b/data_structures/page_table.c @@ -323,10 +323,7 @@ void print_page_table(FILE file, const uint32_t* pt) { fprintf(file, "---\n"); for (uint32_t i = 0; i < PAGE_SIZE_DWORDS; i++) { if (get_present_from_pte(pt[i])) { - print_uint32(file, i); - fprintf(file, " -> "); - print_uint32(file, pt[i] & (uint32_t) PAGE_DIRECTORY_ADDRESS); - fprintf(file, "\n"); + fprintf(file, "%x -> %x\n", i, pt[i] & (uint32_t) PAGE_DIRECTORY_ADDRESS); } } fprintf(file, "---\n"); diff --git a/drivers/keyboard.c b/drivers/keyboard.c index 1fc2c35..e13f3c6 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -310,7 +310,7 @@ void keyboard_interrupt_handler() { } if (c != 0) { - print_char(LOG, c); - print_char(SCREEN, c); + fprintf(LOG, "%c", c); + fprintf(SCREEN, "%c", c); } } diff --git a/interrupts.c b/interrupts.c index ff8cb9e..d8c2c98 100644 --- a/interrupts.c +++ b/interrupts.c @@ -10,25 +10,18 @@ #include "stdio.h" void log_stack_trace_line(uint32_t eip) { - print_uint32(LOG, eip); - log(" : "); char * symbol_name = address_to_symbol_name(eip); - fprintf(LOG, symbol_name); - log("\n"); + fprintf(LOG, "%x : %s\n", eip, symbol_name); } void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, struct cpu_state* cpu) { if(cpu->ebp){} - log("--------------------\n"); + fprintf(LOG, "--------------------\n"); - log("Interrupt : "); - log(int_name); - log("\n"); - log("error_code: "); - print_uint32(LOG, error_code); - log("\n"); + fprintf(LOG, "Interrupt: %s\n", int_name); + fprintf(LOG, "error_code: %x\n", error_code); - log("\nStack trace:\n"); + fprintf(LOG, "\nStack trace:\n"); eip -= 4; // eip actually points one past the instruction that triggered interrupt log_stack_trace_line(eip); uint32_t ebp = cpu->ebp; @@ -40,13 +33,11 @@ void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, st ebp = *((uint32_t*)ebp); } - log("--------------------\n"); + fprintf(LOG, "--------------------\n"); } void sys_write_to_screen(char* s) { - log("sys_write_to_screen("); - print_uint32(LOG, (uint32_t) s); - log(")\n"); + fprintf(LOG, "sys_write_to_screen(%x)\n", (uint32_t) s); printf(s); } @@ -58,9 +49,7 @@ void handle_syscall(struct cpu_state* cpu) { sys_write_to_screen((char*) cpu->ebx); break; default: - log("Unknown syscall: "); - print_uint32(LOG, syscall_num); - log("\n"); + fprintf(LOG, "Unknown syscall: %x\n", syscall_num); while(1){} } } @@ -77,30 +66,28 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t page_in((void*) cpu.cr2); break; } - log("Interrupt was a page fault. Here's what I know:\n"); - log("- Tried to access virtual address "); - print_uint32(LOG, cpu.cr2); - log("\n"); + fprintf(LOG, "Interrupt was a page fault. Here's what I know:\n"); + fprintf(LOG, "- Tried to access virtual address %x\n", cpu.cr2); if (error_code & 0b1) { - log("- Couldn't complete because of page-protection violation\n"); + fprintf(LOG, "- Couldn't complete because of page-protection violation\n"); } else { - log("- Couldn't complete because page was not present\n"); + fprintf(LOG, "- Couldn't complete because page was not present\n"); } if (error_code & 0b10) { - log("- This was an attempt to WRITE to this address.\n"); + fprintf(LOG, "- This was an attempt to WRITE to this address.\n"); } else { - log("- This was an attempt to READ from this address.\n"); + fprintf(LOG, "- This was an attempt to READ from this address.\n"); } if (error_code & 0b100) { - log("- Memory access came from user.\n"); + fprintf(LOG, "- Memory access came from user.\n"); } else { - log("- Memory access came from kernel.\n"); + fprintf(LOG, "- Memory access came from kernel.\n"); } if (error_code & 0b1000) { - log("- caused by reading a 1 in a reserved field.\n"); + fprintf(LOG, "- caused by reading a 1 in a reserved field.\n"); } if (error_code & 0b10000) { - log("- caused by an instruction fetch.\n"); + fprintf(LOG, "- caused by an instruction fetch.\n"); } break; @@ -119,9 +106,7 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t break; default: - log("ERROR: Unable to handle interrupt: "); - print_uint32(LOG, interrupt_number); - log("\n"); + fprintf(LOG, "ERROR: Unable to handle interrupt: %x\n", interrupt_number); log_interrupt_details("INT_UNKNOWN", error_code, eip, &cpu); while(1){} break; diff --git a/kmain.c b/kmain.c index 0ba88a1..e49a868 100644 --- a/kmain.c +++ b/kmain.c @@ -60,89 +60,71 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { printf(welcome_string); serial_init(); - log("\n--------------------\ncstackOS is booting!\n--------------------\n\n"); + fprintf(LOG, "\n--------------------\ncstackOS is booting!\n--------------------\n\n"); #ifdef DEBUG - log("\nMultiboot info passed to kernel from GRUB:\n"); + fprintf(LOG, "\nMultiboot info passed to kernel from GRUB:\n"); print_multiboot_info(LOG, mbinfo); - log("\n"); + fprintf(LOG, "\n"); #endif - log("- Initializing symbol table...\n"); + fprintf(LOG, "- Initializing symbol table...\n"); if (load_symbol_table(get_elf_section(mbinfo, ".symtab"), get_elf_section(mbinfo, ".strtab"))) { - log(" - done\n"); + fprintf(LOG, " - done\n"); } else { - log("ERROR: Could not initialize symbol table.\n"); + fprintf(LOG, "ERROR: Could not initialize symbol table.\n"); while(1){} } - log("- Initializing global descriptor table...\n"); + fprintf(LOG, "- Initializing global descriptor table...\n"); initialize_gdt(); - log(" - done\n"); + fprintf(LOG, " - done\n"); - log("- Initializing interrupt descriptor table...\n"); + fprintf(LOG, "- Initializing interrupt descriptor table...\n"); initialize_idt(); - log(" - done\n"); + fprintf(LOG, " - done\n"); - log("- Issuing test interrupt...\n"); + fprintf(LOG, "- Issuing test interrupt...\n"); interrupt(); - log(" - done\n"); + fprintf(LOG, " - done\n"); - log("- Initializing programable interrupt controller...\n"); + fprintf(LOG, "- Initializing programable interrupt controller...\n"); pic_init(); - log(" - done\n"); + fprintf(LOG, " - done\n"); - log("- Initializing page allocator...\n"); + fprintf(LOG, "- Initializing page allocator...\n"); uint32_t free_pages = initialize_page_allocator(kernel_memory, mbinfo); - log(" - done\n"); - log(" - "); - print_uint32(LOG, free_pages); - log(" free pages ("); - print_uint32(LOG, free_pages / 256); - log(" MB)\n"); - - log("- Initializing page directory...\n"); + fprintf(LOG, " - done\n"); + fprintf(LOG, " - %x free pages (%i MB)\n", free_pages, free_pages/256); + + fprintf(LOG, "- Initializing page directory...\n"); page_directory_t pd = initialize_kernel_page_directory(); - log(" - done\n"); - log(" - Address of page directory: "); - print_uint32(LOG, (uint32_t) pd); - log("\n"); + fprintf(LOG, " - done\n"); + fprintf(LOG, " - Address of page directory: %x\n", (uint32_t) pd); uint32_t num_pages = num_present_pages(pd); - log(" - "); - print_uint32(LOG, num_pages); - log(" present pages\n"); + fprintf(LOG, " - %i present pages\n", num_pages); - log("- Triggering a page fault...\n"); + fprintf(LOG, "- Triggering a page fault...\n"); uint32_t value = trigger_page_fault(); - log(" - done\n"); - log(" - value at unmapped address was "); - print_uint32(LOG, value); - log("\n"); + fprintf(LOG, " - done\n"); + fprintf(LOG, " - value at unmapped address was %x\n", value); - log("- Initializing task state segment...\n"); + fprintf(LOG, "- Initializing task state segment...\n"); initialize_tss(); - log(" - done\n"); + fprintf(LOG, " - done\n"); - log("- Dynamically allocating a struct...\n"); + fprintf(LOG, "- Dynamically allocating a struct...\n"); struct test_struct_t* test = (struct test_struct_t*) malloc(sizeof(struct test_struct_t)); - log(" - done\n"); - log(" - address is: "); - print_uint32(LOG, (uint32_t) test); - log("\n"); + fprintf(LOG, " - done\n"); + fprintf(LOG, " - address is: %x\n", (uint32_t) test); uint32_t local = 0xDEADBEEF; - log(" - local variable at: "); - print_uint32(LOG, (uint32_t) &local); - log("\n"); - log(" - local variable value: "); - print_uint32(LOG, (uint32_t) local); - log("\n"); + fprintf(LOG, " - local variable at: %x\n", (uint32_t) &local); + fprintf(LOG, " - local variable value: %x\n", (uint32_t) local); void* sp = current_stack_pointer(); - log(" - stack pointer is: "); - print_uint32(LOG, (uint32_t) sp); - log("\n"); + fprintf(LOG, " - stack pointer is: %x\n", (uint32_t) sp); fprintf( LOG, @@ -150,9 +132,9 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { "test", 'A', 0xDEADBEEF, 0xDEADBEEF, 12345, -12345, 12345 ); - log("- Creating a user process...\n"); + fprintf(LOG, "- Creating a user process...\n"); create_process(first_module(mbinfo)); - log(" - done\n"); + fprintf(LOG, " - done\n"); // Loop forever // User input is accepted asynchronously via interrupts diff --git a/multiboot_utils.c b/multiboot_utils.c index b83cee0..54ba356 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -10,12 +10,8 @@ uint32_t p_to_v(uint32_t physical_address) { void print_module_info(FILE stream, struct module * m) { fprintf(stream, (char*) (p_to_v(m->string))); fprintf(stream, ":\n"); - fprintf(stream, "mod_start (virtual): "); - print_uint32(stream, p_to_v(m->mod_start)); - fprintf(stream, "\n"); - fprintf(stream, "mod_end (virtual): "); - print_uint32(stream, p_to_v(m->mod_end)); - fprintf(stream, "\n"); + fprintf(stream, "mod_start (virtual): %x\n", p_to_v(m->mod_start)); + fprintf(stream, "mod_end (virtual): %x\n", p_to_v(m->mod_end)); } struct elf_section_header_t * get_elf_section(multiboot_info_t* info, char * section_name) { @@ -55,12 +51,8 @@ void print_elf_section_header_table(FILE stream, elf_section_header_table_t tabl for (uint32_t i = 0; i < num; i++) { uint32_t sh_addr = section_header_table[i].sh_addr; - print_uint32(stream, sh_addr); + fprintf(stream, "%x : %x : ", sh_addr, section_header_table[i].sh_size); - fprintf(stream, " : "); - print_uint32(stream, section_header_table[i].sh_size); - - fprintf(stream, " : "); uint32_t sh_name = section_header_table[i].sh_name; if (sh_name != 0) { char * name = (char*) (string_table_start + sh_name); @@ -78,55 +70,23 @@ void print_memory_map(FILE stream, multiboot_info_t* info) { uint32_t num_entries = info->mmap_length / sizeof(memory_map_t); for (uint32_t i = 0; i < num_entries; i++) { - fprintf(stream, "base_addr_low: "); - print_uint32(stream, memory_map[i].base_addr_low); - fprintf(stream, "\n"); - - fprintf(stream, "base_addr_high: "); - print_uint32(stream, memory_map[i].base_addr_high); - fprintf(stream, "\n"); - - fprintf(stream, "length_low: "); - print_uint32(stream, memory_map[i].length_low); - fprintf(stream, "\n"); - - fprintf(stream, "length_high: "); - print_uint32(stream, memory_map[i].length_high); - fprintf(stream, "\n"); - - fprintf(stream, "type: "); - print_uint32(stream, memory_map[i].type); - fprintf(stream, "\n"); - + fprintf(stream, "base_addr_low: %x\n", memory_map[i].base_addr_low); + fprintf(stream, "base_addr_high: %x\n", memory_map[i].base_addr_high); + fprintf(stream, "length_low: %x\n", memory_map[i].length_low); + fprintf(stream, "length_high: %x\n", memory_map[i].length_high); + fprintf(stream, "type: %x\n", memory_map[i].type); fprintf(stream, "\n"); } } void print_multiboot_info(FILE stream, multiboot_info_t* info) { - fprintf(stream, "flags: "); - print_uint32(stream, info->flags); - fprintf(stream, "\n"); - - fprintf(stream, "mem_lower (kilobytes): "); - print_uint32(stream, info->mem_lower); - fprintf(stream, "\n"); - fprintf(stream, "mem_upper (kilobytes): "); - print_uint32(stream, info->mem_upper); - fprintf(stream, "\n"); - - fprintf(stream, "boot_device: "); - print_uint32(stream, info->boot_device); - fprintf(stream, "\n"); - fprintf(stream, "cmdline: "); - print_uint32(stream, info->cmdline); - fprintf(stream, "\n"); - - fprintf(stream, "mods_count: "); - print_uint32(stream, info->mods_count); - fprintf(stream, "\n"); - fprintf(stream, "mods_addr (virtual): "); - print_uint32(stream, p_to_v(info->mods_addr)); - fprintf(stream, "\n"); + fprintf(stream, "flags: %x\n", info->flags); + fprintf(stream, "mem_lower (kilobytes): %i\n", info->mem_lower); + fprintf(stream, "mem_upper (kilobytes): %i\n", info->mem_upper); + fprintf(stream, "boot_device: %x\n", info->boot_device); + fprintf(stream, "cmdline: %x\n", info->cmdline); + fprintf(stream, "mods_count: %i\n", info->mods_count); + fprintf(stream, "mods_addr (virtual): %x\n", info->mods_addr); fprintf(stream, "\nGRUB modules: \n"); struct module * modules; diff --git a/process.c b/process.c index 42aa3b2..0866b77 100644 --- a/process.c +++ b/process.c @@ -98,6 +98,6 @@ void create_process(struct module* mod) { set_page_directory(virtual_to_physical(pd)); - log("Entering user mode...\n"); + fprintf(LOG, "Entering user mode...\n"); enter_user_mode(); } \ No newline at end of file diff --git a/stdio.c b/stdio.c index 695b9bf..c61e3da 100644 --- a/stdio.c +++ b/stdio.c @@ -15,28 +15,6 @@ write_byte_t write_byte_function(FILE stream) { } } -void print_char(FILE stream, char c) { - write_byte_t write_byte = write_byte_function(stream); - write_byte(c); -} - -void print_bytes(FILE stream, uint8_t * bytes, uint32_t num_bytes) { - write_byte_t write_byte = write_byte_function(stream); - if (num_bytes == 0) { return; } - print_uint8(stream, bytes[0]); - for (uint32_t i=1; i < num_bytes; i++) { - write_byte(' '); - print_uint8(stream, bytes[i]); - } -} - -void write_string(write_byte_t write_byte, char* s) { - while(*s) { - write_byte(*s); - s++; - } -} - void write_half_byte(write_byte_t write_byte, uint8_t half_byte, bool upcase) { switch (half_byte) { case 0x0: @@ -90,6 +68,25 @@ void write_half_byte(write_byte_t write_byte, uint8_t half_byte, bool upcase) { } } +void print_uint8(FILE stream, uint8_t data) { + write_byte_t write_byte = write_byte_function(stream); + + uint8_t half_byte; + write_byte('0'); + write_byte('x'); + for (int i = 1; i >=0; i--) { + half_byte = (data >> (4*i)) & 0x0F; + write_half_byte(write_byte, half_byte, true); + } +} + +void write_string(write_byte_t write_byte, char* s) { + while(*s) { + write_byte(*s); + s++; + } +} + void write_uint(write_byte_t write_byte, uint32_t value) { char output[10]; for (int place = 0; place < 10; place++) { @@ -196,42 +193,6 @@ int fprintf (FILE stream, const char * format, ...) { return i; } -void print_uint8(FILE stream, uint8_t data) { - write_byte_t write_byte = write_byte_function(stream); - - uint8_t half_byte; - write_byte('0'); - write_byte('x'); - for (int i = 1; i >=0; i--) { - half_byte = (data >> (4*i)) & 0x0F; - write_half_byte(write_byte, half_byte, true); - } -} - -void print_uint16(FILE stream, uint16_t data) { - write_byte_t write_byte = write_byte_function(stream); - - uint8_t half_byte; - write_byte('0'); - write_byte('x'); - for (int i = 3; i >=0; i--) { - half_byte = (data >> (4*i)) & 0x0F; - write_half_byte(write_byte, half_byte, true); - } -} - -void print_uint32(FILE stream, uint32_t data) { - write_byte_t write_byte = write_byte_function(stream); - - uint8_t half_byte; - write_byte('0'); - write_byte('x'); - for (int i = 7; i >=0; i--) { - half_byte = (data >> (4*i)) & 0x0F; - write_half_byte(write_byte, half_byte, true); - } -} - int printf (const char * format, ...) { return fprintf(SCREEN, format); } diff --git a/stdio.h b/stdio.h index 20fb71a..8485cf7 100644 --- a/stdio.h +++ b/stdio.h @@ -6,12 +6,6 @@ typedef enum output_t {SCREEN, LOG} FILE; int fprintf (FILE stream, const char * format, ...); -int log(char * format, ...); int printf (const char * format, ...); -void print_uint8(FILE stream, uint8_t data); -void print_uint16(FILE stream, uint16_t data); -void print_uint32(FILE stream, uint32_t data); -void print_char(FILE stream, char c); -void print_bytes(FILE stream, uint8_t * bytes, uint32_t num_bytes); #endif /* STDIO_H */ \ No newline at end of file From 2f72d437be10e756a0ffbe3d250508d3e8ea1592 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Fri, 25 Nov 2016 19:04:34 -0800 Subject: [PATCH 56/67] Clean up logging. --- data_structures/global_descriptor_table.c | 12 ------------ interrupts.c | 7 +++++-- kmain.c | 10 +++++----- process.c | 1 - 4 files changed, 10 insertions(+), 20 deletions(-) diff --git a/data_structures/global_descriptor_table.c b/data_structures/global_descriptor_table.c index e87e100..224817e 100644 --- a/data_structures/global_descriptor_table.c +++ b/data_structures/global_descriptor_table.c @@ -77,8 +77,6 @@ struct gdt_description_structure_t { void initialize_tss() { uint32_t tss_base = (uint32_t) &tss; uint32_t tss_limit = sizeof(tss); - fprintf(LOG, "tss_base: %x\n", tss_base); - fprintf(LOG, "tss_limit: %x\n", tss_limit); gdt[TASK_STATE_SEGMENT_INDEX].limit_0_15 = tss_limit & 0xFFFF; gdt[TASK_STATE_SEGMENT_INDEX].base_0_15 = tss_base & 0xFFFF; gdt[TASK_STATE_SEGMENT_INDEX].base_16_23 = (tss_base & 0xFF0000) >> 16; @@ -89,16 +87,6 @@ void initialize_tss() { tss.ss0 = KERNAL_DATA_SEGMENT_SELECTOR; tss.esp0 = ((uint32_t) &kernel_stack_lowest_address + KERNEL_STACK_SIZE) - 4; - log("KERNEL_STACK_SIZE: %x\n", (uint32_t) KERNEL_STACK_SIZE); - - log("kernel_stack_lowest_address: %x\n", (uint32_t) kernel_stack_lowest_address); - - log("&kernel_stack_lowest_address: %x\n", (uint32_t) (&kernel_stack_lowest_address)); - - log("tss.ss0: %x\n", tss.ss0); - - log("tss.esp0: %x\n", tss.esp0); - tss_flush(); } diff --git a/interrupts.c b/interrupts.c index d8c2c98..6f17b25 100644 --- a/interrupts.c +++ b/interrupts.c @@ -37,13 +37,15 @@ void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, st } void sys_write_to_screen(char* s) { - fprintf(LOG, "sys_write_to_screen(%x)\n", (uint32_t) s); + fprintf(LOG, "sys_write_to_screen(%s)\n", s); printf(s); } void handle_syscall(struct cpu_state* cpu) { uint32_t syscall_num = cpu->eax; + fprintf(LOG, "--------------------\nSYSCALL (%i)\n", syscall_num); + switch (syscall_num) { case (1): sys_write_to_screen((char*) cpu->ebx); @@ -52,6 +54,8 @@ void handle_syscall(struct cpu_state* cpu) { fprintf(LOG, "Unknown syscall: %x\n", syscall_num); while(1){} } + + fprintf(LOG, "--------------------\n"); } void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip) { @@ -96,7 +100,6 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t break; case(INT_SYSCALL): - log_interrupt_details("INT_SYSCALL", error_code, eip, &cpu); handle_syscall(&cpu); break; diff --git a/kmain.c b/kmain.c index e49a868..5be573e 100644 --- a/kmain.c +++ b/kmain.c @@ -95,7 +95,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { fprintf(LOG, "- Initializing page allocator...\n"); uint32_t free_pages = initialize_page_allocator(kernel_memory, mbinfo); fprintf(LOG, " - done\n"); - fprintf(LOG, " - %x free pages (%i MB)\n", free_pages, free_pages/256); + fprintf(LOG, " - %i free pages (%i MB)\n", free_pages, free_pages/256); fprintf(LOG, "- Initializing page directory...\n"); page_directory_t pd = initialize_kernel_page_directory(); @@ -116,19 +116,19 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { fprintf(LOG, "- Dynamically allocating a struct...\n"); struct test_struct_t* test = (struct test_struct_t*) malloc(sizeof(struct test_struct_t)); fprintf(LOG, " - done\n"); - fprintf(LOG, " - address is: %x\n", (uint32_t) test); + fprintf(LOG, " - address (on heap) is: %x\n", (uint32_t) test); uint32_t local = 0xDEADBEEF; - fprintf(LOG, " - local variable at: %x\n", (uint32_t) &local); - fprintf(LOG, " - local variable value: %x\n", (uint32_t) local); + fprintf(LOG, " - local variable (on stack) at: %x\n", (uint32_t) &local); void* sp = current_stack_pointer(); fprintf(LOG, " - stack pointer is: %x\n", (uint32_t) sp); + fprintf(LOG, "- Testing format strings...\n"); fprintf( LOG, - "%%s -> %s, %%c -> %c, %%x -> %x, %%X -> %X, %%u -> %u, %%i -> %i, %%o -> %o\n", + " - %%s -> %s, %%c -> %c, %%x -> %x, %%X -> %X, %%u -> %u, %%i -> %i, %%o -> %o\n", "test", 'A', 0xDEADBEEF, 0xDEADBEEF, 12345, -12345, 12345 ); diff --git a/process.c b/process.c index 0866b77..941b7f2 100644 --- a/process.c +++ b/process.c @@ -98,6 +98,5 @@ void create_process(struct module* mod) { set_page_directory(virtual_to_physical(pd)); - fprintf(LOG, "Entering user mode...\n"); enter_user_mode(); } \ No newline at end of file From 063725663405bd9669aecdb2391102b1ca805f4b Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 26 Nov 2016 15:36:43 -0800 Subject: [PATCH 57/67] User mode printf. --- Makefile | 5 +- interrupts.c | 1 + script/user_program_dump | 10 ++ stdio.c | 2 +- stdlib/stdarg.h | 133 +++++++++++++++++++++++++ stdlib/stdio.c | 207 +++++++++++++++++++++++++++++++++++++++ stdlib/stdio.h | 8 ++ stdlib/types.h | 22 +++++ user_program.c | 5 +- 9 files changed, 389 insertions(+), 4 deletions(-) create mode 100755 script/user_program_dump create mode 100644 stdlib/stdarg.h create mode 100644 stdlib/stdio.c create mode 100644 stdlib/stdio.h create mode 100644 stdlib/types.h diff --git a/Makefile b/Makefile index afba80a..ad93ecf 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,9 @@ stdio.o \ stdlib.o \ string.o +STDLIB = stdlib/assembly_functions.o \ +stdlib/stdio.o + all: os.iso %.o: %.c @@ -56,7 +59,7 @@ start_user_program.o: start_user_program.s user_program.o: user_program.c $(GCC) $(CFLAGS) $< -o $@ -user_program.bin: user_program.o start_user_program.o stdlib/assembly_functions.o +user_program.bin: user_program.o start_user_program.o $(STDLIB) $(LD) -T link_user_program.ld -melf_i386 $^ -o $@ os.iso: kernel.elf user_program.bin menu.lst diff --git a/interrupts.c b/interrupts.c index 6f17b25..0794edd 100644 --- a/interrupts.c +++ b/interrupts.c @@ -93,6 +93,7 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t if (error_code & 0b10000) { fprintf(LOG, "- caused by an instruction fetch.\n"); } + while(1){} break; case(INT_SOFTWARE): diff --git a/script/user_program_dump b/script/user_program_dump new file mode 100755 index 0000000..2d1c449 --- /dev/null +++ b/script/user_program_dump @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby +raw = `xxd user_program.bin` + +lines = raw.split("\n") + +formatted_lines = lines.map do |line| + line[9,41].tr(' ', '') +end + +puts formatted_lines.join("").gsub(/(.{2})/, '\1 ') \ No newline at end of file diff --git a/stdio.c b/stdio.c index c61e3da..797d92c 100644 --- a/stdio.c +++ b/stdio.c @@ -95,7 +95,7 @@ void write_uint(write_byte_t write_byte, uint32_t value) { } bool past_leading_zeroes = false; - for (int place = 10; place >= 0; place--) { + for (int place = 9; place >= 0; place--) { if (output[place] > 0) { past_leading_zeroes = true; } diff --git a/stdlib/stdarg.h b/stdlib/stdarg.h new file mode 100644 index 0000000..8be7b67 --- /dev/null +++ b/stdlib/stdarg.h @@ -0,0 +1,133 @@ +/* Copyright (C) 1989, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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, or (at your option) +any later version. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you include this header file into source + files compiled by GCC, this header file does not by itself cause + the resulting executable to be covered by the GNU General Public + License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General + Public License. */ + +/* + * ISO C Standard: 7.15 Variable arguments + */ + +#ifndef _STDARG_H +#ifndef _ANSI_STDARG_H_ +#ifndef __need___va_list +#define _STDARG_H +#define _ANSI_STDARG_H_ +#endif /* not __need___va_list */ +#undef __need___va_list + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +/* Define the standard macros for the user, + if this invocation was from the user program. */ +#ifdef _STDARG_H + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L +#define va_copy(d,s) __builtin_va_copy(d,s) +#endif +#define __va_copy(d,s) __builtin_va_copy(d,s) + +/* Define va_list, if desired, from __gnuc_va_list. */ +/* We deliberately do not define va_list when called from + stdio.h, because ANSI C says that stdio.h is not supposed to define + va_list. stdio.h needs to have access to that data type, + but must not use that name. It should use the name __gnuc_va_list, + which is safe because it is reserved for the implementation. */ + +#ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */ +#undef _VA_LIST +#endif + +#ifdef _BSD_VA_LIST +#undef _BSD_VA_LIST +#endif + +#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST)) +/* SVR4.2 uses _VA_LIST for an internal alias for va_list, + so we must avoid testing it and setting it here. + SVR4 uses _VA_LIST as a flag in stdarg.h, but we should + have no conflict with that. */ +#ifndef _VA_LIST_ +#define _VA_LIST_ +#ifdef __i860__ +#ifndef _VA_LIST +#define _VA_LIST va_list +#endif +#endif /* __i860__ */ +typedef __gnuc_va_list va_list; +#ifdef _SCO_DS +#define __VA_LIST +#endif +#endif /* _VA_LIST_ */ +#else /* not __svr4__ || _SCO_DS */ + +/* The macro _VA_LIST_ is the same thing used by this file in Ultrix. + But on BSD NET2 we must not test or define or undef it. + (Note that the comments in NET 2's ansi.h + are incorrect for _VA_LIST_--see stdio.h!) */ +#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) +/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */ +#ifndef _VA_LIST_DEFINED +/* The macro _VA_LIST is used in SCO Unix 3.2. */ +#ifndef _VA_LIST +/* The macro _VA_LIST_T_H is used in the Bull dpx2 */ +#ifndef _VA_LIST_T_H +/* The macro __va_list__ is used by BeOS. */ +#ifndef __va_list__ +typedef __gnuc_va_list va_list; +#endif /* not __va_list__ */ +#endif /* not _VA_LIST_T_H */ +#endif /* not _VA_LIST */ +#endif /* not _VA_LIST_DEFINED */ +#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)) +#define _VA_LIST_ +#endif +#ifndef _VA_LIST +#define _VA_LIST +#endif +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED +#endif +#ifndef _VA_LIST_T_H +#define _VA_LIST_T_H +#endif +#ifndef __va_list__ +#define __va_list__ +#endif + +#endif /* not _VA_LIST_, except on certain systems */ + +#endif /* not __svr4__ */ + +#endif /* _STDARG_H */ + +#endif /* not _ANSI_STDARG_H_ */ +#endif /* not _STDARG_H */ \ No newline at end of file diff --git a/stdlib/stdio.c b/stdlib/stdio.c new file mode 100644 index 0000000..07d0148 --- /dev/null +++ b/stdlib/stdio.c @@ -0,0 +1,207 @@ +#include "stdio.h" + +#include "assembly_functions.h" +#include "stdarg.h" + +#define BUFFER_SIZE 128 + +struct buffer_t { + char bytes[BUFFER_SIZE+1]; // 1 bytes for null character + uint8_t bytes_in_buffer; +}; + +void flush_buffer(struct buffer_t* buffer) { + write_to_screen(buffer->bytes); + buffer->bytes_in_buffer = 0; +} + +void write_byte(char byte, struct buffer_t* buffer) { + buffer->bytes[buffer->bytes_in_buffer] = byte; + + buffer->bytes_in_buffer++; + + if (buffer->bytes_in_buffer >= BUFFER_SIZE) { + flush_buffer(buffer); + } +} + +void write_half_byte(uint8_t half_byte, bool upcase, struct buffer_t* buffer) { + switch (half_byte) { + case 0x0: + write_byte('0', buffer); + break; + case 0x1: + write_byte('1', buffer); + break; + case 0x2: + write_byte('2', buffer); + break; + case 0x3: + write_byte('3', buffer); + break; + case 0x4: + write_byte('4', buffer); + break; + case 0x5: + write_byte('5', buffer); + break; + case 0x6: + write_byte('6', buffer); + break; + case 0x7: + write_byte('7', buffer); + break; + case 0x8: + write_byte('8', buffer); + break; + case 0x9: + write_byte('9', buffer); + break; + case 0xA: + write_byte(upcase ? 'A' : 'a', buffer); + break; + case 0xB: + write_byte(upcase ? 'B' : 'b', buffer); + break; + case 0xC: + write_byte(upcase ? 'C' : 'c', buffer); + break; + case 0xD: + write_byte(upcase ? 'D' : 'd', buffer); + break; + case 0xE: + write_byte(upcase ? 'E' : 'e', buffer); + break; + case 0xF: + write_byte(upcase ? 'F' : 'f', buffer); + break; + } +} + +void print_uint8(uint8_t data, struct buffer_t* buffer) { + uint8_t half_byte; + write_byte('0', buffer); + write_byte('x', buffer); + for (int i = 1; i >=0; i--) { + half_byte = (data >> (4*i)) & 0x0F; + write_half_byte(half_byte, true, buffer); + } +} + +void write_string(char* s, struct buffer_t* buffer) { + while(*s) { + write_byte(*s, buffer); + s++; + } +} + +void write_uint(uint32_t value, struct buffer_t* buffer) { + char output[10]; + for (int place = 0; place < 10; place++) { + output[place] = value % 10; + value = value / 10; + } + + bool past_leading_zeroes = false; + for (int place = 9; place >= 0; place--) { + if (output[place] > 0) { + past_leading_zeroes = true; + } + + if (past_leading_zeroes) { + write_byte(output[place] + '0', buffer); + } + } +} + +void write_int(int value, struct buffer_t* buffer) { + if (value < 0) { + write_byte('-', buffer); + value *= -1; + } + write_uint(value, buffer); +} + +void write_octal(uint32_t value, struct buffer_t* buffer) { + write_byte('0', buffer); + write_byte('o', buffer); + bool past_leading_zeroes = false; + uint8_t part = (value >> 30) & 0b11; + if (part > 0) { + write_half_byte(part, true, buffer); + past_leading_zeroes = true; + } + for (int i = 10; i >=0; i--) { + part = (value >> (3*i)) & 0b111; + if (part > 0) { + past_leading_zeroes = true; + } + + if (past_leading_zeroes) { + write_half_byte(part, true, buffer); + } + } +} + +enum format_string_mode {NORMAL, COMMAND}; +int printf (const char * format, ...) { + va_list vl; + va_start(vl,format); + + struct buffer_t buffer; + for (int i = 0; i <=BUFFER_SIZE; i++) { + buffer.bytes[i] = 0; + buffer.bytes_in_buffer = 0; + } + + int i = 0; + enum format_string_mode mode = NORMAL; + uint32_t vararg; + while (format[i]) { + switch (mode) { + case (NORMAL): + if (format[i] == '%') { + mode = COMMAND; + } else { + write_byte(format[i], &buffer); + } + break; + case (COMMAND): + if (format[i] == '%') { + write_byte('%', &buffer); + } else if (format[i] == 'c') { + write_byte((uint32_t) va_arg(vl,uint32_t), &buffer); + } else if (format[i] == 'i' || format[i] == 'd') { + write_int(va_arg(vl, int), &buffer); + } else if (format[i] == 'o') { + write_octal(va_arg(vl, int), &buffer); + } else if (format[i] == 's') { + write_string((char*) va_arg(vl,char*), &buffer); + } else if (format[i] == 'u') { + write_uint(va_arg(vl, uint32_t), &buffer); + } else if (format[i] == 'x') { + write_byte('0', &buffer); + write_byte('x', &buffer); + vararg = va_arg(vl,uint32_t); + for (int i = 7; i >=0; i--) { + write_half_byte((vararg >> (4*i)) & 0x0F, false, &buffer); + } + } else if (format[i] == 'X') { + write_byte('0', &buffer); + write_byte('x', &buffer); + vararg = va_arg(vl,uint32_t); + for (int i = 7; i >=0; i--) { + write_half_byte((vararg >> (4*i)) & 0x0F, true, &buffer); + } + } else { + write_byte('?', &buffer); + mode = NORMAL; + } + mode = NORMAL; + break; + } + i++; + } + flush_buffer(&buffer); + return i; +} \ No newline at end of file diff --git a/stdlib/stdio.h b/stdlib/stdio.h new file mode 100644 index 0000000..8e82ab0 --- /dev/null +++ b/stdlib/stdio.h @@ -0,0 +1,8 @@ +#ifndef STDIO_H +#define STDIO_H + +#include "../types.h" + +int printf (const char * format, ...); + +#endif /* STDIO_H */ \ No newline at end of file diff --git a/stdlib/types.h b/stdlib/types.h new file mode 100644 index 0000000..4b96d9e --- /dev/null +++ b/stdlib/types.h @@ -0,0 +1,22 @@ +#ifndef INCLUDE_TYPES_H +#define INCLUDE_TYPES_H + +typedef unsigned char int8; +typedef int8 byte; +typedef unsigned short int16; +typedef int16 byte2; +typedef unsigned long int32; +typedef int16 byte4; +typedef unsigned long long int64; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; + +typedef void (*void_function_t)(void); + +#define bool char +#define true 1 +#define false 0 + +#endif /* INCLUDE_TYPES_H */ \ No newline at end of file diff --git a/user_program.c b/user_program.c index 368ed70..b783a25 100644 --- a/user_program.c +++ b/user_program.c @@ -1,4 +1,4 @@ -#include "stdlib/assembly_functions.h" +#include "stdlib/stdio.h" int fib(unsigned int n) { if (n == 0) { @@ -15,7 +15,8 @@ int fib(unsigned int n) { int main() { int result = fib(20); // Should be 0x1a6d - write_to_screen("\n----\nHello World!\n----\n"); + printf("\n----\nHello World!\n----\n"); + printf("fib(20) -> %i\n", result); return result; } From 4bb7398992ebbefa0922da4ab33c9a5fe34d0d38 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 26 Nov 2016 16:39:21 -0800 Subject: [PATCH 58/67] Start filesystem. Parse test file. metadata. --- .gitignore | 2 ++ Makefile | 9 +++++-- file_system_root/test.txt | 1 + filesystem.c | 49 +++++++++++++++++++++++++++++++++++++++ filesystem.h | 18 ++++++++++++++ kmain.c | 14 +++++++++-- menu.lst | 2 +- script/build_file_system | 13 +++++++++++ stdlib.c | 15 ++++++++++++ stdlib.h | 1 + string.c | 15 ++++++++++++ string.h | 3 +++ 12 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 file_system_root/test.txt create mode 100644 filesystem.c create mode 100644 filesystem.h create mode 100755 script/build_file_system diff --git a/.gitignore b/.gitignore index 0055e21..bc9df09 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ iso/ *.iso stage2_eltorito log/ +built_file_system +TODO diff --git a/Makefile b/Makefile index ad93ecf..eeabe24 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ drivers/frame_buffer.o \ drivers/keyboard.o \ drivers/pic.o \ drivers/serial_port.o \ +filesystem.o \ interrupts.o \ kmain.o \ multiboot_utils.o \ @@ -62,12 +63,15 @@ user_program.o: user_program.c user_program.bin: user_program.o start_user_program.o $(STDLIB) $(LD) -T link_user_program.ld -melf_i386 $^ -o $@ -os.iso: kernel.elf user_program.bin menu.lst +built_file_system: file_system_root/* + script/build_file_system + +os.iso: kernel.elf user_program.bin menu.lst built_file_system mkdir -p iso/boot/grub # create the folder structure mkdir -p iso/modules cp stage2_eltorito iso/boot/grub/ # copy the bootloader cp kernel.elf iso/boot/ # copy the kernel - cp user_program.bin iso/modules # copy the 'user' program + cp built_file_system iso/modules # copy the 'user' program cp menu.lst iso/boot/grub # copy the grub configuration file mkisofs -R \ -b boot/grub/stage2_eltorito \ @@ -91,3 +95,4 @@ clean: rm -f *.bin # flat binary executables rm -f *.out rm -rf iso/ + rm built_file_system diff --git a/file_system_root/test.txt b/file_system_root/test.txt new file mode 100644 index 0000000..3245b20 --- /dev/null +++ b/file_system_root/test.txt @@ -0,0 +1 @@ +Hello World. \ No newline at end of file diff --git a/filesystem.c b/filesystem.c new file mode 100644 index 0000000..01e0ca8 --- /dev/null +++ b/filesystem.c @@ -0,0 +1,49 @@ +#include "filesystem.h" + +#include "memory.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" + +struct file_t* f; + +void initialize_filesystem(struct module* mod) { + void* mod_virtual_start = (void*) (mod->mod_start + UPPER_GB_START); + + char* cursor = (char*) mod_virtual_start; + + if (strncmp(cursor, "FILE ", 5) != 0) { + fprintf(LOG, "ERROR: First bytes of metadata should be `FILE ` but were `"); + for (int i = 0; i < 5; i++) { + fprintf(LOG, "%c", cursor[i]); + } + fprintf(LOG, "`\n"); + fprintf(LOG, "strncmp returned %i\n", strncmp(cursor, "FILE ", 5)); + fprintf(LOG, "cursor: %s", cursor); + } + cursor += 5; + + struct file_t* file = malloc(sizeof(struct file_t)); + + uint32_t file_name_length = 0; + while (*cursor != ' ' && file_name_length < FILE_NAME_MAX_LENGTH) { + file->name[file_name_length] = *cursor; + cursor++; + file_name_length++; + } + cursor++; + + uint32_t file_size = atoi(cursor); + file->size = file_size; + while (*cursor != '\n') { + cursor++; + } + cursor++; + file->bytes = cursor; + + f = file; +} + +struct file_t* get_file() { + return f; +} diff --git a/filesystem.h b/filesystem.h new file mode 100644 index 0000000..f205ef5 --- /dev/null +++ b/filesystem.h @@ -0,0 +1,18 @@ +#ifndef INCLUDE_FILESYSTEM_H +#define INCLUDE_FILESYSTEM_H + +#include "types.h" +#include "multiboot.h" + +#define FILE_NAME_MAX_LENGTH 63 +struct file_t { + char name[FILE_NAME_MAX_LENGTH+1]; + uint32_t size; + char* bytes; + struct file_t* next_sibling; +}; + +void initialize_filesystem(struct module* mbinfo); +struct file_t* get_file(); + +#endif /* INCLUDE_FILESYSTEM_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index 5be573e..04c9cf0 100644 --- a/kmain.c +++ b/kmain.c @@ -6,6 +6,7 @@ #include "drivers/frame_buffer.h" #include "drivers/pic.h" #include "drivers/serial_port.h" +#include "filesystem.h" #include "multiboot_utils.h" #include "process.h" #include "stdio.h" @@ -132,10 +133,19 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { "test", 'A', 0xDEADBEEF, 0xDEADBEEF, 12345, -12345, 12345 ); - fprintf(LOG, "- Creating a user process...\n"); - create_process(first_module(mbinfo)); + fprintf(LOG, "- Loading file system from GRUB module...\n"); + initialize_filesystem(first_module(mbinfo)); fprintf(LOG, " - done\n"); + struct file_t* file = get_file(); + fprintf(LOG, "Name of file: %s\n", file->name); + fprintf(LOG, "Size of file: %i\n", file->size); + fprintf(LOG, "Contents of file:\n----\n%s\n----\n", file->bytes); + + // fprintf(LOG, "- Creating a user process...\n"); + // create_process(first_module(mbinfo)); + // fprintf(LOG, " - done\n"); + // Loop forever // User input is accepted asynchronously via interrupts while(1){} diff --git a/menu.lst b/menu.lst index 336bddf..d262cf1 100644 --- a/menu.lst +++ b/menu.lst @@ -3,4 +3,4 @@ timeout=0 title os kernel /boot/kernel.elf -module /modules/user_program.bin \ No newline at end of file +module /modules/built_file_system \ No newline at end of file diff --git a/script/build_file_system b/script/build_file_system new file mode 100755 index 0000000..524ef50 --- /dev/null +++ b/script/build_file_system @@ -0,0 +1,13 @@ +#!/usr/bin/env ruby +dirname = "#{File.dirname(__FILE__)}/../file_system_root" +f = File.open('built_file_system', 'w') +Dir.foreach(dirname) do |item| + next if item == '.' or item == '..' + f2 = File.open("#{dirname}/#{item}") + f.write("FILE #{item} #{f2.size}\n") + f.write(f2.read) + f.write("\n") + f2.close +end + +f.close \ No newline at end of file diff --git a/stdlib.c b/stdlib.c index dfa6670..fe8fac7 100644 --- a/stdlib.c +++ b/stdlib.c @@ -18,4 +18,19 @@ void* malloc(uint32_t bytes) { } return chunk_start; +} + +bool isdigit(char c) { + return c >= '0' && c <= '9'; +} + +int atoi (const char * str) { + int value = 0; + while(isdigit(*str)) { + value *= 10; + value += (*str)-'0'; + str++; + } + + return value; } \ No newline at end of file diff --git a/stdlib.h b/stdlib.h index 5429d03..a3f6fc7 100644 --- a/stdlib.h +++ b/stdlib.h @@ -4,5 +4,6 @@ #include "types.h" void* malloc(uint32_t bytes); +int atoi (const char * str); #endif /* STDLIB_H */ \ No newline at end of file diff --git a/string.c b/string.c index e7f6a47..a32d417 100644 --- a/string.c +++ b/string.c @@ -19,5 +19,20 @@ int strcmp(const char * str1, const char * str2) { } // One of these points to 0 + return *str1 - *str2; +} + +int strncmp (const char * str1, const char * str2, uint32_t num) { + while (*str1 != 0 && *str2 != 0 && num > 1) { + int diff = *str1 - *str2; + if (diff != 0) { + return diff; + } + + str1++; + str2++; + num--; + } + return *str1 - *str2; } \ No newline at end of file diff --git a/string.h b/string.h index 94775ca..c59a567 100644 --- a/string.h +++ b/string.h @@ -1,6 +1,9 @@ #ifndef STRING_H #define STRING_H +#include "types.h" + int strcmp (const char * str1, const char * str2); +int strncmp (const char * str1, const char * str2, uint32_t num); #endif /* STRING_H */ \ No newline at end of file From 240d041057028ced5e8a0675ff6cf9e62d6fefc4 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 26 Nov 2016 17:05:01 -0800 Subject: [PATCH 59/67] Parse multiple files. --- Makefile | 2 +- filesystem.c | 60 ++++++++++++++++++++++++++-------------- interrupts.c | 1 - kmain.c | 8 ++++-- script/build_file_system | 20 ++++++++++---- 5 files changed, 59 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index eeabe24..469a279 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ user_program.o: user_program.c user_program.bin: user_program.o start_user_program.o $(STDLIB) $(LD) -T link_user_program.ld -melf_i386 $^ -o $@ -built_file_system: file_system_root/* +built_file_system: file_system_root/* user_program.bin script/build_file_system os.iso: kernel.elf user_program.bin menu.lst built_file_system diff --git a/filesystem.c b/filesystem.c index 01e0ca8..fda04d7 100644 --- a/filesystem.c +++ b/filesystem.c @@ -5,45 +5,63 @@ #include "stdlib.h" #include "string.h" -struct file_t* f; +struct file_t* first_file; +struct file_t* last_file; -void initialize_filesystem(struct module* mod) { - void* mod_virtual_start = (void*) (mod->mod_start + UPPER_GB_START); - - char* cursor = (char*) mod_virtual_start; - - if (strncmp(cursor, "FILE ", 5) != 0) { +struct file_t* parse_file(char** cursor) { + if (strncmp(*cursor, "FILE ", 5) != 0) { fprintf(LOG, "ERROR: First bytes of metadata should be `FILE ` but were `"); for (int i = 0; i < 5; i++) { - fprintf(LOG, "%c", cursor[i]); + fprintf(LOG, "%c", (*cursor)[i]); } fprintf(LOG, "`\n"); - fprintf(LOG, "strncmp returned %i\n", strncmp(cursor, "FILE ", 5)); + fprintf(LOG, "strncmp returned %i\n", strncmp(*cursor, "FILE ", 5)); fprintf(LOG, "cursor: %s", cursor); + while(1){} } - cursor += 5; + (*cursor) += 5; struct file_t* file = malloc(sizeof(struct file_t)); uint32_t file_name_length = 0; - while (*cursor != ' ' && file_name_length < FILE_NAME_MAX_LENGTH) { - file->name[file_name_length] = *cursor; - cursor++; + while (*(*cursor) != ' ' && file_name_length < FILE_NAME_MAX_LENGTH) { + file->name[file_name_length] = *(*cursor); + (*cursor)++; file_name_length++; } - cursor++; + (*cursor)++; - uint32_t file_size = atoi(cursor); + uint32_t file_size = atoi(*cursor); file->size = file_size; - while (*cursor != '\n') { - cursor++; + while (*(*cursor) != '\n') { + (*cursor)++; } - cursor++; - file->bytes = cursor; + (*cursor)++; + file->bytes = (*cursor); + + (*cursor) += file->size + 1; + + return file; +} - f = file; +void initialize_filesystem(struct module* mod) { + void* mod_virtual_start = (void*) (mod->mod_start + UPPER_GB_START); + char* mod_virtual_end = (mod->mod_end + UPPER_GB_START); + char* cursor = (char*) mod_virtual_start; + + while (cursor < mod_virtual_end) { + struct file_t* new_file = parse_file(&cursor); + if (!first_file) { + first_file = new_file; + } + if (last_file) { + last_file->next_sibling = new_file; + } else { + last_file = new_file; + } + } } struct file_t* get_file() { - return f; + return first_file; } diff --git a/interrupts.c b/interrupts.c index 0794edd..6edf5e8 100644 --- a/interrupts.c +++ b/interrupts.c @@ -64,7 +64,6 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t keyboard_interrupt_handler(); break; case(INT_PAGE_FAULT): - log_interrupt_details("INT_PAGE_FAULT", error_code, eip, &cpu); if ((error_code & 0b1) == 0) { // Caused by page-not-present page_in((void*) cpu.cr2); diff --git a/kmain.c b/kmain.c index 04c9cf0..ec82e49 100644 --- a/kmain.c +++ b/kmain.c @@ -138,9 +138,11 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { fprintf(LOG, " - done\n"); struct file_t* file = get_file(); - fprintf(LOG, "Name of file: %s\n", file->name); - fprintf(LOG, "Size of file: %i\n", file->size); - fprintf(LOG, "Contents of file:\n----\n%s\n----\n", file->bytes); + + while (file) { + fprintf(LOG, "%s (%i bytes)\n----\n%s\n----\n", file->name, file->size, file->bytes); + file = file->next_sibling; + } // fprintf(LOG, "- Creating a user process...\n"); // create_process(first_module(mbinfo)); diff --git a/script/build_file_system b/script/build_file_system index 524ef50..5cda100 100755 --- a/script/build_file_system +++ b/script/build_file_system @@ -1,13 +1,21 @@ #!/usr/bin/env ruby -dirname = "#{File.dirname(__FILE__)}/../file_system_root" + +def include_file(path, output_file) + f2 = File.open(path) + filename = path.split("/").last + output_file.write("FILE #{filename} #{f2.size}\n") + output_file.write(f2.read) + output_file.write("\n") + f2.close +end + f = File.open('built_file_system', 'w') +include_file("#{File.dirname(__FILE__)}/../user_program.bin", f) + +dirname = "#{File.dirname(__FILE__)}/../file_system_root" Dir.foreach(dirname) do |item| next if item == '.' or item == '..' - f2 = File.open("#{dirname}/#{item}") - f.write("FILE #{item} #{f2.size}\n") - f.write(f2.read) - f.write("\n") - f2.close + include_file("#{dirname}/#{item}", f) end f.close \ No newline at end of file From b9c5764b7d549d13cc7167dc971c5675b4f58b5e Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 27 Nov 2016 16:08:06 -0800 Subject: [PATCH 60/67] Start process from file. --- filesystem.c | 13 +++++++++++-- filesystem.h | 2 +- kmain.c | 13 ++++--------- process.c | 9 +++------ process.h | 3 ++- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/filesystem.c b/filesystem.c index fda04d7..a448701 100644 --- a/filesystem.c +++ b/filesystem.c @@ -62,6 +62,15 @@ void initialize_filesystem(struct module* mod) { } } -struct file_t* get_file() { - return first_file; +struct file_t* get_file(char* name) { + struct file_t* file = first_file; + + while (file) { + if (strcmp(file->name, name) == 0) { + return file; + } + file = file->next_sibling; + } + + return 0; } diff --git a/filesystem.h b/filesystem.h index f205ef5..bff3b71 100644 --- a/filesystem.h +++ b/filesystem.h @@ -13,6 +13,6 @@ struct file_t { }; void initialize_filesystem(struct module* mbinfo); -struct file_t* get_file(); +struct file_t* get_file(char* name); #endif /* INCLUDE_FILESYSTEM_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index ec82e49..5fb1aa8 100644 --- a/kmain.c +++ b/kmain.c @@ -137,16 +137,11 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { initialize_filesystem(first_module(mbinfo)); fprintf(LOG, " - done\n"); - struct file_t* file = get_file(); + struct file_t* file = get_file("user_program.bin"); - while (file) { - fprintf(LOG, "%s (%i bytes)\n----\n%s\n----\n", file->name, file->size, file->bytes); - file = file->next_sibling; - } - - // fprintf(LOG, "- Creating a user process...\n"); - // create_process(first_module(mbinfo)); - // fprintf(LOG, " - done\n"); + fprintf(LOG, "- Creating a user process...\n"); + create_process(file); + fprintf(LOG, " - done\n"); // Loop forever // User input is accepted asynchronously via interrupts diff --git a/process.c b/process.c index 941b7f2..c98e03f 100644 --- a/process.c +++ b/process.c @@ -13,7 +13,7 @@ struct process_t { page_directory_t pd; }; -void create_process(struct module* mod) { +void create_process(struct file_t* file) { struct process_t* p = malloc(sizeof(struct process_t)); p->pid = next_pid; next_pid += 1; @@ -87,11 +87,8 @@ void create_process(struct module* mod) { map_kernel_into_page_directory(pd); - uint32_t program_length_bytes = mod->mod_end - mod->mod_start; - void* mod_virtual_start = (void*) (mod->mod_start + UPPER_GB_START); - - for (uint32_t i = 0; i < program_length_bytes; i++) { - ((uint8_t*)user_code)[i] = ((uint8_t*)mod_virtual_start)[i]; + for (uint32_t i = 0; i < file->size; i++) { + ((char*)user_code)[i] = (file->bytes)[i]; } disable_hardware_interrupts(); diff --git a/process.h b/process.h index 1c41e0c..9989399 100644 --- a/process.h +++ b/process.h @@ -3,7 +3,8 @@ #include "multiboot.h" #include "types.h" +#include "filesystem.h" -void create_process(struct module* mod); +void create_process(struct file_t* file); #endif /* INCLUDE_PROCESS_H */ \ No newline at end of file From 1e71d6cd8e79f64abaa7c0b96c1e5a155f72236c Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 27 Nov 2016 17:12:47 -0800 Subject: [PATCH 61/67] Syscall to count files. --- Makefile | 9 ++--- asm_interrupts.s | 32 ++++++++++++++++- filesystem.h | 18 ---------- interrupts.c | 30 +++------------- interrupts.h | 2 +- filesystem.c => kernel_filesystem.c | 6 +++- kernel_filesystem.h | 12 +++++++ stdlib/assembly_functions.h | 8 ----- stdlib/syscalls.h | 11 ++++++ stdlib/{assembly_functions.s => syscalls.s} | 9 +++++ syscalls.c | 39 +++++++++++++++++++++ syscalls.h | 8 +++++ user_program.c | 11 ++++++ 13 files changed, 137 insertions(+), 58 deletions(-) delete mode 100644 filesystem.h rename filesystem.c => kernel_filesystem.c (95%) create mode 100644 kernel_filesystem.h delete mode 100644 stdlib/assembly_functions.h create mode 100644 stdlib/syscalls.h rename stdlib/{assembly_functions.s => syscalls.s} (58%) create mode 100644 syscalls.c create mode 100644 syscalls.h diff --git a/Makefile b/Makefile index 469a279..ea0c2c0 100644 --- a/Makefile +++ b/Makefile @@ -29,17 +29,18 @@ drivers/frame_buffer.o \ drivers/keyboard.o \ drivers/pic.o \ drivers/serial_port.o \ -filesystem.o \ interrupts.o \ +kernel_filesystem.o \ kmain.o \ multiboot_utils.o \ process.o \ stdio.o \ stdlib.o \ -string.o +string.o \ +syscalls.o -STDLIB = stdlib/assembly_functions.o \ -stdlib/stdio.o +STDLIB = stdlib/stdio.o \ +stdlib/syscalls.o all: os.iso diff --git a/asm_interrupts.s b/asm_interrupts.s index 8bbcb0b..4d1a749 100644 --- a/asm_interrupts.s +++ b/asm_interrupts.s @@ -772,7 +772,7 @@ global interrupt_handler_128 interrupt_handler_128: push dword 0 push dword 128 - jmp common_interrupt_handler + jmp interrupt_handler_with_return_value global interrupt_handler_129 interrupt_handler_129: @@ -1566,3 +1566,33 @@ common_interrupt_handler: ; the common parts of the generic interr ; return to the code that got interrupted iret + +interrupt_handler_with_return_value: + push eax + push ebx + push ecx + push edx + push esi + push edi + push ebp + mov eax, cr2 + push eax + + ; call the C function + call interrupt_handler + + ; restore the registers + add esp, 4 ; cr2 + pop ebp + pop edi + pop esi + pop edx + pop ecx + pop ebx + ; don't pop eax. It contains the return value + + ; pop eax, error_code and interrupt_number off the stack + add esp, 12 + + ; return to the code that got interrupted + iret diff --git a/filesystem.h b/filesystem.h deleted file mode 100644 index bff3b71..0000000 --- a/filesystem.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef INCLUDE_FILESYSTEM_H -#define INCLUDE_FILESYSTEM_H - -#include "types.h" -#include "multiboot.h" - -#define FILE_NAME_MAX_LENGTH 63 -struct file_t { - char name[FILE_NAME_MAX_LENGTH+1]; - uint32_t size; - char* bytes; - struct file_t* next_sibling; -}; - -void initialize_filesystem(struct module* mbinfo); -struct file_t* get_file(char* name); - -#endif /* INCLUDE_FILESYSTEM_H */ \ No newline at end of file diff --git a/interrupts.c b/interrupts.c index 6edf5e8..abadb8b 100644 --- a/interrupts.c +++ b/interrupts.c @@ -8,6 +8,7 @@ #include "loader.h" #include "memory.h" #include "stdio.h" +#include "syscalls.h" void log_stack_trace_line(uint32_t eip) { char * symbol_name = address_to_symbol_name(eip); @@ -36,29 +37,7 @@ void log_interrupt_details(char* int_name, uint32_t error_code, uint32_t eip, st fprintf(LOG, "--------------------\n"); } -void sys_write_to_screen(char* s) { - fprintf(LOG, "sys_write_to_screen(%s)\n", s); - printf(s); -} - -void handle_syscall(struct cpu_state* cpu) { - uint32_t syscall_num = cpu->eax; - - fprintf(LOG, "--------------------\nSYSCALL (%i)\n", syscall_num); - - switch (syscall_num) { - case (1): - sys_write_to_screen((char*) cpu->ebx); - break; - default: - fprintf(LOG, "Unknown syscall: %x\n", syscall_num); - while(1){} - } - - fprintf(LOG, "--------------------\n"); -} - -void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip) { +uint32_t interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip) { switch(interrupt_number) { case(INT_KEYBOARD): keyboard_interrupt_handler(); @@ -100,8 +79,7 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t break; case(INT_SYSCALL): - handle_syscall(&cpu); - break; + return handle_syscall(&cpu); case(INT_OUT_OF_MEMORY): log_interrupt_details("INT_OUT_OF_MEMORY", error_code, eip, &cpu); @@ -116,4 +94,6 @@ void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t } pic_acknowledge(); + + return 0; } diff --git a/interrupts.h b/interrupts.h index cfc48b5..5bdca99 100644 --- a/interrupts.h +++ b/interrupts.h @@ -22,6 +22,6 @@ struct cpu_state { } __attribute__((packed)); void enable_keyboard_interrupts(); -void interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip); +uint32_t interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint32_t error_code, uint32_t eip); #endif /* INCLUDE_INTERRUPTS_H */ \ No newline at end of file diff --git a/filesystem.c b/kernel_filesystem.c similarity index 95% rename from filesystem.c rename to kernel_filesystem.c index a448701..ad9167f 100644 --- a/filesystem.c +++ b/kernel_filesystem.c @@ -1,4 +1,4 @@ -#include "filesystem.h" +#include "kernel_filesystem.h" #include "memory.h" #include "stdio.h" @@ -74,3 +74,7 @@ struct file_t* get_file(char* name) { return 0; } + +struct file_t* get_first_file() { + return first_file; +} diff --git a/kernel_filesystem.h b/kernel_filesystem.h new file mode 100644 index 0000000..2847986 --- /dev/null +++ b/kernel_filesystem.h @@ -0,0 +1,12 @@ +#ifndef INCLUDE_KERNEL_FILESYSTEM_H +#define INCLUDE_KERNEL_FILESYSTEM_H + +#include "types.h" +#include "multiboot.h" +#include "stdlib/filesystem.h" + +void initialize_filesystem(struct module* mbinfo); +struct file_t* get_file(char* name); +struct file_t* get_first_file(); + +#endif /* INCLUDE_KERNEL_FILESYSTEM_H */ \ No newline at end of file diff --git a/stdlib/assembly_functions.h b/stdlib/assembly_functions.h deleted file mode 100644 index 5f34db8..0000000 --- a/stdlib/assembly_functions.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef INCLUDE_ASSEMBLY_FUNCTIONS_H -#define INCLUDE_ASSEMBLY_FUNCTIONS_H - -#include "../types.h" - -void write_to_screen(char* s); - -#endif /* INCLUDE_ASSEMBLY_FUNCTIONS_H */ \ No newline at end of file diff --git a/stdlib/syscalls.h b/stdlib/syscalls.h new file mode 100644 index 0000000..31b3f87 --- /dev/null +++ b/stdlib/syscalls.h @@ -0,0 +1,11 @@ +#ifndef INCLUDE_SYSCALLS_H +#define INCLUDE_SYSCALLS_H + +#include "types.h" +#include "filesystem.h" + +void write_to_screen(char* s); +uint32_t count_files(); +void list_files(struct file_t buffer[]); + +#endif /* INCLUDE_SYSCALLS_H */ \ No newline at end of file diff --git a/stdlib/assembly_functions.s b/stdlib/syscalls.s similarity index 58% rename from stdlib/assembly_functions.s rename to stdlib/syscalls.s index 4a5a55c..9ea1fdb 100644 --- a/stdlib/assembly_functions.s +++ b/stdlib/syscalls.s @@ -8,3 +8,12 @@ write_to_screen: mov ebx, [esp+4] int 0x80 ret ; return to the calling function + +global count_files +; count_files +; stack: [esp ] return address +count_files: + mov eax, 2 + int 0x80 + ret ; return to the calling function + diff --git a/syscalls.c b/syscalls.c new file mode 100644 index 0000000..db3d1ee --- /dev/null +++ b/syscalls.c @@ -0,0 +1,39 @@ +#include "syscalls.h" + +#include "kernel_filesystem.h" +#include "stdio.h" + +uint32_t sys_write_to_screen(char* s) { + fprintf(LOG, "sys_write_to_screen(%s)\n", s); + printf(s); + return 0; +} + +uint32_t sys_count_files() { + struct file_t* file = get_first_file(); + uint32_t count = 0; + while (file) { + count++; + file = file->next_sibling; + } + + return count; +} + +uint32_t handle_syscall(struct cpu_state* cpu) { + uint32_t syscall_num = cpu->eax; + + fprintf(LOG, "--------------------\nSYSCALL (%i)\n", syscall_num); + + switch (syscall_num) { + case (1): + return sys_write_to_screen((char*) cpu->ebx); + case (2): + return sys_count_files(); + default: + fprintf(LOG, "Unknown syscall: %x\n", syscall_num); + while(1){} + } + + fprintf(LOG, "--------------------\n"); +} \ No newline at end of file diff --git a/syscalls.h b/syscalls.h new file mode 100644 index 0000000..1732ab7 --- /dev/null +++ b/syscalls.h @@ -0,0 +1,8 @@ +#ifndef INCLUDE_SYSCALLS_H +#define INCLUDE_SYSCALLS_H + +#include "interrupts.h" + +uint32_t handle_syscall(struct cpu_state* cpu); + +#endif /* INCLUDE_SYSCALLS_H */ \ No newline at end of file diff --git a/user_program.c b/user_program.c index b783a25..4628311 100644 --- a/user_program.c +++ b/user_program.c @@ -1,4 +1,5 @@ #include "stdlib/stdio.h" +#include "stdlib/syscalls.h" int fib(unsigned int n) { if (n == 0) { @@ -18,5 +19,15 @@ int main() { printf("\n----\nHello World!\n----\n"); printf("fib(20) -> %i\n", result); + uint32_t num_files = count_files(); + // struct file_t* files = malloc(sizeof(file_t)); + // list_files(files); + + printf("\nFiles: %d\n", num_files); + // for (uint32_t i = 0; i < num_files; i++) { + // file_t* file = files[i]; + // printf("%s\n", file->name); + // } + return result; } From 5144fb02af66afe24de8322a8b20f20a18dd8b02 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 27 Nov 2016 17:44:21 -0800 Subject: [PATCH 62/67] Print out file names. --- interrupts.c | 1 + kmain.c | 2 +- process.h | 2 +- stdlib/filesystem.h | 12 ++++++++++++ stdlib/syscalls.s | 9 +++++++++ string.c | 13 +++++++++++++ string.h | 1 + syscalls.c | 13 +++++++++++++ user_program.c | 15 ++++++++------- 9 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 stdlib/filesystem.h diff --git a/interrupts.c b/interrupts.c index abadb8b..afed433 100644 --- a/interrupts.c +++ b/interrupts.c @@ -48,6 +48,7 @@ uint32_t interrupt_handler(struct cpu_state cpu, uint32_t interrupt_number, uint page_in((void*) cpu.cr2); break; } + log_interrupt_details("INT_PAGE_FAULT", error_code, eip, &cpu); fprintf(LOG, "Interrupt was a page fault. Here's what I know:\n"); fprintf(LOG, "- Tried to access virtual address %x\n", cpu.cr2); if (error_code & 0b1) { diff --git a/kmain.c b/kmain.c index 5fb1aa8..f6ec5d0 100644 --- a/kmain.c +++ b/kmain.c @@ -6,7 +6,7 @@ #include "drivers/frame_buffer.h" #include "drivers/pic.h" #include "drivers/serial_port.h" -#include "filesystem.h" +#include "kernel_filesystem.h" #include "multiboot_utils.h" #include "process.h" #include "stdio.h" diff --git a/process.h b/process.h index 9989399..34fec83 100644 --- a/process.h +++ b/process.h @@ -3,7 +3,7 @@ #include "multiboot.h" #include "types.h" -#include "filesystem.h" +#include "kernel_filesystem.h" void create_process(struct file_t* file); diff --git a/stdlib/filesystem.h b/stdlib/filesystem.h new file mode 100644 index 0000000..2572ad1 --- /dev/null +++ b/stdlib/filesystem.h @@ -0,0 +1,12 @@ +#ifndef INCLUDE_FILESYSTEM_H +#define INCLUDE_FILESYSTEM_H + +#define FILE_NAME_MAX_LENGTH 63 +struct file_t { + char name[FILE_NAME_MAX_LENGTH+1]; + uint32_t size; + char* bytes; + struct file_t* next_sibling; +}; + +#endif /* INCLUDE_FILESYSTEM_H */ \ No newline at end of file diff --git a/stdlib/syscalls.s b/stdlib/syscalls.s index 9ea1fdb..6a3200c 100644 --- a/stdlib/syscalls.s +++ b/stdlib/syscalls.s @@ -17,3 +17,12 @@ count_files: int 0x80 ret ; return to the calling function +global list_files +; list_files +; stack: [esp + 4] address of buffer +; [esp ] return address +list_files: + mov eax, 3 + mov ebx, [esp+4] + int 0x80 + ret ; return to the calling function diff --git a/string.c b/string.c index a32d417..8bbd046 100644 --- a/string.c +++ b/string.c @@ -35,4 +35,17 @@ int strncmp (const char * str1, const char * str2, uint32_t num) { } return *str1 - *str2; +} + +void* memcpy (void* dest, const void* src, uint32_t count) { + char* dest_byte = (char*) dest; + char* src_byte = (char*) src; + + for (uint32_t i = 0; i < count; i++) { + *dest_byte = *src_byte; + dest_byte++; + src_byte++; + } + + return dest; } \ No newline at end of file diff --git a/string.h b/string.h index c59a567..d1b7ea6 100644 --- a/string.h +++ b/string.h @@ -3,6 +3,7 @@ #include "types.h" +void* memcpy (void* dest, const void* src, uint32_t count); int strcmp (const char * str1, const char * str2); int strncmp (const char * str1, const char * str2, uint32_t num); diff --git a/syscalls.c b/syscalls.c index db3d1ee..93ca29d 100644 --- a/syscalls.c +++ b/syscalls.c @@ -20,6 +20,17 @@ uint32_t sys_count_files() { return count; } +uint32_t sys_list_files(struct file_t* buffer) { + struct file_t* file = get_first_file(); + while (file) { + *buffer = *file; + buffer++; + file = file->next_sibling; + } + + return 0; +} + uint32_t handle_syscall(struct cpu_state* cpu) { uint32_t syscall_num = cpu->eax; @@ -30,6 +41,8 @@ uint32_t handle_syscall(struct cpu_state* cpu) { return sys_write_to_screen((char*) cpu->ebx); case (2): return sys_count_files(); + case (3): + return sys_list_files((struct file_t *) cpu->ebx); default: fprintf(LOG, "Unknown syscall: %x\n", syscall_num); while(1){} diff --git a/user_program.c b/user_program.c index 4628311..de78121 100644 --- a/user_program.c +++ b/user_program.c @@ -1,5 +1,6 @@ #include "stdlib/stdio.h" #include "stdlib/syscalls.h" +#include "stdlib/filesystem.h" int fib(unsigned int n) { if (n == 0) { @@ -19,15 +20,15 @@ int main() { printf("\n----\nHello World!\n----\n"); printf("fib(20) -> %i\n", result); - uint32_t num_files = count_files(); - // struct file_t* files = malloc(sizeof(file_t)); - // list_files(files); + struct file_t files[10]; + uint32_t num_files = count_files(); printf("\nFiles: %d\n", num_files); - // for (uint32_t i = 0; i < num_files; i++) { - // file_t* file = files[i]; - // printf("%s\n", file->name); - // } + list_files(files); + + for (uint32_t i = 0; i < num_files; i++) { + printf("%s\n", files[i].name); + } return result; } From 527799e52c4a578b23b77ae17d83fb528176f7e4 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 4 Dec 2016 16:38:39 -0800 Subject: [PATCH 63/67] A shell with Makefile NOTES README.md TODO asm_interrupts.h asm_interrupts.o asm_interrupts.s assembly_interface.h assembly_interface.o assembly_interface.s built_file_system data_structures drivers elf.h file_system_root filesystem.o interrupts.c interrupts.h interrupts.o iso kernel.elf kernel_filesystem.c kernel_filesystem.h kernel_filesystem.o kernel_stdio.c kernel_stdio.h kernel_stdio.o kernel_syscalls.c kernel_syscalls.h kernel_syscalls.o kmain.c kmain.o link.ld link_user_program.ld loader.h loader.o loader.s log memory.h menu.lst multiboot.h multiboot_utils.c multiboot_utils.h multiboot_utils.o os.iso process.c process.h process.o program.s script stage2_eltorito start_user_program.o start_user_program.s stdarg.h stdlib stdlib.c stdlib.h stdlib.o syscalls.o types.h user_program.bin user_program.c user_program.o command. --- .gitignore | 1 + Makefile | 14 +++---- data_structures/global_descriptor_table.c | 2 +- data_structures/page_table.h | 2 +- data_structures/symbol_table.c | 2 +- drivers/frame_buffer.c | 7 +++- drivers/keyboard.c | 38 ++++++++++++++++- drivers/keyboard.h | 2 + drivers/pic.c | 2 +- interrupts.c | 4 +- kernel_filesystem.c | 4 +- stdio.c => kernel_stdio.c | 51 +++++++---------------- stdio.h => kernel_stdio.h | 1 - syscalls.c => kernel_syscalls.c | 15 +++++-- kernel_syscalls.h | 8 ++++ kmain.c | 4 +- multiboot_utils.c | 2 +- multiboot_utils.h | 2 +- process.c | 4 +- stdlib/filesystem.h | 2 + string.c => stdlib/string.c | 0 string.h => stdlib/string.h | 0 stdlib/syscalls.h | 3 ++ stdlib/syscalls.s | 10 +++++ syscalls.h | 8 ---- user_program.c | 44 +++++++++---------- 26 files changed, 137 insertions(+), 95 deletions(-) rename stdio.c => kernel_stdio.c (72%) rename stdio.h => kernel_stdio.h (81%) rename syscalls.c => kernel_syscalls.c (75%) create mode 100644 kernel_syscalls.h rename string.c => stdlib/string.c (100%) rename string.h => stdlib/string.h (100%) delete mode 100644 syscalls.h diff --git a/.gitignore b/.gitignore index bc9df09..e1f69f9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ stage2_eltorito log/ built_file_system TODO +NOTES diff --git a/Makefile b/Makefile index ea0c2c0..721017e 100644 --- a/Makefile +++ b/Makefile @@ -31,15 +31,15 @@ drivers/pic.o \ drivers/serial_port.o \ interrupts.o \ kernel_filesystem.o \ +kernel_stdio.o \ +kernel_syscalls.o \ kmain.o \ multiboot_utils.o \ process.o \ -stdio.o \ -stdlib.o \ -string.o \ -syscalls.o +stdlib.o STDLIB = stdlib/stdio.o \ +stdlib/string.o \ stdlib/syscalls.o all: os.iso @@ -52,8 +52,8 @@ all: os.iso # assemble s files with nasm $(NASM) $(ASFLAGS) $< -o $@ -kernel.elf: $(OBJECTS) - $(LD) -T link.ld -melf_i386 $(OBJECTS) -o kernel.elf # Link to make an executable for the kernel. +kernel.elf: $(OBJECTS) $(STDLIB) + $(LD) -T link.ld -melf_i386 $^ -o kernel.elf # Link to make an executable for the kernel. start_user_program.o: start_user_program.s $(NASM) $(ASFLAGS) $< -o $@ @@ -96,4 +96,4 @@ clean: rm -f *.bin # flat binary executables rm -f *.out rm -rf iso/ - rm built_file_system + rm -f built_file_system diff --git a/data_structures/global_descriptor_table.c b/data_structures/global_descriptor_table.c index 224817e..4c531af 100644 --- a/data_structures/global_descriptor_table.c +++ b/data_structures/global_descriptor_table.c @@ -2,7 +2,7 @@ #include "../assembly_interface.h" #include "../loader.h" -#include "../stdio.h" +#include "../kernel_stdio.h" #include "../memory.h" // A struct describing a Task State Segment. diff --git a/data_structures/page_table.h b/data_structures/page_table.h index ba0902b..91f760f 100644 --- a/data_structures/page_table.h +++ b/data_structures/page_table.h @@ -2,7 +2,7 @@ #define INCLUDE_PAGE_TABLE_H #include "../multiboot.h" -#include "../stdio.h" +#include "../kernel_stdio.h" #include "../types.h" struct kernel_memory_descriptor_t { diff --git a/data_structures/symbol_table.c b/data_structures/symbol_table.c index ed79f8c..ce6ef27 100644 --- a/data_structures/symbol_table.c +++ b/data_structures/symbol_table.c @@ -2,7 +2,7 @@ #include "../loader.h" #include "../multiboot_utils.h" -#include "../stdio.h" +#include "../kernel_stdio.h" struct symbol_table_descriptor_t { bool present; diff --git a/drivers/frame_buffer.c b/drivers/frame_buffer.c index cd3b7da..457b8a8 100644 --- a/drivers/frame_buffer.c +++ b/drivers/frame_buffer.c @@ -3,7 +3,7 @@ #include "frame_buffer.h" #include "../assembly_interface.h" -#include "../stdio.h" +#include "../kernel_stdio.h" /* The I/O ports */ #define FB_COMMAND_PORT 0x3D4 @@ -91,7 +91,12 @@ void fb_write_byte(uint8_t b) { } else { fb_write_cell(cursor_pos, b, FB_WHITE, FB_BLACK); cursor_pos++; + if (cursor_pos == FB_CELLS) { + scroll(); + cursor_pos -= FB_COLS; + } } + move_cursor_to_pos(cursor_pos); } void fb_backspace() { diff --git a/drivers/keyboard.c b/drivers/keyboard.c index e13f3c6..4caecc7 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -2,7 +2,7 @@ #include "frame_buffer.h" #include "../assembly_interface.h" -#include "../stdio.h" +#include "../kernel_stdio.h" #include "../types.h" #define KBD_DATA_PORT 0x60 @@ -279,6 +279,40 @@ bool lshift_pressed; bool rshift_pressed; bool extended_scan_code; +#define INPUT_BUFFER_SIZE 80 +uint8_t input_buffer_occupancy = 0; +char input_buffer[INPUT_BUFFER_SIZE+1]; + +void input_buffer_backspace() { + if (input_buffer_occupancy > 0) { + input_buffer_occupancy -= 1; + input_buffer[input_buffer_occupancy] = 0; + } +} + +InputHandler input_handler = 0; + +void set_input_handler(InputHandler handler) { + input_handler = handler; +} + +void append_to_input_buffer(char c) { + if (c == '\n') { + fprintf(LOG, "flush input buffer: %s\n", input_buffer); + if (input_handler != 0) { + input_handler(input_buffer); + } + input_buffer_occupancy = 0; + input_buffer[0] = 0; + } else if (input_buffer_occupancy < INPUT_BUFFER_SIZE) { + input_buffer[input_buffer_occupancy] = c; + input_buffer_occupancy += 1; + input_buffer[input_buffer_occupancy] = 0; + } else { + fprintf(LOG, "Error: dropped input because input buffer is full.\n"); + } +} + uint8_t read_scan_code() { return inb(KBD_DATA_PORT); @@ -298,6 +332,7 @@ void keyboard_interrupt_handler() { } if (scan_code == BACKSPACE) { + input_buffer_backspace(); fb_backspace(); return; } @@ -312,5 +347,6 @@ void keyboard_interrupt_handler() { if (c != 0) { fprintf(LOG, "%c", c); fprintf(SCREEN, "%c", c); + append_to_input_buffer(c); } } diff --git a/drivers/keyboard.h b/drivers/keyboard.h index a8974b4..d64ac68 100644 --- a/drivers/keyboard.h +++ b/drivers/keyboard.h @@ -2,8 +2,10 @@ #define INCLUDE_KEYBOARD_H #include "../types.h" +#include "../stdlib/syscalls.h" void keyboard_interrupt_handler(); +void set_input_handler(InputHandler handler); uint8_t read_scan_code(); #endif /* INCLUDE_KEYBOARD_H */ \ No newline at end of file diff --git a/drivers/pic.c b/drivers/pic.c index d327d0c..3ee19f8 100644 --- a/drivers/pic.c +++ b/drivers/pic.c @@ -1,6 +1,6 @@ #include "pic.h" #include "../assembly_interface.h" -#include "../stdio.h" +#include "../kernel_stdio.h" #define PIC1 0x20 /* IO base address for master PIC */ #define PIC2 0xA0 /* IO base address for slave PIC */ diff --git a/interrupts.c b/interrupts.c index afed433..c079888 100644 --- a/interrupts.c +++ b/interrupts.c @@ -7,8 +7,8 @@ #include "drivers/pic.h" #include "loader.h" #include "memory.h" -#include "stdio.h" -#include "syscalls.h" +#include "kernel_stdio.h" +#include "kernel_syscalls.h" void log_stack_trace_line(uint32_t eip) { char * symbol_name = address_to_symbol_name(eip); diff --git a/kernel_filesystem.c b/kernel_filesystem.c index ad9167f..95b9e27 100644 --- a/kernel_filesystem.c +++ b/kernel_filesystem.c @@ -1,9 +1,9 @@ #include "kernel_filesystem.h" #include "memory.h" -#include "stdio.h" +#include "kernel_stdio.h" #include "stdlib.h" -#include "string.h" +#include "stdlib/string.h" struct file_t* first_file; struct file_t* last_file; diff --git a/stdio.c b/kernel_stdio.c similarity index 72% rename from stdio.c rename to kernel_stdio.c index 797d92c..a475e85 100644 --- a/stdio.c +++ b/kernel_stdio.c @@ -1,4 +1,5 @@ -#include "stdio.h" +#include "kernel_stdio.h" + #include "drivers/frame_buffer.h" #include "drivers/serial_port.h" @@ -15,7 +16,7 @@ write_byte_t write_byte_function(FILE stream) { } } -void write_half_byte(write_byte_t write_byte, uint8_t half_byte, bool upcase) { +void kernel_write_half_byte(write_byte_t write_byte, uint8_t half_byte, bool upcase) { switch (half_byte) { case 0x0: write_byte('0'); @@ -68,26 +69,14 @@ void write_half_byte(write_byte_t write_byte, uint8_t half_byte, bool upcase) { } } -void print_uint8(FILE stream, uint8_t data) { - write_byte_t write_byte = write_byte_function(stream); - - uint8_t half_byte; - write_byte('0'); - write_byte('x'); - for (int i = 1; i >=0; i--) { - half_byte = (data >> (4*i)) & 0x0F; - write_half_byte(write_byte, half_byte, true); - } -} - -void write_string(write_byte_t write_byte, char* s) { +void kernel_write_string(write_byte_t write_byte, char* s) { while(*s) { write_byte(*s); s++; } } -void write_uint(write_byte_t write_byte, uint32_t value) { +void kernel_write_uint(write_byte_t write_byte, uint32_t value) { char output[10]; for (int place = 0; place < 10; place++) { output[place] = value % 10; @@ -106,21 +95,21 @@ void write_uint(write_byte_t write_byte, uint32_t value) { } } -void write_int(write_byte_t write_byte, int value) { +void kernel_write_int(write_byte_t write_byte, int value) { if (value < 0) { write_byte('-'); value *= -1; } - write_uint(write_byte, value); + kernel_write_uint(write_byte, value); } -void write_octal(write_byte_t write_byte, uint32_t value) { +void kernel_write_octal(write_byte_t write_byte, uint32_t value) { write_byte('0'); write_byte('o'); bool past_leading_zeroes = false; uint8_t part = (value >> 30) & 0b11; if (part > 0) { - write_half_byte(write_byte, part, true); + kernel_write_half_byte(write_byte, part, true); past_leading_zeroes = true; } for (int i = 10; i >=0; i--) { @@ -130,7 +119,7 @@ void write_octal(write_byte_t write_byte, uint32_t value) { } if (past_leading_zeroes) { - write_half_byte(write_byte, part, true); + kernel_write_half_byte(write_byte, part, true); } } } @@ -160,26 +149,26 @@ int fprintf (FILE stream, const char * format, ...) { } else if (format[i] == 'c') { write_byte((uint32_t) va_arg(vl,uint32_t)); } else if (format[i] == 'i' || format[i] == 'd') { - write_int(write_byte, va_arg(vl, int)); + kernel_write_int(write_byte, va_arg(vl, int)); } else if (format[i] == 'o') { - write_octal(write_byte, va_arg(vl, int)); + kernel_write_octal(write_byte, va_arg(vl, int)); } else if (format[i] == 's') { - write_string(write_byte, (char*) va_arg(vl,char*)); + kernel_write_string(write_byte, (char*) va_arg(vl,char*)); } else if (format[i] == 'u') { - write_uint(write_byte, va_arg(vl, uint32_t)); + kernel_write_uint(write_byte, va_arg(vl, uint32_t)); } else if (format[i] == 'x') { write_byte('0'); write_byte('x'); vararg = va_arg(vl,uint32_t); for (int i = 7; i >=0; i--) { - write_half_byte(write_byte, (vararg >> (4*i)) & 0x0F, false); + kernel_write_half_byte(write_byte, (vararg >> (4*i)) & 0x0F, false); } } else if (format[i] == 'X') { write_byte('0'); write_byte('x'); vararg = va_arg(vl,uint32_t); for (int i = 7; i >=0; i--) { - write_half_byte(write_byte, (vararg >> (4*i)) & 0x0F, true); + kernel_write_half_byte(write_byte, (vararg >> (4*i)) & 0x0F, true); } } else { write_byte('?'); @@ -191,12 +180,4 @@ int fprintf (FILE stream, const char * format, ...) { i++; } return i; -} - -int printf (const char * format, ...) { - return fprintf(SCREEN, format); -} - -int log(char * format, ...) { - return fprintf(LOG, format); } \ No newline at end of file diff --git a/stdio.h b/kernel_stdio.h similarity index 81% rename from stdio.h rename to kernel_stdio.h index 8485cf7..9ec19a0 100644 --- a/stdio.h +++ b/kernel_stdio.h @@ -6,6 +6,5 @@ typedef enum output_t {SCREEN, LOG} FILE; int fprintf (FILE stream, const char * format, ...); -int printf (const char * format, ...); #endif /* STDIO_H */ \ No newline at end of file diff --git a/syscalls.c b/kernel_syscalls.c similarity index 75% rename from syscalls.c rename to kernel_syscalls.c index 93ca29d..b27400f 100644 --- a/syscalls.c +++ b/kernel_syscalls.c @@ -1,11 +1,13 @@ -#include "syscalls.h" +#include "kernel_syscalls.h" +#include "drivers/keyboard.h" #include "kernel_filesystem.h" -#include "stdio.h" +#include "kernel_stdio.h" +#include "stdlib/syscalls.h" uint32_t sys_write_to_screen(char* s) { fprintf(LOG, "sys_write_to_screen(%s)\n", s); - printf(s); + fprintf(SCREEN, s); return 0; } @@ -31,6 +33,11 @@ uint32_t sys_list_files(struct file_t* buffer) { return 0; } +uint32_t sys_register_input_handler(InputHandler handler) { + set_input_handler(handler); + return 0; +} + uint32_t handle_syscall(struct cpu_state* cpu) { uint32_t syscall_num = cpu->eax; @@ -43,6 +50,8 @@ uint32_t handle_syscall(struct cpu_state* cpu) { return sys_count_files(); case (3): return sys_list_files((struct file_t *) cpu->ebx); + case (4): + return sys_register_input_handler((InputHandler) cpu->ebx); default: fprintf(LOG, "Unknown syscall: %x\n", syscall_num); while(1){} diff --git a/kernel_syscalls.h b/kernel_syscalls.h new file mode 100644 index 0000000..0682b99 --- /dev/null +++ b/kernel_syscalls.h @@ -0,0 +1,8 @@ +#ifndef INCLUDE_KERNEL_SYSCALLS_H +#define INCLUDE_KERNEL_SYSCALLS_H + +#include "interrupts.h" + +uint32_t handle_syscall(struct cpu_state* cpu); + +#endif /* INCLUDE_KERNEL_SYSCALLS_H */ \ No newline at end of file diff --git a/kmain.c b/kmain.c index f6ec5d0..5d081f4 100644 --- a/kmain.c +++ b/kmain.c @@ -9,7 +9,7 @@ #include "kernel_filesystem.h" #include "multiboot_utils.h" #include "process.h" -#include "stdio.h" +#include "kernel_stdio.h" #include "stdlib.h" #include "types.h" @@ -58,7 +58,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { clear_screen(); - printf(welcome_string); + fprintf(SCREEN, welcome_string); serial_init(); fprintf(LOG, "\n--------------------\ncstackOS is booting!\n--------------------\n\n"); diff --git a/multiboot_utils.c b/multiboot_utils.c index 54ba356..4e84811 100644 --- a/multiboot_utils.c +++ b/multiboot_utils.c @@ -1,7 +1,7 @@ #include "multiboot_utils.h" #include "elf.h" #include "loader.h" -#include "string.h" +#include "stdlib/string.h" uint32_t p_to_v(uint32_t physical_address) { return physical_address + (uint32_t) &KERNEL_VIRTUAL_BASE; diff --git a/multiboot_utils.h b/multiboot_utils.h index e97a6b5..e4bcf73 100644 --- a/multiboot_utils.h +++ b/multiboot_utils.h @@ -2,7 +2,7 @@ #define MULTIBOOT_UTILS_H #include "multiboot.h" -#include "stdio.h" +#include "kernel_stdio.h" #include "types.h" struct module* first_module(multiboot_info_t* info); diff --git a/process.c b/process.c index c98e03f..18f26b7 100644 --- a/process.c +++ b/process.c @@ -3,7 +3,7 @@ #include "assembly_interface.h" #include "data_structures/page_table.h" #include "memory.h" -#include "stdio.h" +#include "kernel_stdio.h" #include "stdlib.h" uint32_t next_pid = 0; @@ -91,8 +91,6 @@ void create_process(struct file_t* file) { ((char*)user_code)[i] = (file->bytes)[i]; } - disable_hardware_interrupts(); - set_page_directory(virtual_to_physical(pd)); enter_user_mode(); diff --git a/stdlib/filesystem.h b/stdlib/filesystem.h index 2572ad1..3eec210 100644 --- a/stdlib/filesystem.h +++ b/stdlib/filesystem.h @@ -1,6 +1,8 @@ #ifndef INCLUDE_FILESYSTEM_H #define INCLUDE_FILESYSTEM_H +#include "types.h" + #define FILE_NAME_MAX_LENGTH 63 struct file_t { char name[FILE_NAME_MAX_LENGTH+1]; diff --git a/string.c b/stdlib/string.c similarity index 100% rename from string.c rename to stdlib/string.c diff --git a/string.h b/stdlib/string.h similarity index 100% rename from string.h rename to stdlib/string.h diff --git a/stdlib/syscalls.h b/stdlib/syscalls.h index 31b3f87..180d768 100644 --- a/stdlib/syscalls.h +++ b/stdlib/syscalls.h @@ -8,4 +8,7 @@ void write_to_screen(char* s); uint32_t count_files(); void list_files(struct file_t buffer[]); +typedef void (*InputHandler)(char*); +void register_input_handler(InputHandler handler); + #endif /* INCLUDE_SYSCALLS_H */ \ No newline at end of file diff --git a/stdlib/syscalls.s b/stdlib/syscalls.s index 6a3200c..af340ef 100644 --- a/stdlib/syscalls.s +++ b/stdlib/syscalls.s @@ -26,3 +26,13 @@ list_files: mov ebx, [esp+4] int 0x80 ret ; return to the calling function + +global register_input_handler +; register_input_handler +; stack: [esp + 4] address of handler +; [esp ] return address +register_input_handler: + mov eax, 4 + mov ebx, [esp+4] + int 0x80 + ret ; return to the calling function diff --git a/syscalls.h b/syscalls.h deleted file mode 100644 index 1732ab7..0000000 --- a/syscalls.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef INCLUDE_SYSCALLS_H -#define INCLUDE_SYSCALLS_H - -#include "interrupts.h" - -uint32_t handle_syscall(struct cpu_state* cpu); - -#endif /* INCLUDE_SYSCALLS_H */ \ No newline at end of file diff --git a/user_program.c b/user_program.c index de78121..9fbfdf1 100644 --- a/user_program.c +++ b/user_program.c @@ -1,34 +1,30 @@ +#include "stdlib/filesystem.h" #include "stdlib/stdio.h" +#include "stdlib/string.h" #include "stdlib/syscalls.h" -#include "stdlib/filesystem.h" -int fib(unsigned int n) { - if (n == 0) { - return 0; - } +void print_prompt() { + printf("> "); +} - if (n == 1) { - return 1; +void handle_input(char* input) { + if (strcmp(input, "ls") == 0) { + struct file_t files[10]; + uint32_t num_files = count_files(); + list_files(files); + for (uint32_t i = 0; i < num_files; i++) { + printf("%s\n", files[i].name); + } + } else { + printf("Unknown command `%s`\n", input); } - - return fib(n-1) + fib(n-2); + printf("> "); } int main() { - int result = fib(20); // Should be 0x1a6d - - printf("\n----\nHello World!\n----\n"); - printf("fib(20) -> %i\n", result); - - struct file_t files[10]; - - uint32_t num_files = count_files(); - printf("\nFiles: %d\n", num_files); - list_files(files); - - for (uint32_t i = 0; i < num_files; i++) { - printf("%s\n", files[i].name); - } + print_prompt(); + register_input_handler(handle_input); + while(1){} - return result; + return 0; } From 224db4d34fd8bab47d8318d73b457faba61e8525 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 4 Dec 2016 19:01:33 -0800 Subject: [PATCH 64/67] Add flag. --- user_program.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/user_program.c b/user_program.c index 9fbfdf1..7d9bad7 100644 --- a/user_program.c +++ b/user_program.c @@ -7,14 +7,35 @@ void print_prompt() { printf("> "); } -void handle_input(char* input) { - if (strcmp(input, "ls") == 0) { - struct file_t files[10]; - uint32_t num_files = count_files(); - list_files(files); - for (uint32_t i = 0; i < num_files; i++) { +void handle_ls(char* input) { + bool flag_long = false; + char* flag = input + 2; + while (*flag == ' ') { + flag++; + } + if (*flag != 0) { + if (strncmp(flag, "-l", 2) == 0) { + flag_long = true; + } else { + printf("Unrecognized flag `%s`\n", flag); + return; + } + } + struct file_t files[10]; + uint32_t num_files = count_files(); + list_files(files); + for (uint32_t i = 0; i < num_files; i++) { + if (flag_long) { + printf("%s (%d bytes)\n", files[i].name, files[i].size); + } else { printf("%s\n", files[i].name); } + } +} + +void handle_input(char* input) { + if (strncmp(input, "ls", 2) == 0) { + handle_ls(input); } else { printf("Unknown command `%s`\n", input); } From efcecd4bbf4bdbd17d628cdb6e98a3c23dc8dcf6 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sat, 17 Dec 2016 22:37:00 -0800 Subject: [PATCH 65/67] Rename user_program to shell. --- Makefile | 8 ++++---- kmain.c | 7 ++++++- script/build_file_system | 2 +- user_program.c => shell.c | 0 4 files changed, 11 insertions(+), 6 deletions(-) rename user_program.c => shell.c (100%) diff --git a/Makefile b/Makefile index 721017e..5699530 100644 --- a/Makefile +++ b/Makefile @@ -58,16 +58,16 @@ kernel.elf: $(OBJECTS) $(STDLIB) start_user_program.o: start_user_program.s $(NASM) $(ASFLAGS) $< -o $@ -user_program.o: user_program.c +shell.o: shell.c $(GCC) $(CFLAGS) $< -o $@ -user_program.bin: user_program.o start_user_program.o $(STDLIB) +shell.bin: shell.o start_user_program.o $(STDLIB) $(LD) -T link_user_program.ld -melf_i386 $^ -o $@ -built_file_system: file_system_root/* user_program.bin +built_file_system: file_system_root/* shell.bin script/build_file_system -os.iso: kernel.elf user_program.bin menu.lst built_file_system +os.iso: kernel.elf shell.bin menu.lst built_file_system mkdir -p iso/boot/grub # create the folder structure mkdir -p iso/modules cp stage2_eltorito iso/boot/grub/ # copy the bootloader diff --git a/kmain.c b/kmain.c index 5d081f4..48c0a38 100644 --- a/kmain.c +++ b/kmain.c @@ -137,7 +137,12 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { initialize_filesystem(first_module(mbinfo)); fprintf(LOG, " - done\n"); - struct file_t* file = get_file("user_program.bin"); + char* file_name = "shell.bin"; + struct file_t* file = get_file(file_name); + if (file == 0) { + fprintf(LOG, "ERROR: could not find file %s\n", file_name); + while(1){} + } fprintf(LOG, "- Creating a user process...\n"); create_process(file); diff --git a/script/build_file_system b/script/build_file_system index 5cda100..96df07c 100755 --- a/script/build_file_system +++ b/script/build_file_system @@ -10,7 +10,7 @@ def include_file(path, output_file) end f = File.open('built_file_system', 'w') -include_file("#{File.dirname(__FILE__)}/../user_program.bin", f) +include_file("#{File.dirname(__FILE__)}/../shell.bin", f) dirname = "#{File.dirname(__FILE__)}/../file_system_root" Dir.foreach(dirname) do |item| diff --git a/user_program.c b/shell.c similarity index 100% rename from user_program.c rename to shell.c From aa50a1a819f400eb0db4363736bca2807c4719a8 Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 18 Dec 2016 12:08:49 -0800 Subject: [PATCH 66/67] Fix bug printing 0. --- kernel_stdio.c | 5 +++++ kmain.c | 2 +- stdlib/stdio.c | 7 ++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel_stdio.c b/kernel_stdio.c index a475e85..55151ce 100644 --- a/kernel_stdio.c +++ b/kernel_stdio.c @@ -77,6 +77,11 @@ void kernel_write_string(write_byte_t write_byte, char* s) { } void kernel_write_uint(write_byte_t write_byte, uint32_t value) { + if (value == 0) { + write_byte('0'); + return; + } + char output[10]; for (int place = 0; place < 10; place++) { output[place] = value % 10; diff --git a/kmain.c b/kmain.c index 48c0a38..3f30f68 100644 --- a/kmain.c +++ b/kmain.c @@ -130,7 +130,7 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) { fprintf( LOG, " - %%s -> %s, %%c -> %c, %%x -> %x, %%X -> %X, %%u -> %u, %%i -> %i, %%o -> %o\n", - "test", 'A', 0xDEADBEEF, 0xDEADBEEF, 12345, -12345, 12345 + "test", 'A', 0xDEADBEEF, 0xDEADBEEF, 0, -12345, 12345 ); fprintf(LOG, "- Loading file system from GRUB module...\n"); diff --git a/stdlib/stdio.c b/stdlib/stdio.c index 07d0148..4121db8 100644 --- a/stdlib/stdio.c +++ b/stdlib/stdio.c @@ -1,7 +1,7 @@ #include "stdio.h" -#include "assembly_functions.h" #include "stdarg.h" +#include "syscalls.h" #define BUFFER_SIZE 128 @@ -96,6 +96,11 @@ void write_string(char* s, struct buffer_t* buffer) { } void write_uint(uint32_t value, struct buffer_t* buffer) { + if (value == 0) { + write_byte('0', buffer); + return; + } + char output[10]; for (int place = 0; place < 10; place++) { output[place] = value % 10; From 8681607dc6e816e90eb5fe103540ad42bd1c161e Mon Sep 17 00:00:00 2001 From: Connor Stack Date: Sun, 18 Dec 2016 12:24:41 -0800 Subject: [PATCH 67/67] Use enum for syscalls. --- kernel_syscalls.c | 30 +++++++++++++++++++++--------- stdlib/syscalls.h | 8 ++++++++ stdlib/syscalls.s | 8 ++++---- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/kernel_syscalls.c b/kernel_syscalls.c index b27400f..3e9908f 100644 --- a/kernel_syscalls.c +++ b/kernel_syscalls.c @@ -6,7 +6,6 @@ #include "stdlib/syscalls.h" uint32_t sys_write_to_screen(char* s) { - fprintf(LOG, "sys_write_to_screen(%s)\n", s); fprintf(SCREEN, s); return 0; } @@ -38,22 +37,35 @@ uint32_t sys_register_input_handler(InputHandler handler) { return 0; } +char* syscall_name(Syscall syscall) { + switch (syscall) { + case (WRITE_TO_SCREEN): + return "WRITE_TO_SCREEN"; + case (COUNT_FILES): + return "COUNT_FILES"; + case (LIST_FILES): + return "LIST_FILES"; + case (REGISTER_INPUT_HANDLER): + return "REGISTER_INPUT_HANDLER"; + } +} + uint32_t handle_syscall(struct cpu_state* cpu) { - uint32_t syscall_num = cpu->eax; + Syscall syscall = (Syscall) cpu->eax; - fprintf(LOG, "--------------------\nSYSCALL (%i)\n", syscall_num); + fprintf(LOG, "--------------------\nSYSCALL (%i - %s)\n", syscall, syscall_name(syscall)); - switch (syscall_num) { - case (1): + switch (syscall) { + case (WRITE_TO_SCREEN): return sys_write_to_screen((char*) cpu->ebx); - case (2): + case (COUNT_FILES): return sys_count_files(); - case (3): + case (LIST_FILES): return sys_list_files((struct file_t *) cpu->ebx); - case (4): + case (REGISTER_INPUT_HANDLER): return sys_register_input_handler((InputHandler) cpu->ebx); default: - fprintf(LOG, "Unknown syscall: %x\n", syscall_num); + fprintf(LOG, "Unknown syscall: %x\n", syscall); while(1){} } diff --git a/stdlib/syscalls.h b/stdlib/syscalls.h index 180d768..99dfab0 100644 --- a/stdlib/syscalls.h +++ b/stdlib/syscalls.h @@ -4,6 +4,14 @@ #include "types.h" #include "filesystem.h" +enum _Syscall { + WRITE_TO_SCREEN, + COUNT_FILES, + LIST_FILES, + REGISTER_INPUT_HANDLER +}; +typedef enum _Syscall Syscall; + void write_to_screen(char* s); uint32_t count_files(); void list_files(struct file_t buffer[]); diff --git a/stdlib/syscalls.s b/stdlib/syscalls.s index af340ef..5db2e44 100644 --- a/stdlib/syscalls.s +++ b/stdlib/syscalls.s @@ -4,7 +4,7 @@ global write_to_screen ; stack: [esp + 4] string ; [esp ] return address write_to_screen: - mov eax, 1 + mov eax, 0 mov ebx, [esp+4] int 0x80 ret ; return to the calling function @@ -13,7 +13,7 @@ global count_files ; count_files ; stack: [esp ] return address count_files: - mov eax, 2 + mov eax, 1 int 0x80 ret ; return to the calling function @@ -22,7 +22,7 @@ global list_files ; stack: [esp + 4] address of buffer ; [esp ] return address list_files: - mov eax, 3 + mov eax, 2 mov ebx, [esp+4] int 0x80 ret ; return to the calling function @@ -32,7 +32,7 @@ global register_input_handler ; stack: [esp + 4] address of handler ; [esp ] return address register_input_handler: - mov eax, 4 + mov eax, 3 mov ebx, [esp+4] int 0x80 ret ; return to the calling function