Loading Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ boot.img: a.out $(MKRESCUE) -o $@ _boot rm -rf _boot a.out: mem/paging.o dev/io.o kernel.o boot.o a.out: mem/paging.o dev/io.o kernel.o boot.o util.o $(LD) -o $@ -T linkscript $(CFLAGS) $(LDFLAGS) $^ %.o: %.cpp Loading boot.S +86 −14 Original line number Diff line number Diff line #define ASM_FILE 1 // Stack size shall be at most 4M #define STACK_SIZE 0x4000 #define HIGHER_HALF 0xC0000000 #define VIRT_STACK 0xFFC00000 #include "multiboot2.h" .text .globl start, _start start: _start: jmp multiboot_entry .section .multiboot .align 8 /* required multiboot header alignment */ multiboot_header: .long MULTIBOOT2_HEADER_MAGIC Loading @@ -17,23 +14,78 @@ multiboot_header: .long -( MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 \ + ( multiboot_header_end - multiboot_header ) ) .align 8 /* each tag must be aligned separately */ .short MULTIBOOT_HEADER_TAG_ADDRESS .short 0 /* flags */ .long 24 /* tag size */ .long (multiboot_header - HIGHER_HALF) /* header address */ .long (_kernel_start - HIGHER_HALF) /* load address */ .long (_kernel_end - HIGHER_HALF) /* load end address */ .long (_bss_end - HIGHER_HALF) /* bss end address */ .align 8 /* each tag must be aligned separately */ .short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS .short 0 /* flags */ .long 12 /* tag size */ .long (start - HIGHER_HALF) /* entry address */ .align 8 /* each tag must be aligned separately */ .short MULTIBOOT_HEADER_TAG_END /* tag id */ .short 0 /* flags */ .long 8 /* tag size */ multiboot_header_end: .text .globl start, _start .type _start, @function #define VIDEO 0xC00B8000 _start: start: multiboot_entry: movl $(stack + STACK_SIZE), %esp /* stack pointer */ movl %eax, %esi movl %ebx, %edi movl $(page_directory - HIGHER_HALF), %eax movl %eax, %cr3 # Set phys. addr. of page directory mov %cr4, %eax or $0x00000010, %eax # Enable PSE mov %eax, %cr4 mov %cr0, %eax or $0x80000001, %eax # Enable paging mov %eax, %cr0 mov $higher, %eax jmp *%eax higher: /* map the stack base to 4G minus 4M */ movl $((STACK_SIZE >> 12) - 1), %ecx loop1: movl %ecx, %ebx shl $12, %ebx add $(stack - HIGHER_HALF), %ebx or $0x3, %ebx mov %ecx, %eax shl $2, %eax add $(stack_pgtbl + 0x1000 - (STACK_SIZE >> 10) ), %eax movl %ebx, (%eax) dec %ecx jns loop1 movl $VIRT_STACK, %esp # Map stack to a new virt. addr. pushl $0 popf /* reset EFLAGS */ popf pushl %edi /* multiboot information structure */ pushl %esi /* multiboot magic value */ call main pushl %ebx /* multiboot information structure */ pushl %eax /* multiboot magic value */ call main /* let's C */ jmp pre_halt #define VIDEO 0xB8000 pre_halt: mov $2, %ecx loop_flags_row: Loading Loading @@ -61,6 +113,26 @@ empty: hlt #undef VIDEO #define HH_PGDIR_IDX (HIGHER_HALF >> 22) .section .paging .global page_directory .align 0x1000 page_directory: .long 0x00000083 # Id-map low 4M .fill (HH_PGDIR_IDX - 1), 4, 0x0 # Nothing .long 0x00000083 # Map low 4M to HIGHER_HALF .fill (1021 - HH_PGDIR_IDX), 4, 0x0 # Nothing .long (stack_pgtbl - HIGHER_HALF + 0x3) # Page table for the stack .long 0x00000000 .align 0x1000 stack_pgtbl: .fill 1020, 4, 0x0 # Nothing .long (stack - HIGHER_HALF + 0x3) # Four static stack pages .long (stack - HIGHER_HALF + 0x1003) .long (stack - HIGHER_HALF + 0x2003) .long (stack - HIGHER_HALF + 0x3003) halt_message: .asciz " Nyni muzete pocitac bezpecne vypnout " .comm stack, STACK_SIZE /* the stack */ dev/vga.hpp +7 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,8 @@ namespace masys { namespace dev { class Vga : public CharacterOutput { u8 * const video = ( u8 * ) 0xB8000; u8 * const video; const int columns = 80; const int lines = 24; Loading @@ -15,6 +16,11 @@ class Vga : public CharacterOutput { y = 0, flags = 0x07; public: static const u32 MEMORY_MAPPED = 0xB8000; Vga( u8 * fb_addr ) : video( fb_addr ) {} Status putch( u8 c ) { if ( c == '\b' && x > 0 ) { --x; Loading kernel.cpp +34 −30 Original line number Diff line number Diff line #include <dev/vga.hpp> #include <dev/serial.hpp> #include <mem/paging.hpp> #include <util.hpp> #include <multiboot2.h> namespace masys { const size_t PAGE_SIZE = 4096; alignas( PAGE_SIZE ) mem::PageEntry page_directory[ PAGE_SIZE ]; void kernel( unsigned long magic, unsigned long addr ) { dev::Vga vga; vga.clear(); extern "C" { vga.puts( "Enabling paging...\n" ); extern masys::mem::PageEntry page_directory[]; for ( auto & pgdir_entry : page_directory ) { pgdir_entry._raw = 0; } auto & mypage = page_directory[ 1 << 8 ]; mypage.present = 1; mem::enable_paging( page_directory ); namespace masys { const size_t PAGE_SIZE = 0x1000; const size_t PAGEDIR_ENTRIES = 1024; const u32 HIGHER_HALF = 0xC0000000; if ( magic != MULTIBOOT2_BOOTLOADER_MAGIC ) void kernel( unsigned long magic, unsigned long addr ) { vga.puts( "invalid magic number :-(" ); return; } dev::SerialLine ser( dev::SERIAL_PORT_1 ); if ( addr & 7 ) { vga.puts( "unaligned mbi :-(" ); return; } char buf[32]; ser.puts( "Page Directory address: 0x" ); itoa( (u32) page_directory, buf, 16 ); ser.puts( buf ); ser.putch( '\n' ); ser.puts( "Stack pointer: 0x" ); itoa( (u32) buf, buf, 16 ); ser.puts( buf ); ser.putch( '\n' ); ser.puts( "Multiboot info address: 0x" ); itoa( addr, buf, 16 ); ser.puts( buf ); ser.putch( '\n' ); dev::Vga vga( (u8*) dev::Vga::MEMORY_MAPPED + HIGHER_HALF ); vga.clear(); vga.puts( "\nSwitched.\n" ); // TODO: Don't assume that multiboot info is in lower 4M vga.puts( "Co nam Multiboot povedel:\n================================\n" ); auto tag = reinterpret_cast< multiboot_tag * >( addr + 8 ); Loading @@ -58,11 +60,12 @@ void kernel( unsigned long magic, unsigned long addr ) + tag->size + 7 ) & 0xfffffff8UL ); } vga.puts( "Nyni ocekavam vstup na seriove lince (coz je stdin, ehm).\n" ); vga.puts( "^D ukonci cinnost tohoto bohorovneho jadra.\n\n" ); /* Cancel id-mapping */ page_directory[ 0 ].present = 0; vga.puts( "Nyni ocekavam vstup na seriove lince.\n" ); vga.puts( "^D ukonci cinnost tohoto bohorovneho jadra.\n\n" ); dev::SerialLine ser( dev::SERIAL_PORT_1 ); ser.puts( "Ahoj svete za seriovou linkou! Povez mi neco:\n" ); const char CTRL_D = 4; Loading @@ -74,6 +77,7 @@ void kernel( unsigned long magic, unsigned long addr ) ser.putch( a ); } while ( a != CTRL_D ); ser.puts( "\nKernel konec.\n" ); vga.puts( "\nKernel konec.\n" ); } Loading linkscript +11 −7 Original line number Diff line number Diff line Loading @@ -6,37 +6,41 @@ ENTRY(_start) kernel image. */ SECTIONS { /* Begin putting sections at 1 MiB, a conventional place for kernels to be loaded at by the bootloader. */ . = 1M; /* This is a higher half kernel, virtually at 1G+1M, physically at 1M */ . = 0xC0100000; _kernel_start = .; /* First put the multiboot header, as it is required to be put very early early in the image or the bootloader won't recognize the file format. Next we'll put the .text section. */ .text BLOCK(4K) : ALIGN(4K) .text BLOCK(4K) : AT(ADDR(.text) - 0xC000000) { *(.multiboot) *(.text) } /* Read-only data. */ .rodata BLOCK(4K) : ALIGN(4K) .rodata BLOCK(4K) : AT(ADDR(.rodata) - 0xC000000) { *(.rodata) } /* Read-write data (initialized) */ .data BLOCK(4K) : ALIGN(4K) .data BLOCK(4K) : AT(ADDR(.data) - 0xC000000) { *(.paging) *(.data) } _kernel_end = .; /* Read-write data (uninitialized) and stack */ .bss BLOCK(4K) : ALIGN(4K) .bss BLOCK(4K) : AT(ADDR(.bss) - 0xC000000) { *(COMMON) *(.bss) } _bss_end = .; /* The compiler may produce other sections, by default it will put them in a segment with the same name. Simply add stuff here as needed. */ Loading Loading
Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ boot.img: a.out $(MKRESCUE) -o $@ _boot rm -rf _boot a.out: mem/paging.o dev/io.o kernel.o boot.o a.out: mem/paging.o dev/io.o kernel.o boot.o util.o $(LD) -o $@ -T linkscript $(CFLAGS) $(LDFLAGS) $^ %.o: %.cpp Loading
boot.S +86 −14 Original line number Diff line number Diff line #define ASM_FILE 1 // Stack size shall be at most 4M #define STACK_SIZE 0x4000 #define HIGHER_HALF 0xC0000000 #define VIRT_STACK 0xFFC00000 #include "multiboot2.h" .text .globl start, _start start: _start: jmp multiboot_entry .section .multiboot .align 8 /* required multiboot header alignment */ multiboot_header: .long MULTIBOOT2_HEADER_MAGIC Loading @@ -17,23 +14,78 @@ multiboot_header: .long -( MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 \ + ( multiboot_header_end - multiboot_header ) ) .align 8 /* each tag must be aligned separately */ .short MULTIBOOT_HEADER_TAG_ADDRESS .short 0 /* flags */ .long 24 /* tag size */ .long (multiboot_header - HIGHER_HALF) /* header address */ .long (_kernel_start - HIGHER_HALF) /* load address */ .long (_kernel_end - HIGHER_HALF) /* load end address */ .long (_bss_end - HIGHER_HALF) /* bss end address */ .align 8 /* each tag must be aligned separately */ .short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS .short 0 /* flags */ .long 12 /* tag size */ .long (start - HIGHER_HALF) /* entry address */ .align 8 /* each tag must be aligned separately */ .short MULTIBOOT_HEADER_TAG_END /* tag id */ .short 0 /* flags */ .long 8 /* tag size */ multiboot_header_end: .text .globl start, _start .type _start, @function #define VIDEO 0xC00B8000 _start: start: multiboot_entry: movl $(stack + STACK_SIZE), %esp /* stack pointer */ movl %eax, %esi movl %ebx, %edi movl $(page_directory - HIGHER_HALF), %eax movl %eax, %cr3 # Set phys. addr. of page directory mov %cr4, %eax or $0x00000010, %eax # Enable PSE mov %eax, %cr4 mov %cr0, %eax or $0x80000001, %eax # Enable paging mov %eax, %cr0 mov $higher, %eax jmp *%eax higher: /* map the stack base to 4G minus 4M */ movl $((STACK_SIZE >> 12) - 1), %ecx loop1: movl %ecx, %ebx shl $12, %ebx add $(stack - HIGHER_HALF), %ebx or $0x3, %ebx mov %ecx, %eax shl $2, %eax add $(stack_pgtbl + 0x1000 - (STACK_SIZE >> 10) ), %eax movl %ebx, (%eax) dec %ecx jns loop1 movl $VIRT_STACK, %esp # Map stack to a new virt. addr. pushl $0 popf /* reset EFLAGS */ popf pushl %edi /* multiboot information structure */ pushl %esi /* multiboot magic value */ call main pushl %ebx /* multiboot information structure */ pushl %eax /* multiboot magic value */ call main /* let's C */ jmp pre_halt #define VIDEO 0xB8000 pre_halt: mov $2, %ecx loop_flags_row: Loading Loading @@ -61,6 +113,26 @@ empty: hlt #undef VIDEO #define HH_PGDIR_IDX (HIGHER_HALF >> 22) .section .paging .global page_directory .align 0x1000 page_directory: .long 0x00000083 # Id-map low 4M .fill (HH_PGDIR_IDX - 1), 4, 0x0 # Nothing .long 0x00000083 # Map low 4M to HIGHER_HALF .fill (1021 - HH_PGDIR_IDX), 4, 0x0 # Nothing .long (stack_pgtbl - HIGHER_HALF + 0x3) # Page table for the stack .long 0x00000000 .align 0x1000 stack_pgtbl: .fill 1020, 4, 0x0 # Nothing .long (stack - HIGHER_HALF + 0x3) # Four static stack pages .long (stack - HIGHER_HALF + 0x1003) .long (stack - HIGHER_HALF + 0x2003) .long (stack - HIGHER_HALF + 0x3003) halt_message: .asciz " Nyni muzete pocitac bezpecne vypnout " .comm stack, STACK_SIZE /* the stack */
dev/vga.hpp +7 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,8 @@ namespace masys { namespace dev { class Vga : public CharacterOutput { u8 * const video = ( u8 * ) 0xB8000; u8 * const video; const int columns = 80; const int lines = 24; Loading @@ -15,6 +16,11 @@ class Vga : public CharacterOutput { y = 0, flags = 0x07; public: static const u32 MEMORY_MAPPED = 0xB8000; Vga( u8 * fb_addr ) : video( fb_addr ) {} Status putch( u8 c ) { if ( c == '\b' && x > 0 ) { --x; Loading
kernel.cpp +34 −30 Original line number Diff line number Diff line #include <dev/vga.hpp> #include <dev/serial.hpp> #include <mem/paging.hpp> #include <util.hpp> #include <multiboot2.h> namespace masys { const size_t PAGE_SIZE = 4096; alignas( PAGE_SIZE ) mem::PageEntry page_directory[ PAGE_SIZE ]; void kernel( unsigned long magic, unsigned long addr ) { dev::Vga vga; vga.clear(); extern "C" { vga.puts( "Enabling paging...\n" ); extern masys::mem::PageEntry page_directory[]; for ( auto & pgdir_entry : page_directory ) { pgdir_entry._raw = 0; } auto & mypage = page_directory[ 1 << 8 ]; mypage.present = 1; mem::enable_paging( page_directory ); namespace masys { const size_t PAGE_SIZE = 0x1000; const size_t PAGEDIR_ENTRIES = 1024; const u32 HIGHER_HALF = 0xC0000000; if ( magic != MULTIBOOT2_BOOTLOADER_MAGIC ) void kernel( unsigned long magic, unsigned long addr ) { vga.puts( "invalid magic number :-(" ); return; } dev::SerialLine ser( dev::SERIAL_PORT_1 ); if ( addr & 7 ) { vga.puts( "unaligned mbi :-(" ); return; } char buf[32]; ser.puts( "Page Directory address: 0x" ); itoa( (u32) page_directory, buf, 16 ); ser.puts( buf ); ser.putch( '\n' ); ser.puts( "Stack pointer: 0x" ); itoa( (u32) buf, buf, 16 ); ser.puts( buf ); ser.putch( '\n' ); ser.puts( "Multiboot info address: 0x" ); itoa( addr, buf, 16 ); ser.puts( buf ); ser.putch( '\n' ); dev::Vga vga( (u8*) dev::Vga::MEMORY_MAPPED + HIGHER_HALF ); vga.clear(); vga.puts( "\nSwitched.\n" ); // TODO: Don't assume that multiboot info is in lower 4M vga.puts( "Co nam Multiboot povedel:\n================================\n" ); auto tag = reinterpret_cast< multiboot_tag * >( addr + 8 ); Loading @@ -58,11 +60,12 @@ void kernel( unsigned long magic, unsigned long addr ) + tag->size + 7 ) & 0xfffffff8UL ); } vga.puts( "Nyni ocekavam vstup na seriove lince (coz je stdin, ehm).\n" ); vga.puts( "^D ukonci cinnost tohoto bohorovneho jadra.\n\n" ); /* Cancel id-mapping */ page_directory[ 0 ].present = 0; vga.puts( "Nyni ocekavam vstup na seriove lince.\n" ); vga.puts( "^D ukonci cinnost tohoto bohorovneho jadra.\n\n" ); dev::SerialLine ser( dev::SERIAL_PORT_1 ); ser.puts( "Ahoj svete za seriovou linkou! Povez mi neco:\n" ); const char CTRL_D = 4; Loading @@ -74,6 +77,7 @@ void kernel( unsigned long magic, unsigned long addr ) ser.putch( a ); } while ( a != CTRL_D ); ser.puts( "\nKernel konec.\n" ); vga.puts( "\nKernel konec.\n" ); } Loading
linkscript +11 −7 Original line number Diff line number Diff line Loading @@ -6,37 +6,41 @@ ENTRY(_start) kernel image. */ SECTIONS { /* Begin putting sections at 1 MiB, a conventional place for kernels to be loaded at by the bootloader. */ . = 1M; /* This is a higher half kernel, virtually at 1G+1M, physically at 1M */ . = 0xC0100000; _kernel_start = .; /* First put the multiboot header, as it is required to be put very early early in the image or the bootloader won't recognize the file format. Next we'll put the .text section. */ .text BLOCK(4K) : ALIGN(4K) .text BLOCK(4K) : AT(ADDR(.text) - 0xC000000) { *(.multiboot) *(.text) } /* Read-only data. */ .rodata BLOCK(4K) : ALIGN(4K) .rodata BLOCK(4K) : AT(ADDR(.rodata) - 0xC000000) { *(.rodata) } /* Read-write data (initialized) */ .data BLOCK(4K) : ALIGN(4K) .data BLOCK(4K) : AT(ADDR(.data) - 0xC000000) { *(.paging) *(.data) } _kernel_end = .; /* Read-write data (uninitialized) and stack */ .bss BLOCK(4K) : ALIGN(4K) .bss BLOCK(4K) : AT(ADDR(.bss) - 0xC000000) { *(COMMON) *(.bss) } _bss_end = .; /* The compiler may produce other sections, by default it will put them in a segment with the same name. Simply add stuff here as needed. */ Loading