diff --git a/Makefile b/Makefile index 1c4316b..c34960f 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ LDFLAGS = -ffreestanding -nostdlib LDLIBS = -lgcc LDFILE = -T linker.ld -c_objects = kernel.o +c_objects = kernel.o term.o asm_objects = boot.o ISODIR = isodir diff --git a/gdt.c b/gdt.c new file mode 100644 index 0000000..fa45af0 --- /dev/null +++ b/gdt.c @@ -0,0 +1,23 @@ +#include "gdt.c" + +void encodeGdtEntry(uint8_t *target, struct GDT source) { + // Check the limit to make sure that it can be encoded + if (source.limit > 0xFFFFF) {kerror("GDT cannot encode limits larger than 0xFFFFF");} + + // Encode the limit + target[0] = source.limit & 0xFF; + target[1] = (source.limit >> 8) & 0xFF; + target[6] = (source.limit >> 16) & 0x0F; + + // Encode the base + target[2] = source.base & 0xFF; + target[3] = (source.base >> 8) & 0xFF; + target[4] = (source.base >> 16) & 0xFF; + target[7] = (source.base >> 24) & 0xFF; + + // Encode the access byte + target[5] = source.access_byte; + + // Encode the flags + target[6] |= (source.flags << 4); +} diff --git a/gdt.h b/gdt.h new file mode 100644 index 0000000..9f47d70 --- /dev/null +++ b/gdt.h @@ -0,0 +1,6 @@ +#ifndef GDT_K_H +#define GDT_K_H + +void encodeGdtEntry(uint8_t *target, struct GDT source); + +#endif diff --git a/kernel.c b/kernel.c index c99d848..d829e20 100644 --- a/kernel.c +++ b/kernel.c @@ -2,6 +2,7 @@ #include #include #include "multiboot.h" +#include "term.h" /* Check if the compiler thinks you are targeting the wrong operating system. */ #if defined(__linux__) #error "You are not using a cross-compiler, you will most certainly run into trouble" @@ -11,108 +12,9 @@ #if !defined(__i386__) #error "This tutorial needs to be compiled with a ix86-elf compiler" #endif - -/* Hardware text mode color constants. */ -enum vga_color { - VGA_COLOR_BLACK = 0, - VGA_COLOR_BLUE = 1, - VGA_COLOR_GREEN = 2, - VGA_COLOR_CYAN = 3, - VGA_COLOR_RED = 4, - VGA_COLOR_MAGENTA = 5, - VGA_COLOR_BROWN = 6, - VGA_COLOR_LIGHT_GREY = 7, - VGA_COLOR_DARK_GREY = 8, - VGA_COLOR_LIGHT_BLUE = 9, - VGA_COLOR_LIGHT_GREEN = 10, - VGA_COLOR_LIGHT_CYAN = 11, - VGA_COLOR_LIGHT_RED = 12, - VGA_COLOR_LIGHT_MAGENTA = 13, - VGA_COLOR_LIGHT_BROWN = 14, - VGA_COLOR_WHITE = 15, -}; - -static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { - return fg | bg << 4; -} - -static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { - return (uint16_t) uc | (uint16_t) color << 8; -} - -size_t strlen(const char* str) { - size_t len = 0; - while (str[len]) - len++; - return len; -} - -static const size_t VGA_WIDTH = 80; -static const size_t VGA_HEIGHT = 25; - -size_t terminal_row; -size_t terminal_column; -uint8_t terminal_color; -uint16_t* terminal_buffer; - -void terminal_initialize(void) { - terminal_row = 0; - terminal_column = 0; - terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); - terminal_buffer = (uint16_t*) 0xB8000; - for (size_t y = 0; y < VGA_HEIGHT; y++) { - for (size_t x = 0; x < VGA_WIDTH; x++) { - const size_t index = y * VGA_WIDTH + x; - terminal_buffer[index] = vga_entry(' ', terminal_color); - } - } -} -void terminal_shiftup(void) { - for(size_t y = 0; y < VGA_HEIGHT-1; y++) { - for (size_t x = 0; x < VGA_WIDTH; x++) { - size_t index_current = y * VGA_WIDTH + x; - size_t index_next = (y+1) * VGA_WIDTH + x; - terminal_buffer[index_current] = terminal_buffer[index_next]; - } - } -} - -void terminal_setcolor(uint8_t color) { - terminal_color = color; -} - -void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) { - const size_t index = y * VGA_WIDTH + x; - terminal_buffer[index] = vga_entry(c, color); -} - -void terminal_putchar(char c) { - if (c == '\n'){ - terminal_row = terminal_row + 1; - terminal_column = 0; - return; - } - terminal_putentryat(c, terminal_color, terminal_column, terminal_row); - terminal_column = terminal_column + 1; - if (terminal_column >= VGA_WIDTH) { - terminal_column = 0; - terminal_row = terminal_row + 1; - } - if (terminal_row >= VGA_HEIGHT) { - terminal_shiftup(); - //terminal_row = 0; - } -} - -void terminal_write(const char* data, size_t size) { - for (size_t i = 0; i < size; i++) - terminal_putchar(data[i]); -} - -void terminal_writestring(const char* data) { - terminal_write(data, strlen(data)); -} +kVGATerm vgaterm; + void int_to_string(char * str, size_t strlen, size_t conv) { char buffer[100]; @@ -137,12 +39,16 @@ void int_to_string(char * str, size_t strlen, size_t conv) { j = j + 1; } } +} +void os_vga_writestring(char * data) { + terminal_writestring(&vgaterm, data); } void kernel_main(unsigned long addr) { /* Initialize terminal interface */ - terminal_initialize(); + //kVGATerm vgaterm; + terminal_initialize(&vgaterm); //uint32_t * flags = (uint32_t *) addr; /* Newline support is left as an exercise. */ @@ -154,8 +60,8 @@ void kernel_main(unsigned long addr) { x[i] = -1; } int_to_string(x, 50, mbi->mem_lower); - terminal_writestring(x); - terminal_writestring("\n"); + os_vga_writestring(x); + os_vga_writestring("\n"); for (int i = 0; i < 50; i++) { x[i] = -1; @@ -163,12 +69,12 @@ void kernel_main(unsigned long addr) { int_to_string(x, 50, mbi->mem_upper); - terminal_writestring(x); - terminal_writestring("\n"); + os_vga_writestring(x); + os_vga_writestring("\n"); - terminal_writestring("erm what da sigma\n"); - terminal_writestring("Hello, kernel World!\n"); - terminal_writestring("Hello, kernel World!\n"); - terminal_writestring("Hello, kernel World!\n"); + os_vga_writestring("erm what da sigma\n"); + os_vga_writestring("Hello, kernel World!\n"); + os_vga_writestring("Hello, kernel World!\n"); + os_vga_writestring("Hello, kernel World!\n"); } diff --git a/multiboot.h b/multiboot.h index f163418..269cf9b 100644 --- a/multiboot.h +++ b/multiboot.h @@ -1,11 +1,127 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + #ifndef MULTIBOOT_HEADER -#define MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 +#define MULTIBOOT_HEADER_ALIGN 4 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the ’flags’ member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the ’flags’ member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 + +#ifndef ASM_FILE typedef unsigned char multiboot_uint8_t; typedef unsigned short multiboot_uint16_t; typedef unsigned int multiboot_uint32_t; typedef unsigned long long multiboot_uint64_t; +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* The symbol table for a.out. */ struct multiboot_aout_symbol_table { multiboot_uint32_t tabsize; @@ -15,6 +131,7 @@ struct multiboot_aout_symbol_table }; typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; +/* The section header table for ELF. */ struct multiboot_elf_section_header_table { multiboot_uint32_t num; @@ -24,8 +141,6 @@ struct multiboot_elf_section_header_table }; typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; - - struct multiboot_info { /* Multiboot info version number */ @@ -105,4 +220,55 @@ struct multiboot_info }; typedef struct multiboot_info multiboot_info_t; -#endif +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ + /* the memory used goes from bytes ’mod_start’ to ’mod_end-1’ inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +/* APM BIOS info. */ +struct multiboot_apm_info +{ + multiboot_uint16_t version; + multiboot_uint16_t cseg; + multiboot_uint32_t offset; + multiboot_uint16_t cseg_16; + multiboot_uint16_t dseg; + multiboot_uint16_t flags; + multiboot_uint16_t cseg_len; + multiboot_uint16_t cseg_16_len; + multiboot_uint16_t dseg_len; +}; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/term.c b/term.c new file mode 100644 index 0000000..ac85745 --- /dev/null +++ b/term.c @@ -0,0 +1,80 @@ +#include "term.h" + +static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { + return fg | bg << 4; +} + + +static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { + return (uint16_t) uc | (uint16_t) color << 8; +} + + +void terminal_initialize(kVGATerm *term) { + term->terminal_row = 0; + term->terminal_column = 0; + term->terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); + term->terminal_buffer = (uint16_t*) 0xB8000; + + for (size_t y = 0; y < VGA_HEIGHT; y++) { + for (size_t x = 0; x < VGA_WIDTH; x++) { + const size_t index = y * VGA_WIDTH + x; + term->terminal_buffer[index] = vga_entry(' ', term->terminal_color); + } + } +} + +void terminal_shiftup(kVGATerm *term){ + for(size_t y = 0; y < VGA_HEIGHT-1; y++) { + for (size_t x = 0; x < VGA_WIDTH; x++) { + size_t index_current = y * VGA_WIDTH + x; + size_t index_next = (y+1) * VGA_WIDTH + x; + term->terminal_buffer[index_current] = term->terminal_buffer[index_next]; + } + } +} + +void terminal_setcolor(kVGATerm *term, uint8_t color){ + term->terminal_color = color; +} + +void terminal_putentryat(kVGATerm *term, char c, uint8_t color, size_t x, size_t y){ + size_t index = y * VGA_WIDTH + x; + term->terminal_buffer[index] = vga_entry(c, color); +} + +void terminal_putchar(kVGATerm *term, char c){ + if (c == '\n'){ + term->terminal_row = term->terminal_row + 1; + term->terminal_column = 0; + return; + } + terminal_putentryat(term, c, term->terminal_color, term->terminal_column, term->terminal_row); + term->terminal_column = term->terminal_column + 1; + if (term->terminal_column >= VGA_WIDTH) { + term->terminal_column = 0; + term->terminal_row = term->terminal_row + 1; + } + if (term->terminal_row >= VGA_HEIGHT) { + terminal_shiftup(term); + //terminal_row = 0; + } +} + +void terminal_write(kVGATerm *term, const char* data, size_t size) { + for (size_t i = 0; i < size; i++) { + terminal_putchar(term, data[i]); + } + +} + +void terminal_writestring(kVGATerm *term, const char* data) { + terminal_write(term, data, strlen(data)); +} + +size_t strlen(const char* str) { + size_t len = 0; + while (str[len]) + len++; + return len; +} diff --git a/term.h b/term.h new file mode 100644 index 0000000..624ed0c --- /dev/null +++ b/term.h @@ -0,0 +1,62 @@ +#ifndef TERM_K_H +#define TERM_K_H + +#include +#include +#include + +static const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; + +struct kVGATerm { + size_t terminal_row; + size_t terminal_column; + uint8_t terminal_color; + uint16_t* terminal_buffer; +}; +typedef struct kVGATerm kVGATerm; +void terminal_initialize(kVGATerm *term); + +void terminal_shiftup(kVGATerm *term); + + +void terminal_setcolor(kVGATerm *term, uint8_t color); + + +void terminal_putentryat(kVGATerm *term, char c, uint8_t color, size_t x, size_t y); + + +void terminal_write(kVGATerm *term, const char* data, size_t size); + +void terminal_writestring(kVGATerm *term, const char * data); + +void terminal_putchar(kVGATerm *term, char c); + +enum vga_color { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, +}; + +static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg); + + +static inline uint16_t vga_entry(unsigned char uc, uint8_t color); + +size_t strlen(const char* str); + + +#endif