Compare commits
2 commits
d6465ade55
...
53198515c8
| Author | SHA1 | Date | |
|---|---|---|---|
| 53198515c8 | |||
| 62ab718e4d |
7 changed files with 71 additions and 44 deletions
21
Makefile
21
Makefile
|
|
@ -25,6 +25,19 @@ OBJECTS := $(OBJECTS:.s=.o)
|
||||||
OUT_ELF := $(BIN_DIR)/ukern.elf
|
OUT_ELF := $(BIN_DIR)/ukern.elf
|
||||||
OUT_ISO := $(BIN_DIR)/uOS.iso
|
OUT_ISO := $(BIN_DIR)/uOS.iso
|
||||||
|
|
||||||
|
###QEMU CONFIG
|
||||||
|
QEMU_FLAGS :=
|
||||||
|
|
||||||
|
VGA ?= 1
|
||||||
|
SERIAL ?= 0
|
||||||
|
|
||||||
|
ifeq ($(VGA), 0)
|
||||||
|
QEMU_FLAGS += -display none
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SERIAL), 1)
|
||||||
|
QEMU_FLAGS += -serial stdio
|
||||||
|
endif
|
||||||
###RULES
|
###RULES
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
@ -61,16 +74,16 @@ iso: $(OUT_ISO)
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: $(OUT_ELF)
|
run: $(OUT_ELF)
|
||||||
$(QEMU) -kernel $(OUT_ELF)
|
$(QEMU) $(QEMU_FLAGS) -kernel $(OUT_ELF)
|
||||||
|
|
||||||
.PHONY: debug
|
.PHONY: debug
|
||||||
debug:
|
debug:
|
||||||
$(QEMU) -s -S -kernel $(OUT_ELF)
|
$(QEMU) $(QEMU_FLAGS) -s -S -kernel $(OUT_ELF)
|
||||||
|
|
||||||
.PHONY: run_iso
|
.PHONY: run_iso
|
||||||
run_iso:
|
run_iso:
|
||||||
$(QEMU) -cdrom $(OUT_ISO)
|
$(QEMU) $(QEMU_FLAGS) -cdrom $(OUT_ISO)
|
||||||
|
|
||||||
.PHONY: debug_iso
|
.PHONY: debug_iso
|
||||||
debug_iso:
|
debug_iso:
|
||||||
$(QEMU) -s -S -cdrom $(OUT_ISO)
|
$(QEMU) $(QEMU_FLAGS) -s -S -cdrom $(OUT_ISO)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ struct char_writer_s {
|
||||||
void* ctx;
|
void* ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern char_writer_t* default_output;
|
||||||
|
|
||||||
int putc(char_writer_t*, char);
|
int putc(char_writer_t*, char);
|
||||||
int print(char_writer_t*, const char*);
|
int print(char_writer_t*, const char*);
|
||||||
int println(char_writer_t*, const char*);
|
int println(char_writer_t*, const char*);
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct SerialState_s {
|
typedef struct serial_ctx_s {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
} SerialState_t;
|
} serial_ctx_t;
|
||||||
|
|
||||||
extern char_writer_t* default_COM;
|
extern char_writer_t* default_COM;
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ extern char_writer_t* default_COM;
|
||||||
* @param port The serial port number to initialize
|
* @param port The serial port number to initialize
|
||||||
* @return Status code indicating success or failure
|
* @return Status code indicating success or failure
|
||||||
*/
|
*/
|
||||||
int serial_init(uint16_t port);
|
int serial_init(serial_ctx_t* ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if there is pending data to receive on the serial port
|
* @brief Check if there is pending data to receive on the serial port
|
||||||
|
|
@ -32,19 +32,19 @@ int serial_recv_pending();
|
||||||
* @brief Receive a single byte from the serial port
|
* @brief Receive a single byte from the serial port
|
||||||
* @return The received byte as an 8-bit unsigned integer
|
* @return The received byte as an 8-bit unsigned integer
|
||||||
*/
|
*/
|
||||||
uint8_t serial_recv8(uint16_t port);
|
uint8_t serial_recv8(serial_ctx_t* ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the serial port is ready to send data
|
* @brief Check if the serial port is ready to send data
|
||||||
* @return Non-zero if ready to send, 0 otherwise
|
* @return Non-zero if ready to send, 0 otherwise
|
||||||
*/
|
*/
|
||||||
int serial_send_pending(uint16_t port);
|
int serial_send_pending(serial_ctx_t* ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a single byte through the serial port
|
* @brief Send a single byte through the serial port
|
||||||
* @param data The 8-bit data byte to send
|
* @param data The 8-bit data byte to send
|
||||||
*/
|
*/
|
||||||
int serial_send8(uint16_t port, char data);
|
int serial_send8(void* ctx, char data);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,13 @@
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
void generic_isr_handler(StateSnapshot_t* cpu_state) {
|
void generic_isr_handler(StateSnapshot_t* cpu_state) {
|
||||||
//We made it to C for our interrupt! For now, let's just print our interrupt to the screen.
|
//We made it to C for our interrupt! For now, let's just print our interrupt to the screen.
|
||||||
//What's cookin for outputs?
|
|
||||||
char_writer_t* out = 0;
|
|
||||||
if(default_COM) {
|
|
||||||
out = default_COM;
|
|
||||||
} else if(default_vga) {
|
|
||||||
out = default_vga;
|
|
||||||
vga_clear_ctx(default_vga->ctx);
|
|
||||||
}
|
|
||||||
switch(cpu_state->interrupt_id) {
|
switch(cpu_state->interrupt_id) {
|
||||||
default:
|
default:
|
||||||
if(out){
|
if(default_output){
|
||||||
printf(out, "INTERRUPT TRIGGERED! Info below.\n");
|
printf(default_output, "INTERRUPT TRIGGERED! Info below.\n");
|
||||||
printf(out, "Int_ID|ERR: %X|%X\n", cpu_state->interrupt_id, cpu_state->error_code);
|
printf(default_output, "Int_ID|ERR: %X|%X\n", cpu_state->interrupt_id, cpu_state->error_code);
|
||||||
printf(out, "EFLAGS|CS|EIP: %X|%X|%X\n", cpu_state->eflags, cpu_state->cs,cpu_state->eip);
|
printf(default_output, "EFLAGS|CS|EIP: %X|%X|%X\n", cpu_state->eflags, cpu_state->cs,cpu_state->eip);
|
||||||
printf(out, "GP Registers:\neax:%X\nebx:%X\necx:%X\nedx:%X\nesp:%X\nebp:%X\nesi:%X\nedi:%X\n",
|
printf(default_output, "GP Registers:\neax:%X\nebx:%X\necx:%X\nedx:%X\nesp:%X\nebp:%X\nesi:%X\nedi:%X\n",
|
||||||
cpu_state->eax,
|
cpu_state->eax,
|
||||||
cpu_state->ebx,
|
cpu_state->ebx,
|
||||||
cpu_state->ecx,
|
cpu_state->ecx,
|
||||||
|
|
@ -27,7 +19,7 @@ void generic_isr_handler(StateSnapshot_t* cpu_state) {
|
||||||
cpu_state->ebp,
|
cpu_state->ebp,
|
||||||
cpu_state->esi,
|
cpu_state->esi,
|
||||||
cpu_state->edi);
|
cpu_state->edi);
|
||||||
printf(out, "HALT!");
|
printf(default_output, "HALT!");
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
src/io.c
2
src/io.c
|
|
@ -2,6 +2,8 @@
|
||||||
#include "kttools.h"
|
#include "kttools.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
char_writer_t* default_output = 0;
|
||||||
|
|
||||||
int printhex(char_writer_t* writer, uint32_t out) {
|
int printhex(char_writer_t* writer, uint32_t out) {
|
||||||
char buff[9];
|
char buff[9];
|
||||||
i_to_str(out, buff, 9, 0x10);
|
i_to_str(out, buff, 9, 0x10);
|
||||||
|
|
|
||||||
24
src/main.c
24
src/main.c
|
|
@ -25,17 +25,27 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
||||||
default_vga = &vga_writer;
|
default_vga = &vga_writer;
|
||||||
vga_clear_ctx(&vga_ctx);
|
vga_clear_ctx(&vga_ctx);
|
||||||
|
|
||||||
|
//Serial prep
|
||||||
|
serial_ctx_t serial_ctx;
|
||||||
|
serial_ctx.port = COM1;
|
||||||
|
char_writer_t serial_writer;
|
||||||
|
serial_writer.ctx = &serial_ctx;
|
||||||
|
serial_writer.putChar = serial_send8;
|
||||||
|
default_COM = &serial_writer;
|
||||||
|
serial_init(&serial_ctx);
|
||||||
|
|
||||||
printf(&vga_writer, "Entry eax:%X\n", multiboot_magic);
|
//AND OUR DEFAULT OUTPUT IS:
|
||||||
|
default_output = default_vga;
|
||||||
|
|
||||||
|
printf(default_output, "Entry eax:%X\n", multiboot_magic);
|
||||||
|
|
||||||
if(multiboot_magic != 0x2BADB002) {
|
if(multiboot_magic != 0x2BADB002) {
|
||||||
println(&vga_writer, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!");
|
println(default_output, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
println(&vga_writer, "Multiboot detected! Continuing...");
|
println(default_output, "Multiboot detected! Continuing...");
|
||||||
}
|
}
|
||||||
|
printf(default_output, "MEM_LOWER:%X\n", multiboot_info->mem_lower);
|
||||||
printf(&vga_writer, "MEM_LOWER:%X\n", multiboot_info->mem_lower);
|
printf(default_output, "MEM_UPPER:%X\n", multiboot_info->mem_upper);
|
||||||
printf(&vga_writer, "MEM_UPPER:%X\n", multiboot_info->mem_upper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
36
src/serial.c
36
src/serial.c
|
|
@ -3,11 +3,12 @@
|
||||||
|
|
||||||
char_writer_t* default_COM = 0;
|
char_writer_t* default_COM = 0;
|
||||||
|
|
||||||
int serial_init(uint16_t port) {
|
int serial_init(serial_ctx_t* ctx) {
|
||||||
|
|
||||||
//disable interrupts when messing with it
|
//disable interrupts when messing with it
|
||||||
outb(port + 1, 0x00);
|
outb(ctx->port + 1, 0x00);
|
||||||
//set the dlab latch in order to make the baud rate accessible. In binary for clarity.
|
//set the dlab latch in order to make the baud rate accessible. In binary for clarity.
|
||||||
outb(port + 3, 0b10000000);
|
outb(ctx->port + 3, 0b10000000);
|
||||||
|
|
||||||
//Sets the baud rate. Quick except on baud rate:
|
//Sets the baud rate. Quick except on baud rate:
|
||||||
//internal clock for the serial controller is 115200 ticks/sec. Or 115200hz.
|
//internal clock for the serial controller is 115200 ticks/sec. Or 115200hz.
|
||||||
|
|
@ -18,44 +19,51 @@ int serial_init(uint16_t port) {
|
||||||
//(Source:https://wiki.osdev.org/Serial_Ports#Baud_Rate)
|
//(Source:https://wiki.osdev.org/Serial_Ports#Baud_Rate)
|
||||||
|
|
||||||
//Baud lo byte
|
//Baud lo byte
|
||||||
outb(port, 0x03);
|
outb(ctx->port, 0x03);
|
||||||
//Baud hi byte
|
//Baud hi byte
|
||||||
outb(port+1, 0x00);
|
outb(ctx->port+1, 0x00);
|
||||||
|
|
||||||
//Again from OSWiki we're going to use their defaults for now.
|
//Again from OSWiki we're going to use their defaults for now.
|
||||||
//DLAB off
|
//DLAB off
|
||||||
//Parity=0(no Parity)
|
//Parity=0(no Parity)
|
||||||
//One stop bit (set to 0)
|
//One stop bit (set to 0)
|
||||||
//Transmit in units of 8 bits
|
//Transmit in units of 8 bits
|
||||||
outb(port+3, 0b00000011);
|
outb(ctx->port+3, 0b00000011);
|
||||||
|
|
||||||
//FIFO Control register
|
//FIFO Control register
|
||||||
//14 bit threshold for interrupt trigger
|
//14 bit threshold for interrupt trigger
|
||||||
//flush and enable FIFOs.
|
//flush and enable FIFOs.
|
||||||
outb(port+2, 0b11000111);
|
outb(ctx->port+2, 0b11000111);
|
||||||
|
|
||||||
//Enable IRQs + DTR + RTS
|
//Enable IRQs + DTR + RTS
|
||||||
//Nicely explained here: https://stackoverflow.com/questions/957337/what-is-the-difference-between-dtr-dsr-and-rts-cts-flow-control
|
//Nicely explained here: https://stackoverflow.com/questions/957337/what-is-the-difference-between-dtr-dsr-and-rts-cts-flow-control
|
||||||
//In the future, this will be referred to 0x0B.
|
//In the future, this will be referred to 0x0B.
|
||||||
outb(port+4, 0b00001011);
|
outb(ctx->port+4, 0b00001011);
|
||||||
|
|
||||||
//done! Let's test our chip. put it in loopback mode.
|
//done! Let's test our chip. put it in loopback mode.
|
||||||
outb(port+4, 0x1E);
|
outb(ctx->port+4, 0x1E);
|
||||||
//Lets try sending C4 (boom!) to test it
|
//Lets try sending C4 (boom!) to test it
|
||||||
outb(port, 0xC4);
|
outb(ctx->port, 0xC4);
|
||||||
|
|
||||||
if(inb(port) != 0xC4) {
|
if(inb(ctx->port) != 0xC4) {
|
||||||
//Boo womp
|
//Boo womp
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//we're good! All set up. Lets put it back into normal operational mode and gtfo.
|
//we're good! All set up. Lets put it back into normal operational mode and gtfo.
|
||||||
outb(port+4, 0x0B);
|
outb(ctx->port+4, 0x0B);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int serial_send_pending(uint16_t port) {
|
int serial_send_pending(serial_ctx_t* ctx) {
|
||||||
//Bit 5 of the line status register has our output queue, essentially
|
//Bit 5 of the line status register has our output queue, essentially
|
||||||
return !(inb(port + 5) & 0x20);
|
return !(inb(ctx->port + 5) & 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
int serial_send8(void* ctx, char out) {
|
||||||
|
serial_ctx_t* serial_ctx = (serial_ctx_t*) ctx;
|
||||||
|
while(serial_send_pending(serial_ctx));
|
||||||
|
outb(serial_ctx->port, out);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue