summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README1
-rw-r--r--doc/LINKS.TODO5
-rw-r--r--src/Makefile8
-rw-r--r--src/README9
-rw-r--r--src/interrupts.c4
-rw-r--r--src/interrupts.h4
-rw-r--r--src/kernel.c33
-rw-r--r--src/setjmp.asm44
-rw-r--r--src/setjmp.h24
-rw-r--r--src/vga.c11
10 files changed, 125 insertions, 18 deletions
diff --git a/README b/README
index 96e888b..1e20d0b 100644
--- a/README
+++ b/README
@@ -83,3 +83,4 @@ http://download.tyndur.org/releases/0.2/
https://code.google.com/archive/p/fpos/source/default/source, FreePascal
https://mirage.io/
http://www.jamesmolloy.co.uk/tutorial_html/
+http://prettyos.de
diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO
index 33fc5bb..15ea245 100644
--- a/doc/LINKS.TODO
+++ b/doc/LINKS.TODO
@@ -32,3 +32,8 @@ https://blog.packagecloud.io/eng/2016/04/05/the-definitive-guide-to-linux-system
A20:
http://www.independent-software.com/writing-your-own-toy-operating-system-enabling-the-a20-line/
+
+longjmp:
+http://blog.reverberate.org/2013/05/deep-wizardry-stack-unwinding.html
+http://prettyos.de
+
diff --git a/src/Makefile b/src/Makefile
index 01a61de..3e89a74 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -28,10 +28,11 @@ kernel.bin: kernel.elf
kernel.sym: kernel.elf
$(OBJCOPY) --only-keep-debug kernel.elf kernel.sym
-kernel.elf: kernel.o console.o vga.o serial.o port.o port_asm.o interrupts.o interrupts_asm.o string.o stdlib.o stdio.o
+kernel.elf: kernel.o console.o vga.o serial.o port.o port_asm.o interrupts.o interrupts_asm.o string.o stdlib.o stdio.o setjmp.o
$(LD) -o kernel.elf -N -n -Ttext 0x8400 --oformat elf32-i386 \
kernel.o console.o vga.o serial.o port.o port_asm.o \
- interrupts.o interrupts_asm.o string.o stdlib.o stdio.o
+ interrupts.o interrupts_asm.o string.o stdlib.o stdio.o \
+ setjmp.o
magic.bin: magic.asm
$(NASM) magic.asm -DMAGIC='"$(MAGIC)"' -f bin -o magic.bin
@@ -69,6 +70,9 @@ stdlib.o: stdlib.c stdlib.h
stdio.o: stdio.c stdio.h
$(CC) $(CFLAGS) -c -o stdio.o stdio.c
+setjmp.o: setjmp.asm
+ $(NASM) setjmp.asm $(NASMFLAGS) -o setjmp.o
+
clean:
-rm -f boot.bin kernel.bin kernel.sym kernel.elf image.bin magic.bin *.o boot.map image.tmp
diff --git a/src/README b/src/README
index 4b120dc..620fab3 100644
--- a/src/README
+++ b/src/README
@@ -16,6 +16,11 @@ kernel utility routines
* port.c, port.asm - I/O ports
* interrupts.c, interrups.asm - interrupt handlers
+C library definitions
+* stddef.h - definition of NULL, size_t
+* limits.h - domain range constants like INT_MAX
+
C library routines
-* string.c
-* stdlib.c
+* string.c - string, memory functions
+* stdlib.c - UNIX standard library functions
+* stdio.c - I/O functions, printing
diff --git a/src/interrupts.c b/src/interrupts.c
index 77ba0d0..810f105 100644
--- a/src/interrupts.c
+++ b/src/interrupts.c
@@ -34,6 +34,10 @@ void interrupts_init( interrupt_t *interrupt )
interrupt->idt_pointer.base = (uint32_t)interrupt->descriptor_table;
interrupts_load_idt( &interrupt->idt_pointer );
+
+ port8_init( &interrupt->PIC_master_control, 0x20 );
+ port8_init( &interrupt->PIC_master_data, 0x21 );
+
}
void interrupts_register_interrupt( interrupt_t *interrupts,
diff --git a/src/interrupts.h b/src/interrupts.h
index d8a6d4b..593a993 100644
--- a/src/interrupts.h
+++ b/src/interrupts.h
@@ -3,6 +3,8 @@
#include <stdint.h>
+#include "port.h"
+
// TCC 0.9.26 bug?, __attribute__( ( packed ) ) on structs not working,
// also not working on members.. resorting to pragmas
#if defined( __TINYC__ )
@@ -42,6 +44,8 @@ typedef struct {
typedef struct {
interrupt_descriptor_table_pointer_t idt_pointer;
interrupt_gate_descriptor_t descriptor_table[NOF_INTERRUPT_GATES];
+ port8_t PIC_master_control;
+ port8_t PIC_master_data;
} interrupt_t;
void interrupts_enable( void );
diff --git a/src/kernel.c b/src/kernel.c
index 72b1222..82fcebe 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -7,18 +7,26 @@
#include "stdlib.h"
#include "stdio.h"
#include "interrupts.h"
+#include "setjmp.h"
+
+static jmp_buf panic_jmp_buf;
+
+static vga_t vga;
+static console_t console;
+// static serial_t serial;
void entry( void )
{
+
// serial_t serial;
// serial_init( &serial );
- vga_t vga;
+// vga_t vga;
vga_init( &vga );
vga_set_color( &vga, VGA_COLOR_LIGHT_GREY );
vga_set_background_color( &vga, VGA_COLOR_BLACK );
-
- console_t console;
+
+// console_t console;
console_init( &console );
console_add_vga_output( &console, &vga );
// console_add_serial_output( &console, &serial );
@@ -33,9 +41,17 @@ void entry( void )
interrupts_init( &interrupt );
interrupts_enable( );
- console_put_string( &console, "Running.." );
-
//~ vga_put_char_at( &vga, 81, 20, 'X' );
+
+ // exit point in case of kernel panic, do this as soon as
+ // possible
+ int v = setjmp( panic_jmp_buf );
+ printf( "setjmp returned %d\n", v );
+ if( v > 0 ) {
+ goto TERMINATE;
+ }
+
+ console_put_string( &console, "Running.." );
const char bar[] = "\\|/-";
int y_pos = vga_get_cursor_y( &vga );
@@ -60,6 +76,7 @@ printf( "Hex number is 0x%X and string is '%s'\n", x, "abaos" );
console_put_newline( &console );
+TERMINATE:
puts( "Terminating" );
}
@@ -71,9 +88,7 @@ void kernel_panic( const char *format, ... )
va_start( args, format );
(void)vprintf( format, args );
va_end( args );
-
- // TODO: find a clever way to jump back out of C code to the
- // termination point in stage 2
- for( ;; );
+
+ longjmp( panic_jmp_buf, 47 );
}
diff --git a/src/setjmp.asm b/src/setjmp.asm
new file mode 100644
index 0000000..a20a0af
--- /dev/null
+++ b/src/setjmp.asm
@@ -0,0 +1,44 @@
+[bits 32]
+
+global setjmp
+global longjmp
+
+;typedef struct {
+; uint32_t ebx;
+; uint32_t esp;
+; uint32_t ebp;
+; uint32_t esi;
+; uint32_t edi;
+; uint32_t eip;
+;} jmp_buf[1];
+
+; int setjmp(jmp_buf env)
+setjmp:
+ mov eax, [esp+4] ; the adress of the jump buffer
+ mov [eax], ebx ; safe registers
+ mov [eax+4], esp
+ mov [eax+8], ebp
+ mov [eax+12], esi
+ mov [eax+16], edi
+ mov edx, [esp] ; get return address from the stack (pushed here by call)
+ mov [eax+20], edx
+ mov eax, 0 ; indicate that we come from setjmp, not from a longjmp
+ ret
+
+; void longjmp(jmp_buf env, int value);
+longjmp:
+ mov eax, [esp+4] ; the address of the jump buffer
+ mov ecx, [esp+8] ; the return value for setjmp
+ mov ebx, [eax] ; restore registers
+ mov esp, [eax+4]
+ mov ebp, [eax+8]
+ mov esi, [eax+12]
+ mov edi, [eax+16]
+ mov edx, [eax+20] ; get jump address and store it on the stack for 'ret'
+ mov [esp], edx
+ mov eax, ecx ; get return value
+ cmp eax, 0
+ jnz .return ; non zero, ok, return it
+ mov eax, 1 ; setjmp called with 0, not good, return 1
+.return:
+ ret
diff --git a/src/setjmp.h b/src/setjmp.h
new file mode 100644
index 0000000..5f987f1
--- /dev/null
+++ b/src/setjmp.h
@@ -0,0 +1,24 @@
+#ifndef SETJMP_H
+#define SETJMP_H
+
+#include <stdint.h>
+
+// C99 states this should be an array so we can address it without
+// the & operator, see prototypes of setjmp and longjmp
+// eax, ecx and edx are scratch registers, save the others
+// also store the jump address (eip)
+typedef struct {
+ uint32_t ebx;
+ uint32_t esp;
+ uint32_t ebp;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t eip;
+} jmp_buf[1];
+
+int setjmp( jmp_buf env );
+
+void longjmp( jmp_buf env, int val );
+
+#endif // SETJMP_H
+
diff --git a/src/vga.c b/src/vga.c
index 1881257..5f612d8 100644
--- a/src/vga.c
+++ b/src/vga.c
@@ -122,13 +122,14 @@ static int calculate_offset( vga_t *vga )
static void scroll_screen( vga_t *vga )
{
volatile uint8_t *VIDEO_MEMORY = (uint8_t *)0xb8000;
-
+
memmove( (void *)VIDEO_MEMORY, (const void *)VIDEO_MEMORY + 2 * vga->res_x, 2 * ( vga->res_y - 1 ) * vga->res_x );
- for( int i = 2 * ( vga->res_x * ( vga->res_y - 1 ) ); i < 2 * ( vga->res_x * vga->res_y ); i += 2 ) {
- *(VIDEO_MEMORY+i) = ' ';
- *(VIDEO_MEMORY+i+1) = calculate_color_cell( vga );
- }
+// TODO: something crashes qemu here
+ //~ for( int i = 2 * ( vga->res_x * ( vga->res_y - 1 ) ); i < 2 * ( vga->res_x * vga->res_y ); i += 2 ) {
+ //~ *(VIDEO_MEMORY+i) = ' ';
+ //~ *(VIDEO_MEMORY+i+1) = calculate_color_cell( vga );
+ //~ }
vga->cursor_y = vga->res_y - 1;
}