Add C89 Support

pull/187/head
Simon Chaykin 4 years ago
parent 7aff64740e
commit 647cc4fe6a

@ -4,10 +4,10 @@ HEADERS = $(wildcard kernel/*.h drivers/*.h cpu/*.h libc/*.h)
OBJ = ${C_SOURCES:.c=.o cpu/interrupt.o} OBJ = ${C_SOURCES:.c=.o cpu/interrupt.o}
# Change this if your cross-compiler is somewhere else # Change this if your cross-compiler is somewhere else
CC = /usr/local/i386elfgcc/bin/i386-elf-gcc CC = gcc -m32 -Wall -Wextra -pedantic-errors -std=c89
GDB = /usr/local/i386elfgcc/bin/i386-elf-gdb GDB = gdb
# -g: Use debugging symbols in gcc # -g: Use debugging symbols in gcc
CFLAGS = -g -ffreestanding -Wall -Wextra -fno-exceptions -m32 CFLAGS = -g -ffreestanding -Wall -Wextra -fno-exceptions -m32 -fno-pie
# First rule is run by default # First rule is run by default
os-image.bin: boot/bootsect.bin kernel.bin os-image.bin: boot/bootsect.bin kernel.bin
@ -16,11 +16,11 @@ os-image.bin: boot/bootsect.bin kernel.bin
# '--oformat binary' deletes all symbols as a collateral, so we don't need # '--oformat binary' deletes all symbols as a collateral, so we don't need
# to 'strip' them manually on this case # to 'strip' them manually on this case
kernel.bin: boot/kernel_entry.o ${OBJ} kernel.bin: boot/kernel_entry.o ${OBJ}
i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary @ld -melf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary
# Used for debugging purposes # Used for debugging purposes
kernel.elf: boot/kernel_entry.o ${OBJ} kernel.elf: boot/kernel_entry.o ${OBJ}
i386-elf-ld -o $@ -Ttext 0x1000 $^ ld -melf_i386 -o $@ -Ttext 0x1000 $^
run: os-image.bin run: os-image.bin
qemu-system-i386 -fda os-image.bin qemu-system-i386 -fda os-image.bin

@ -13,5 +13,5 @@ void set_idt() {
idt_reg.base = (uint32_t) &idt; idt_reg.base = (uint32_t) &idt;
idt_reg.limit = IDT_ENTRIES * sizeof(idt_gate_t) - 1; idt_reg.limit = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
/* Don't make the mistake of loading &idt -- always load &idt_reg */ /* Don't make the mistake of loading &idt -- always load &idt_reg */
asm volatile("lidtl (%0)" : : "r" (&idt_reg)); __asm__ volatile("lidtl (%0)" : : "r" (&idt_reg));
} }

@ -44,7 +44,7 @@ void isr_install() {
set_idt_gate(30, (uint32_t)isr30); set_idt_gate(30, (uint32_t)isr30);
set_idt_gate(31, (uint32_t)isr31); set_idt_gate(31, (uint32_t)isr31);
// Remap the PIC /* Remap the PIC */
port_byte_out(0x20, 0x11); port_byte_out(0x20, 0x11);
port_byte_out(0xA0, 0x11); port_byte_out(0xA0, 0x11);
port_byte_out(0x21, 0x20); port_byte_out(0x21, 0x20);
@ -56,7 +56,7 @@ void isr_install() {
port_byte_out(0x21, 0x0); port_byte_out(0x21, 0x0);
port_byte_out(0xA1, 0x0); port_byte_out(0xA1, 0x0);
// Install the IRQs /* Install the IRQs */
set_idt_gate(32, (uint32_t)irq0); set_idt_gate(32, (uint32_t)irq0);
set_idt_gate(33, (uint32_t)irq1); set_idt_gate(33, (uint32_t)irq1);
set_idt_gate(34, (uint32_t)irq2); set_idt_gate(34, (uint32_t)irq2);
@ -74,7 +74,7 @@ void isr_install() {
set_idt_gate(46, (uint32_t)irq14); set_idt_gate(46, (uint32_t)irq14);
set_idt_gate(47, (uint32_t)irq15); set_idt_gate(47, (uint32_t)irq15);
set_idt(); // Load with ASM set_idt(); /* Load with ASM */
} }
/* To print the message which defines every exception */ /* To print the message which defines every exception */
@ -117,8 +117,8 @@ char *exception_messages[] = {
}; };
void isr_handler(registers_t *r) { void isr_handler(registers_t *r) {
kprint("received interrupt: ");
char s[3]; char s[3];
kprint("received interrupt: ");
int_to_ascii(r->int_no, s); int_to_ascii(r->int_no, s);
kprint(s); kprint(s);
kprint("\n"); kprint("\n");
@ -133,19 +133,20 @@ void register_interrupt_handler(uint8_t n, isr_t handler) {
void irq_handler(registers_t *r) { void irq_handler(registers_t *r) {
/* After every interrupt we need to send an EOI to the PICs /* After every interrupt we need to send an EOI to the PICs
* or they will not send another interrupt again */ * or they will not send another interrupt again */
isr_t handler;
if (r->int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */ if (r->int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */
port_byte_out(0x20, 0x20); /* master */ port_byte_out(0x20, 0x20); /* master */
/* Handle the interrupt in a more modular way */ /* Handle the interrupt in a more modular way */
if (interrupt_handlers[r->int_no] != 0) { if (interrupt_handlers[r->int_no] != 0) {
isr_t handler = interrupt_handlers[r->int_no]; handler = interrupt_handlers[r->int_no];
handler(r); handler(r);
} }
} }
void irq_install() { void irq_install() {
/* Enable interruptions */ /* Enable interruptions */
asm volatile("sti"); __asm__ volatile("sti");
/* IRQ0: timer */ /* IRQ0: timer */
init_timer(50); init_timer(50);
/* IRQ1: keyboard */ /* IRQ1: keyboard */

@ -13,7 +13,7 @@ uint8_t port_byte_in (uint16_t port) {
* *
* Inputs and outputs are separated by colons * Inputs and outputs are separated by colons
*/ */
asm("in %%dx, %%al" : "=a" (result) : "d" (port)); __asm__ volatile("in %%dx, %%al" : "=a" (result) : "d" (port));
return result; return result;
} }
@ -23,15 +23,15 @@ void port_byte_out (uint16_t port, uint8_t data) {
* However we see a comma since there are two variables in the input area * However we see a comma since there are two variables in the input area
* and none in the 'return' area * and none in the 'return' area
*/ */
asm volatile("out %%al, %%dx" : : "a" (data), "d" (port)); __asm__ volatile("out %%al, %%dx" : : "a" (data), "d" (port));
} }
uint16_t port_word_in (uint16_t port) { uint16_t port_word_in (uint16_t port) {
uint16_t result; uint16_t result;
asm("in %%dx, %%ax" : "=a" (result) : "d" (port)); __asm__ volatile("in %%dx, %%ax" : "=a" (result) : "d" (port));
return result; return result;
} }
void port_word_out (uint16_t port, uint16_t data) { void port_word_out (uint16_t port, uint16_t data) {
asm volatile("out %%ax, %%dx" : : "a" (data), "d" (port)); __asm__ volatile("out %%ax, %%dx" : : "a" (data), "d" (port));
} }

@ -11,13 +11,14 @@ static void timer_callback(registers_t *regs) {
} }
void init_timer(uint32_t freq) { void init_timer(uint32_t freq) {
/* Install the function we just wrote */
register_interrupt_handler(IRQ0, timer_callback);
/* Get the PIT value: hardware clock at 1193180 Hz */ /* Get the PIT value: hardware clock at 1193180 Hz */
uint32_t divisor = 1193180 / freq; uint32_t divisor = 1193180 / freq;
uint8_t low = (uint8_t)(divisor & 0xFF); uint8_t low = (uint8_t)(divisor & 0xFF);
uint8_t high = (uint8_t)( (divisor >> 8) & 0xFF); uint8_t high = (uint8_t)( (divisor >> 8) & 0xFF);
/* Install the function we just wrote */
register_interrupt_handler(IRQ0, timer_callback);
/* Send the command */ /* Send the command */
port_byte_out(0x43, 0x36); /* Command port */ port_byte_out(0x43, 0x36); /* Command port */
port_byte_out(0x40, low); port_byte_out(0x40, low);

@ -28,7 +28,8 @@ const char sc_ascii[] = { '?', '?', '1', '2', '3', '4', '5', '6',
static void keyboard_callback(registers_t *regs) { static void keyboard_callback(registers_t *regs) {
/* The PIC leaves us the scancode in port 0x60 */ /* The PIC leaves us the scancode in port 0x60 */
uint8_t scancode = port_byte_in(0x60); uint8_t scancode = port_byte_in(0x60);
char letter;
char str[2];
if (scancode > SC_MAX) return; if (scancode > SC_MAX) return;
if (scancode == BACKSPACE) { if (scancode == BACKSPACE) {
backspace(key_buffer); backspace(key_buffer);
@ -38,9 +39,10 @@ static void keyboard_callback(registers_t *regs) {
user_input(key_buffer); /* kernel-controlled function */ user_input(key_buffer); /* kernel-controlled function */
key_buffer[0] = '\0'; key_buffer[0] = '\0';
} else { } else {
char letter = sc_ascii[(int)scancode]; letter = sc_ascii[(int)scancode];
/* Remember that kprint only accepts char[] */ /* Remember that kprint only accepts char[] */
char str[2] = {letter, '\0'}; str[0] = letter;
str[1] = '\0';
append(key_buffer, letter); append(key_buffer, letter);
kprint(str); kprint(str);
} }

@ -21,7 +21,7 @@ int get_offset_col(int offset);
*/ */
void kprint_at(char *message, int col, int row) { void kprint_at(char *message, int col, int row) {
/* Set cursor if col/row are negative */ /* Set cursor if col/row are negative */
int offset; int offset, i = 0;
if (col >= 0 && row >= 0) if (col >= 0 && row >= 0)
offset = get_offset(col, row); offset = get_offset(col, row);
else { else {
@ -31,7 +31,6 @@ void kprint_at(char *message, int col, int row) {
} }
/* Loop through message and print it */ /* Loop through message and print it */
int i = 0;
while (message[i] != 0) { while (message[i] != 0) {
offset = print_char(message[i++], col, row, WHITE_ON_BLACK); offset = print_char(message[i++], col, row, WHITE_ON_BLACK);
/* Compute row/col for next iteration */ /* Compute row/col for next iteration */
@ -67,6 +66,9 @@ void kprint_backspace() {
*/ */
int print_char(char c, int col, int row, char attr) { int print_char(char c, int col, int row, char attr) {
uint8_t *vidmem = (uint8_t*) VIDEO_ADDRESS; uint8_t *vidmem = (uint8_t*) VIDEO_ADDRESS;
int offset;
int i;
char *last_line;
if (!attr) attr = WHITE_ON_BLACK; if (!attr) attr = WHITE_ON_BLACK;
/* Error control: print a red 'E' if the coords aren't right */ /* Error control: print a red 'E' if the coords aren't right */
@ -76,7 +78,6 @@ int print_char(char c, int col, int row, char attr) {
return get_offset(col, row); return get_offset(col, row);
} }
int offset;
if (col >= 0 && row >= 0) offset = get_offset(col, row); if (col >= 0 && row >= 0) offset = get_offset(col, row);
else offset = get_cursor_offset(); else offset = get_cursor_offset();
@ -94,14 +95,13 @@ int print_char(char c, int col, int row, char attr) {
/* Check if the offset is over screen size and scroll */ /* Check if the offset is over screen size and scroll */
if (offset >= MAX_ROWS * MAX_COLS * 2) { if (offset >= MAX_ROWS * MAX_COLS * 2) {
int i; for (i = 1; i < MAX_ROWS; i++)
for (i = 1; i < MAX_ROWS; i++)
memory_copy((uint8_t*)(get_offset(0, i) + VIDEO_ADDRESS), memory_copy((uint8_t*)(get_offset(0, i) + VIDEO_ADDRESS),
(uint8_t*)(get_offset(0, i-1) + VIDEO_ADDRESS), (uint8_t*)(get_offset(0, i-1) + VIDEO_ADDRESS),
MAX_COLS * 2); MAX_COLS * 2);
/* Blank last line */ /* Blank last line */
char *last_line = (char*) (get_offset(0, MAX_ROWS-1) + (uint8_t*) VIDEO_ADDRESS); last_line = (char*) (get_offset(0, MAX_ROWS-1) + (uint8_t*) VIDEO_ADDRESS);
for (i = 0; i < MAX_COLS * 2; i++) last_line[i] = 0; for (i = 0; i < MAX_COLS * 2; i++) last_line[i] = 0;
offset -= 2 * MAX_COLS; offset -= 2 * MAX_COLS;
@ -116,8 +116,9 @@ int get_cursor_offset() {
* 1. Ask for high byte of the cursor offset (data 14) * 1. Ask for high byte of the cursor offset (data 14)
* 2. Ask for low byte (data 15) * 2. Ask for low byte (data 15)
*/ */
int offset;
port_byte_out(REG_SCREEN_CTRL, 14); port_byte_out(REG_SCREEN_CTRL, 14);
int offset = port_byte_in(REG_SCREEN_DATA) << 8; /* High byte: << 8 */ offset = port_byte_in(REG_SCREEN_DATA) << 8; /* High byte: << 8 */
port_byte_out(REG_SCREEN_CTRL, 15); port_byte_out(REG_SCREEN_CTRL, 15);
offset += port_byte_in(REG_SCREEN_DATA); offset += port_byte_in(REG_SCREEN_DATA);
return offset * 2; /* Position * size of character cell */ return offset * 2; /* Position * size of character cell */

@ -9,24 +9,25 @@ void kernel_main() {
isr_install(); isr_install();
irq_install(); irq_install();
asm("int $2"); __asm__ volatile("int $2");
asm("int $3"); __asm__ volatile("int $3");
kprint("Type something, it will go through the kernel\n" kprint("Type something, it will go through the kernel\n"
"Type END to halt the CPU or PAGE to request a kmalloc()\n> "); "Type END to halt the CPU or PAGE to request a kmalloc()\n> ");
} }
void user_input(char *input) { void user_input(char *input) {
char page_str[16] = "";
char phys_str[16] = "";
uint32_t phys_addr;
uint32_t page;
if (strcmp(input, "END") == 0) { if (strcmp(input, "END") == 0) {
kprint("Stopping the CPU. Bye!\n"); kprint("Stopping the CPU. Bye!\n");
asm volatile("hlt"); __asm__ volatile("hlt");
} else if (strcmp(input, "PAGE") == 0) { } else if (strcmp(input, "PAGE") == 0) {
/* Lesson 22: Code to test kmalloc, the rest is unchanged */ /* Lesson 22: Code to test kmalloc, the rest is unchanged */
uint32_t phys_addr; page = kmalloc(1000, 1, &phys_addr);
uint32_t page = kmalloc(1000, 1, &phys_addr);
char page_str[16] = "";
hex_to_ascii(page, page_str); hex_to_ascii(page, page_str);
char phys_str[16] = "";
hex_to_ascii(phys_addr, phys_str); hex_to_ascii(phys_addr, phys_str);
kprint("Page: "); kprint("Page: ");
kprint(page_str); kprint(page_str);

@ -19,6 +19,7 @@ uint32_t free_mem_addr = 0x10000;
/* Implementation is just a pointer to some free memory which /* Implementation is just a pointer to some free memory which
* keeps growing */ * keeps growing */
uint32_t kmalloc(size_t size, int align, uint32_t *phys_addr) { uint32_t kmalloc(size_t size, int align, uint32_t *phys_addr) {
uint32_t ret;
/* Pages are aligned to 4K, or 0x1000 */ /* Pages are aligned to 4K, or 0x1000 */
if (align == 1 && (free_mem_addr & 0xFFFFF000)) { if (align == 1 && (free_mem_addr & 0xFFFFF000)) {
free_mem_addr &= 0xFFFFF000; free_mem_addr &= 0xFFFFF000;
@ -27,7 +28,7 @@ uint32_t kmalloc(size_t size, int align, uint32_t *phys_addr) {
/* Save also the physical address */ /* Save also the physical address */
if (phys_addr) *phys_addr = free_mem_addr; if (phys_addr) *phys_addr = free_mem_addr;
uint32_t ret = free_mem_addr; ret = free_mem_addr;
free_mem_addr += size; /* Remember to increment the pointer */ free_mem_addr += size; /* Remember to increment the pointer */
return ret; return ret;
} }

@ -19,12 +19,12 @@ void int_to_ascii(int n, char str[]) {
} }
void hex_to_ascii(int n, char str[]) { void hex_to_ascii(int n, char str[]) {
append(str, '0');
append(str, 'x');
char zeros = 0; char zeros = 0;
int32_t tmp; int32_t tmp;
int i; int i;
append(str, '0');
append(str, 'x');
for (i = 28; i > 0; i -= 4) { for (i = 28; i > 0; i -= 4) {
tmp = (n >> i) & 0xF; tmp = (n >> i) & 0xF;
if (tmp == 0 && zeros == 0) continue; if (tmp == 0 && zeros == 0) continue;

Loading…
Cancel
Save