diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2017-05-31 18:31:38 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2017-05-31 18:31:38 +0200 |
commit | d081f5449b3e84d571ad3f8907bd7ab57d3d63a4 (patch) | |
tree | c66a08aa9a53a928a7c221df8a25b34c9be6a8c8 | |
parent | 3d2b8fb9dbc73e303b54f1517ee5f4feca364265 (diff) | |
download | abaos-d081f5449b3e84d571ad3f8907bd7ab57d3d63a4.tar.gz abaos-d081f5449b3e84d571ad3f8907bd7ab57d3d63a4.tar.bz2 |
added a setjmp implementation
kernel_panic uses a longjmp to terminate the kernel entry function
some segfault in scroll_screen
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | doc/LINKS.TODO | 5 | ||||
-rw-r--r-- | src/Makefile | 8 | ||||
-rw-r--r-- | src/README | 9 | ||||
-rw-r--r-- | src/interrupts.c | 4 | ||||
-rw-r--r-- | src/interrupts.h | 4 | ||||
-rw-r--r-- | src/kernel.c | 33 | ||||
-rw-r--r-- | src/setjmp.asm | 44 | ||||
-rw-r--r-- | src/setjmp.h | 24 | ||||
-rw-r--r-- | src/vga.c | 11 |
10 files changed, 125 insertions, 18 deletions
@@ -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 @@ -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 + @@ -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; } |