diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | compile_flags.txt | 6 | ||||
| -rw-r--r-- | include/io.h | 13 | ||||
| -rw-r--r-- | include/utils.h | 8 | ||||
| -rw-r--r-- | include/video.h | 23 | ||||
| -rw-r--r-- | src/boot.asm | 6 | ||||
| -rw-r--r-- | src/io.c | 46 | ||||
| -rw-r--r-- | src/kernel.c | 43 | ||||
| -rw-r--r-- | src/utils.c | 13 | ||||
| -rw-r--r-- | src/video.c | 33 |
10 files changed, 161 insertions, 32 deletions
@@ -24,7 +24,7 @@ all: $(IMAGE) bin: $(BIN) demo: $(IMAGE) - $(QEMU) -cdrom $< + $(QEMU) -chardev file,id=char0,path=/tmp/serial.log,signal=off -serial chardev:char0 -cdrom $< clean: rm -rf $(OBJ) $(ISO) $(BIN) $(IMAGE) diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..2c3cb1d --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,6 @@ +--target=i686-elf +-std=c11 +-ffreestanding +-Wall +-Wextra +-Iinclude diff --git a/include/io.h b/include/io.h new file mode 100644 index 0000000..ed71e6f --- /dev/null +++ b/include/io.h @@ -0,0 +1,13 @@ +#include <stdint.h> + +#ifndef IO_H +#define IO_H + +uint8_t inportb(uint16_t port); +void outportb(uint16_t port, uint8_t data); +void init_serial(); +void serial_putc(char c); +void serial_puts(const char* s); +void serial_puthex(uint32_t h); + +#endif // IO_H
\ No newline at end of file diff --git a/include/utils.h b/include/utils.h index 9ea1f09..beed3cc 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,5 +1,7 @@ #include <stdbool.h> +#define DEBUG 0 + #ifndef UTILS_H #define UTILS_H @@ -7,7 +9,7 @@ #define asm __asm__ volatile #endif -void macaroni_panic(char* msg); -void macaroni_assert(bool condition, char* msg); +void macaroni_panic(const char* msg); +void macaroni_assert(bool condition, const char* msg); -#endif // UTILS_H
\ No newline at end of file +#endif // UTILS_H diff --git a/include/video.h b/include/video.h new file mode 100644 index 0000000..85a670c --- /dev/null +++ b/include/video.h @@ -0,0 +1,23 @@ +#include <stdint.h> +#include "multiboot.h" + +#ifndef VIDEO_H +#define VIDEO_H + +#define MULTIBOOT_GODS_WIDTH 640 +#define MULTIBOOT_GODS_HEIGHT 480 +#define MULTIBOOT_VIDEO_BPP 24 + +typedef uint32_t macaroni_color; +static macaroni_color RED = 0xFF0000; +static macaroni_color GREEN = 0x00FF00; +static macaroni_color BLUE = 0x0000FF; + +static uint8_t* video_framebuffer; +static uint32_t pitch; +static uint32_t pixel_width; + +void init_video(multiboot_info_t* p_multiboot_info); +void put_pixel(macaroni_color color, uint16_t x, uint16_t y); + +#endif // VIDEO_H diff --git a/src/boot.asm b/src/boot.asm index e723d61..3d25240 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -1,4 +1,4 @@ -;> The Multiboot header must be contained completely within the first 8192 bytes of the OS +;> The Multiboot header must be contained completely within the first 8192 bytes of the OS ;> image, and must be longword (32-bit) aligned. MULTIBOOT_ALIGN_TO_PAGE: equ 1 << 0 MULTIBOOT_MEMORY_DESCRIBE: equ 1 << 1 @@ -9,7 +9,7 @@ MULTIBOOT_CHECKSUM: equ -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) MULTIBOOT_VIDEO_TYPE: equ 0 MULTIBOOT_GODS_WIDTH: equ 640 MULTIBOOT_GODS_HEIGHT: equ 480 -MULTIBOOT_VIDEO_BPP: equ 16 +MULTIBOOT_VIDEO_BPP: equ 24 ; We don't set flags[16] because we assemble to ELF32 so header_addr, etc is useless to us ; (at least at the moment). @@ -39,6 +39,8 @@ section .text global _start:function (_start.end - _start) _start: mov esp, stack_top + push ebx + push eax extern cmain call cmain cli @@ -1,6 +1,10 @@ #include <stdint.h> #include "utils.h" +#define PORT 0x3f8 // COM1 +#define LINE_STATUS_REGISTER PORT + 5 +#define TRANSMITTER_EMPTY_BITMASK 0b00100000 + uint8_t inportb(uint16_t port) { uint8_t r; asm("inb %1, %0" : "=a" (r) : "dN" (port)); @@ -9,4 +13,44 @@ uint8_t inportb(uint16_t port) { void outportb(uint16_t port, uint8_t data) { asm("outb %1, %0" : : "dN" (port), "a" (data)); -}
\ No newline at end of file +} + +void init_serial() { + outportb(PORT + 1, 0x00); // Disable all interrupts + outportb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + + // Set divisor to 3 -> (115200 / 3) = 38400 + outportb(PORT + 0, 0x03); // LSB + outportb(PORT + 1, 0x00); // MSB + + outportb(PORT + 3, 0x03); // Character length is 8 bits, no parity, one stop bit + outportb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + +// TODO: GDT and IDT in order to setup COM1 interrupts. +// For now, though, we POLLLLL that mf. +// outportb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + + outportb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip + outportb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) + macaroni_assert(inportb(PORT + 0) == 0xAE, "0xAE expected from serial initizliation"); + outportb(PORT + 4, 0x0F); +} + +int serial_tx_empty(void) { + return inportb(LINE_STATUS_REGISTER) & TRANSMITTER_EMPTY_BITMASK; +} + +void serial_putc(char c) { + while (!serial_tx_empty()); + outportb(PORT, c); +} + +void serial_puts(const char* s) { + while (*s) serial_putc(*s++); +} + +void serial_puthex(uint32_t h) { + serial_puts("0x"); + for (int i = 28; i >= 0; i -= 4) + serial_putc("0123456789abcdef"[(h >> i) & 0xF]); +} diff --git a/src/kernel.c b/src/kernel.c index 2c2afcc..dacc47e 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,28 +1,33 @@ -#include "utils.h" -#include "multiboot.h" #include <stddef.h> #include <stdint.h> #include <stdbool.h> +#include "utils.h" +#include "multiboot.h" +#include "io.h" +#include "video.h" -void validate_multiboot +void validate_multiboot(multiboot_info_t* p_multiboot_info, uint32_t magic_response) { + macaroni_assert(magic_response == 0x2BADB002, "im not a bad boo twooo"); + macaroni_assert(p_multiboot_info->flags != 0, "version flag being zero is not a good sign"); +} -void cmain(void) { - uint32_t magic_response; - multiboot_info_t* p_multiboot_info; - asm("\t movl %%eax,%0" : "=r"(magic_response)); - asm("\t movl %%ebx,%0" : "=r"(p_multiboot_info)); +// Stack: [...Bottom] (%ebx, %eax) [...Top] +void cmain(uint32_t magic_response, multiboot_info_t* p_multiboot_info) { + validate_multiboot(p_multiboot_info, magic_response); - macaroni_assert(magic_response == 0x2BADB002, "im not a bad boo twooo"); - macaroni_assert(p_multiboot_info->framebuffer_width == 640, "not gods width"); - macaroni_assert(p_multiboot_info->framebuffer_height == 480, "not gods height"); - macaroni_assert(p_multiboot_info->framebuffer_bpp == 16, "not gods bpp"); - macaroni_assert(p_multiboot_info->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB, "not gods fbtype"); - macaroni_assert(p_multiboot_info->framebuffer_red_field_position == 1, "bpp not formatted correctly"); + init_serial(); + init_video(p_multiboot_info); - void *fb = (void *) (unsigned long) p_multiboot_info->framebuffer_addr; - uint8_t* pixel = fb; - for (int i = 0; i < 10000; i++) { - *(pixel + i) = i * 2; + macaroni_color colors[] = { RED, GREEN, BLUE }; + uint32_t i = 0; + while(true) { + for (uint32_t y = 0; y < MULTIBOOT_GODS_HEIGHT; y++) { + for (uint32_t x = 0; x < MULTIBOOT_GODS_WIDTH; x++) { + put_pixel(colors[(i + y / 10) % 3], x, y); + } + } + // "sleep" + for (int _k = 0; _k < 10000000; _k++) {} + i++; } - } diff --git a/src/utils.c b/src/utils.c index 63b0b56..bf1ff13 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,14 +1,15 @@ #include "utils.h" +#include "io.h" -void macaroni_panic(char* msg) { +void macaroni_panic(const char* msg) { // we'll do something with msg later. // while(true){ asm("nop\n\t"); } + serial_puts(msg); asm("int $0x13"); } -void macaroni_assert(bool condition, char* msg) { - if (condition) { - return; +void macaroni_assert(bool condition, const char* msg) { + if (!condition) { + macaroni_panic(msg); } - macaroni_panic("thisisatest"); -}
\ No newline at end of file +} diff --git a/src/video.c b/src/video.c new file mode 100644 index 0000000..be01f6d --- /dev/null +++ b/src/video.c @@ -0,0 +1,33 @@ +#include "video.h" +#include "utils.h" +#include "io.h" + +void init_video(multiboot_info_t* p_multiboot_info) { + #ifdef DEBUG + macaroni_assert(p_multiboot_info->framebuffer_width == MULTIBOOT_GODS_WIDTH, "not gods width"); + macaroni_assert(p_multiboot_info->framebuffer_height == MULTIBOOT_GODS_HEIGHT, "not gods height"); + macaroni_assert(p_multiboot_info->framebuffer_bpp == MULTIBOOT_VIDEO_BPP, "not gods bpp"); + macaroni_assert(p_multiboot_info->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB, "not video fbtype"); + #endif + + #ifdef DEBUG + serial_puthex((uint32_t) p_multiboot_info->framebuffer_red_field_position); + serial_puthex((uint32_t) p_multiboot_info->framebuffer_red_mask_size); + serial_puthex((uint32_t) p_multiboot_info->framebuffer_green_field_position); + serial_puthex((uint32_t) p_multiboot_info->framebuffer_green_mask_size); + serial_puthex((uint32_t) p_multiboot_info->framebuffer_blue_field_position); + serial_puthex((uint32_t) p_multiboot_info->framebuffer_blue_mask_size); + serial_puthex((uint32_t) p_multiboot_info->framebuffer_bpp); + serial_puthex((uint32_t) p_multiboot_info->framebuffer_pitch); + #endif // DEBUG + + video_framebuffer = (uint8_t*) (uint32_t) p_multiboot_info->framebuffer_addr; + pixel_width = (p_multiboot_info->framebuffer_bpp / 8); + pitch = p_multiboot_info->framebuffer_pitch; +} + +void put_pixel(macaroni_color color, uint16_t x, uint16_t y) { + video_framebuffer[x * pixel_width + y * pitch] = color & 0xFF; + video_framebuffer[x * pixel_width + y * pitch + 1] = (color >> 8) & 0xFF; + video_framebuffer[x * pixel_width + y * pitch + 2] = (color >> 16) & 0xFF; +} |
