Compare commits

...

14 commits

15 changed files with 521 additions and 198 deletions

4
.gdbinit Normal file
View file

@ -0,0 +1,4 @@
file build/boot/sys/core
target remote :3117
b _start
c

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
config.mk
build/
drive.img
/compile_commands.json
/opt

View file

@ -2,6 +2,8 @@
include config.mk
CFLAGS += -ggdb
# Kernel sources which are specific to the x86_64 architecture.
# Add new source files (C or Assembler) here,
# preferentially in alphabetical order.
@ -16,7 +18,6 @@ KERNEL_SOURCES_x86_64 := \
# preferentially in alphabetical order.
KERNEL_SOURCES := \
src/kernel.c \
src/output.c \
src/pci.c \
src/tar.c \
src/std.c \

3
debug-run-qemu.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
qemu-system-x86_64 -drive if=ide,format=raw,file=build/disk.img -drive if=virtio,media=disk,format=raw,file=drive.img "$@" -S -gdb tcp::3117

View file

@ -1,17 +0,0 @@
#ifndef KARLOS_OUTPUT_H
#define KARLOS_OUTPUT_H
#include <stdbool.h>
#include <stdint.h>
void putc(char c);
void puts(const char *s);
void println(const char *s);
__attribute__((noreturn))
void panic(const char *msg);
void assert(bool cond, const char *msg);
void print_u8x(uint8_t value);
void print_u16x(uint16_t value);
void print_u32x(uint32_t value);
#endif

View file

@ -1,6 +1,8 @@
#ifndef KARLOS_PCI_H
#define KARLOS_PCI_H
#include <stdint.h>
uint16_t pci_bdf_make(uint8_t bus, uint8_t dev, uint8_t fun);
uint32_t pci_config_read_u32(uint16_t bdf, uint8_t offset);
uint16_t pci_config_read_u16(uint16_t bdf, uint8_t offset);
@ -9,14 +11,14 @@ void pci_config_write_u32(uint16_t bdf, uint8_t offset, uint32_t value);
struct pci_bar_desc {
#define PCI_BAR_TYPE_MEM 0
#define PCI_BAR_TYPE_IO 1
uint8_t type;
uint8_t type;
#define PCI_BAR_LOCATABLE_32 0
#define PCI_BAR_LOCATABLE_SMALL 1
#define PCI_BAR_LOCATABLE_64 2
uint8_t locatable;
uint8_t prefetchable;
uint32_t address;
uint32_t length;
uint8_t locatable;
uint8_t prefetchable;
uint32_t address;
uint32_t length;
};
struct pci_bar_desc pci_bar_desc_read(uint16_t bdf, uint8_t barnum);

View file

@ -2,8 +2,52 @@
#define KARLOS_STD_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
// Memory functions
void *memset(void *ptr, int value, size_t num);
void *memcpy(void *dest, const void *src, size_t n);
int memcmp(const void *ptr, const void *ptr2, size_t num);
void *memmove(void *dest, const void *src, size_t num);
// String functions
unsigned int strlen(const char *s);
bool streq(const char *a, const char *b);
void memcpy(void *dst, const void *src, unsigned int n);
bool strcontains(const char *s, char c);
#endif
// Low-level output functions
void putc(char c);
void putln(void);
void puts(const char *s);
void putsln(const char *s);
void put_charbuf(const char *buf, unsigned int len);
void putu8x(uint8_t value);
void putu16x(uint16_t value);
void putu32x(uint32_t value);
void putu64x(uint64_t value);
// String and conversion utilities
void itoa(int value, unsigned int base, char *buffer);
void utoa(unsigned int value, unsigned int base, char *buffer);
void itoa_ll(long long value, unsigned int base, char *buffer);
void utoa_ll(unsigned long long value, unsigned int base, char *buffer);
unsigned int toa_buf_size(unsigned int bits, unsigned int base);
// Formatted output
void printf(const char *format, ...);
// Debug helpers
#define PANIC(msg) panic(__FILE__, __LINE__, msg)
#define ASSERT(cond) do {\
if (!(cond)) {\
PANIC("assertion failed: " #cond);\
}\
} while (0)
#define TODO() PANIC("not implemented")
#define UNREACHABLE() PANIC("unreachable")
// don't use this directly, use the macros above
__attribute__ ((noreturn))
void panic(const char *file, unsigned int line, const char *msg);
#endif // KARLOS_UTILITY_H

View file

@ -28,26 +28,27 @@
#include <stdbool.h>
#include <stdint.h>
#include "bootboot.h"
#include "output.h"
#include "x86_64/mem.h"
#include "x86_64/asm.h"
#include "bootboot.h"
#include "pci.h"
#include "std.h"
#include "tar.h"
/* imported virtual addresses, see linker script */
extern BOOTBOOT bootboot; // see bootboot.h
extern BOOTBOOT bootboot; // see bootboot.h
extern unsigned char environment[4096]; // configuration, UTF-8 text key=value pairs
extern uint8_t fb; // linear framebuffer mapped
void print_virtio_blk_bars() {
uint16_t bdf;
if (pci_search(0x1AF4, 0x1001, &bdf) && pci_search(0x1AF4, 0x1042, &bdf)) {
panic("couldn't find virtio_blk device!");
PANIC("couldn't find virtio_blk device!");
}
puts("found virtio_blk device at bdf ");
print_u16x(bdf);
println(".");
putu16x(bdf);
printf(".\n");
// read BARs
for (int i = 0; i < 6; i++) {
struct pci_bar_desc desc = pci_bar_desc_read(bdf, i);
@ -56,65 +57,77 @@ void print_virtio_blk_bars() {
}
void check_initrd() {
println("");
putln();
uint64_t printed_in_line = 0;
for (uint64_t off = 0; off < bootboot.initrd_size; off++) {
uint8_t byte = ((uint8_t*)bootboot.initrd_ptr)[off];
print_u8x(byte);
putu8x(byte);
putc(' ');
if (++printed_in_line % 32 == 0) {
printed_in_line = 0;
println("");
putln();
}
}
println("");
putln();
}
/******************************************
* Entry point, called by BOOTBOOT Loader *
******************************************/
void _start()
{
void _start() {
/*** NOTE: this code runs on all cores in parallel ***/
int x, y, s=bootboot.fb_scanline, w=bootboot.fb_width, h=bootboot.fb_height;
int x, y, s = bootboot.fb_scanline, w = bootboot.fb_width, h = bootboot.fb_height;
if(s) {
if (s) {
// cross-hair to see screen dimension detected correctly
for(y=0;y<h;y++) { *((uint32_t*)(&fb + s*y + (w*2)))=0x00FFFFFF; }
for(x=0;x<w;x++) { *((uint32_t*)(&fb + s*(h/2)+x*4))=0x00FFFFFF; }
for (y = 0; y < h; y++) {
*((uint32_t *)(&fb + s * y + (w * 2))) = 0x000FFFFF;
}
for (x = 0; x < w; x++) {
*((uint32_t *)(&fb + s * (h / 2) + x * 4)) = 0x00FFFFFF;
}
// red, green, blue boxes in order
for(y=0;y<20;y++) { for(x=0;x<20;x++) { *((uint32_t*)(&fb + s*(y+20) + (x+20)*4))=0x00FF0000; } }
for(y=0;y<20;y++) { for(x=0;x<20;x++) { *((uint32_t*)(&fb + s*(y+20) + (x+50)*4))=0x0000FF00; } }
for(y=0;y<20;y++) { for(x=0;x<20;x++) { *((uint32_t*)(&fb + s*(y+20) + (x+80)*4))=0x000000FF; } }
// say hello
println("Hello from a simple BOOTBOOT kernel");
for (y = 0; y < 20; y++) {
for (x = 0; x < 20; x++) {
*((uint32_t *)(&fb + s * (y + 20) + (x + 20) * 4)) = 0x00FF0000;
}
}
for (y = 0; y < 20; y++) {
for (x = 0; x < 20; x++) {
*((uint32_t *)(&fb + s * (y + 20) + (x + 50) * 4)) = 0x0000FF00;
}
}
for (y = 0; y < 20; y++) {
for (x = 0; x < 20; x++) {
*((uint32_t *)(&fb + s * (y + 20) + (x + 80) * 4)) = 0x000000FF;
}
}
}
// memory stuff
init_gdt();
init_idt();
println("Test after init");
printf("Test after init\n");
// __asm__("int $0x80" :: );
struct tar_header hd;
int res = tar_get_file("hello.txt", &hd);
assert(res == 1, "file not found");
println(hd.name);
print_u32x(hd.size);
println("");
ASSERT(res == 1);
puts(hd.name);
putu32x(hd.size);
putln();
for (uint64_t i = 0; i < hd.size; i++) {
putc(((char *)hd.data)[i]);
}
println("");
putln();
// hang for now
panic("end of kernel");
PANIC("end of kernel");
}
/**************************
@ -131,4 +144,5 @@ typedef struct {
uint32_t width;
uint8_t glyphs;
} __attribute__((packed)) psf2_t;
extern volatile unsigned char _binary_font_psf_start;

View file

@ -1,61 +0,0 @@
#include "x86_64/uart.h"
#include "output.h"
void putc(char c) {
uart_write_char(c);
}
void puts(const char *s) {
for (const char *c = s; *c != '\0'; c++) {
uart_write_char(*c);
}
}
void println(const char *s) {
puts(s);
puts("\r\n");
}
__attribute__((noreturn))
void panic(const char *msg) {
puts("PANIC: ");
println(msg);
// hang for now
while (1);
}
void assert(bool cond, const char *msg) {
if (!cond) {
panic(msg);
}
}
#define TO_HEX(n) (((n) < 10) ? '0' + (n) : 'a' + (n) - 10)
void print_u8x(uint8_t value) {
putc('0');
putc('x');
putc(TO_HEX((value >> 4) & 0xf));
putc(TO_HEX(value & 0xf));
}
void print_u16x(uint16_t value) {
putc('0');
putc('x');
for (int i = 0; i < 4; i++) {
// 12 8 4 0
uint8_t hexval = (value >> ((3 - i) << 2)) & 0xf;
putc(TO_HEX(hexval));
}
}
void print_u32x(uint32_t value) {
putc('0');
putc('x');
for (int i = 0; i < 8; i++) {
uint8_t hexval = (value >> ((7 - i) << 2)) & 0xf;
putc(TO_HEX(hexval));
}
}

View file

@ -1,21 +1,18 @@
#include "output.h"
#include "pci.h"
#include "x86_64/asm.h"
#include "std.h"
#define PCI_CONFIG_ADDR_PORT 0xCF8
#define PCI_CONFIG_DATA_PORT 0xCFC
uint16_t pci_bdf_make(uint8_t bus, uint8_t dev, uint8_t fun) {
if (dev >= 32 || fun >= 8) {
panic("pci_bdf_make");
}
ASSERT(dev < 32 && fun < 8);
return ((uint16_t)bus << 8) | ((uint16_t)dev << 3) | (uint16_t)fun;
}
static uint32_t pci_address(uint16_t bdf, uint8_t offset) {
return ((uint32_t)bdf << 8)
| ((uint32_t)offset & 0xfc)
| ((uint32_t)0x80000000);
return ((uint32_t)bdf << 8) | ((uint32_t)offset & 0xfc) | ((uint32_t)0x80000000);
}
uint32_t pci_config_read_u32(uint16_t bdf, uint8_t offset) {
@ -34,29 +31,25 @@ void pci_config_write_u32(uint16_t bdf, uint8_t offset, uint32_t value) {
}
struct pci_bar_desc pci_bar_desc_read(uint16_t bdf, uint8_t barnum) {
if (barnum >= 6) {
panic("pci_config_read_bar");
}
ASSERT(barnum < 6);
// get basic information
// https://en.wikipedia.org/wiki/PCI_configuration_space
// get basic information
// https://en.wikipedia.org/wiki/PCI_configuration_space
uint8_t offset = 0x10 + (barnum << 2);
uint32_t bar = pci_config_read_u32(bdf, offset);
struct pci_bar_desc desc;
desc.type = bar & 0x1;
if (desc.type == PCI_BAR_TYPE_MEM) {
desc.locatable = (bar >> 1) & 0x3;
if (desc.locatable == 3) {
panic("pci_config_read_bar");
}
ASSERT(desc.locatable != 3);
desc.prefetchable = (bar >> 3) & 0x1;
desc.address = bar & 0xfffffff0;
} else {
desc.address = bar & 0xfffffffc;
}
// get length
// https://stackoverflow.com/questions/19006632/how-is-a-pci-pcie-bar-size-determined
// get length
// https://stackoverflow.com/questions/19006632/how-is-a-pci-pcie-bar-size-determined
pci_config_write_u32(bdf, offset, 0xffffffff);
bar = pci_config_read_u32(bdf, offset);
desc.length = (~(bar & 0xfffffff0)) + 1;
@ -65,34 +58,26 @@ struct pci_bar_desc pci_bar_desc_read(uint16_t bdf, uint8_t barnum) {
}
void pci_bar_desc_print(const struct pci_bar_desc *desc) {
println("pci_bar_desc {");
printf("pci_bar_desc {\n");
if (desc->type == PCI_BAR_TYPE_MEM) {
println(" type = MEM");
printf(" type = MEM\n");
if (desc->locatable == PCI_BAR_LOCATABLE_32) {
println(" locatable = 32");
printf(" locatable = 32\n");
} else if (desc->locatable == PCI_BAR_LOCATABLE_SMALL) {
println(" locatable = SMALL");
printf(" locatable = SMALL\n");
} else {
println(" locatable = 64");
printf(" locatable = 64\n");
}
puts(" prefetchable = ");
println(desc->prefetchable ? "true" : "false");
puts(" address = ");
print_u32x(desc->address);
println("");
puts(" length = ");
print_u32x(desc->length);
println("");
printf(" prefetchable = %s\n", desc->prefetchable ? "true" : "false");
printf(" address = %u\n", desc->address);
printf(" length = %u\n", desc->length);
} else {
println(" type = IO");
puts(" address = ");
print_u32x(desc->address);
println("");
puts(" length = ");
print_u32x(desc->length);
println("");
printf(" type = IO\n");
printf(" address = %u\n", desc->address);
printf(" length = %u\n", desc->length);
}
println("}");
printf("}\n");
}
int pci_search(uint16_t vendor_id, uint16_t device_id, uint16_t *found_out) {

355
src/std.c Normal file
View file

@ -0,0 +1,355 @@
#include <stdarg.h>
#include <stddef.h>
#include "std.h"
#include "x86_64/uart.h"
#define BUFFER_SIZE 1024
/* --- Memory Functions --- */
void *memset(void *ptr, int value, size_t num) {
unsigned char *byte_ptr = (unsigned char *)ptr;
for (size_t i = 0; i < num; i++) {
byte_ptr[i] = (unsigned char)value;
}
return ptr;
}
void *memcpy(void *dest, const void *src, size_t n) {
unsigned char *d = (unsigned char *)dest;
const unsigned char *s = (const unsigned char *)src;
for (size_t i = 0; i < n; i++) {
d[i] = s[i];
}
return dest;
}
int memcmp(const void *ptr, const void *ptr2, size_t num) {
unsigned char *d = (unsigned char *)ptr;
unsigned char *b = (unsigned char *)ptr2;
for (size_t i = 0; i < num; i++) {
if (d[i] != b[i]) {
return (d[i] - b[i]);
}
}
return 0;
}
void *memmove(void *dest, const void *src, size_t num) {
unsigned char *d = (unsigned char *)dest;
const unsigned char *s = (const unsigned char *)src;
if (d < s || d >= (s + num)) {
for (size_t i = 0; i < num; i++) {
d[i] = s[i];
}
} else {
for (size_t i = num; i > 0; i--) {
d[i - 1] = s[i - 1];
}
}
return dest;
}
/* --- String functions --- */
unsigned int strlen(const char *s) {
unsigned int len = 0;
while (*s != '\0') {
s++;
len++;
}
return len;
}
bool streq(const char *a, const char *b) {
while (*a != '\0' && *b != '\0') {
if (*a != *b) {
return false;
}
a++;
b++;
}
// must have same length
return *a == '\0' && *b == '\0';
}
bool strcontains(const char *s, char c) {
while (*s != '\0') {
if (*s++ == c) {
return true;
}
}
return false;
}
/* --- Line buffering --- */
// DO NOT USE THESE FUNCTIONS ANYWHERE! USE THE PUBLIC API (EVEN IN THIS FILE)!
static char linebuf[BUFFER_SIZE];
static unsigned int current_buffer_position = 0;
static void linebuf_flush(void) {
for (unsigned int i = 0; i < current_buffer_position; i++) {
uart_write_char(linebuf[i]);
}
current_buffer_position = 0;
}
static void linebuf_putc(char c) {
if (current_buffer_position == BUFFER_SIZE) {
linebuf_flush();
}
linebuf[current_buffer_position++] = c;
}
/* --- Low-level output functions --- */
void putc(char c) {
if (c == '\n') {
linebuf_putc('\r');
linebuf_putc('\n');
linebuf_flush();
} else {
linebuf_putc(c);
}
}
void putln(void) {
putc('\n');
}
void puts(const char *s) {
while (*s != '\0') {
putc(*s++);
}
}
void putsln(const char *s) {
puts(s);
putln();
}
void put_charbuf(const char *buf, unsigned int len) {
for (unsigned int i = 0; i < len; i++) {
putc(buf[i]);
}
}
#define TO_HEX(n) ((n) < 10 ? (n) + '0' : (n) - 10 + 'a')
#define PUTUXX(nd) \
do { \
putc('0'); \
putc('x'); \
for (int i = 0; i < nd; i++) { \
uint8_t hexval = (value >> ((((nd) - 1) - i) << 2)) & 0xf; \
putc(TO_HEX(hexval)); \
} \
} while (0)
void putu8x(uint8_t value) {
PUTUXX(2);
}
void putu16x(uint16_t value) {
PUTUXX(4);
}
void putu32x(uint32_t value) {
PUTUXX(8);
}
void putu64x(uint64_t value) {
PUTUXX(16);
}
/* --- Number Conversion Functions --- */
// this does not include null byte
#define TOA_MAX_BUF_SIZE 64
/* Converts an int value to a string in a given base */
void itoa(int value, unsigned int base, char *buffer) {
itoa_ll(value, base, buffer);
}
/* Converts an unsigned int value to a string in a given base */
void utoa(unsigned int value, unsigned int base, char *buffer) {
utoa_ll(value, base, buffer);
}
/* Converts a long long value to a string in a given base */
void itoa_ll(long long value, unsigned int base, char *buffer) {
bool is_negative = false;
unsigned long long uvalue;
if (base == 10 && value < 0) {
is_negative = true;
uvalue = -value;
} else {
uvalue = value;
}
if (is_negative) {
buffer[0] = '-';
utoa_ll(uvalue, base, buffer + 1);
} else {
utoa_ll(uvalue, base, buffer);
}
}
/* Converts an unsigned long long value to a string in a given base */
void utoa_ll(unsigned long long value, unsigned int base, char *buffer) {
char temp[TOA_MAX_BUF_SIZE];
int index = 0;
if (value == 0) {
temp[index++] = '0';
} else {
while (value > 0) {
unsigned int digit = value % base;
temp[index++] = "0123456789ABCDEF"[digit];
value /= base;
}
}
int out_index = 0;
for (int i = index - 1; i >= 0; i--) {
buffer[out_index++] = temp[i];
}
buffer[out_index] = '\0';
}
/* --- Helper Functions --- */
unsigned int toa_buf_size(unsigned int bits, unsigned int base) {
unsigned int sz;
if (base == 2) {
sz = bits; // Binary: 1 symbol per bit
} else if (base == 8) {
sz = (bits + 2) / 3; // Octal: 3 bits per digit
} else if (base == 16) {
sz = (bits + 3) / 4; // Hex: 4 bits per digit
} else if (base == 10) {
sz = (bits * 30103) / 100000 + 1; // Approximate log10(2) ≈ 0.30103
} else {
UNREACHABLE();
}
return sz + 1; // null byte inclusive
}
/* --- Custom printf Implementation --- */
#define IS_PRINTABLE(c) ((c) >= ' ' && (c) <= '~')
void printf(const char *format, ...) {
va_list args;
va_start(args, format);
while (*format) {
if (*format == '%') {
format++;
bool do_number = false;
int number_size_bits = 32;
char number_buffer[TOA_MAX_BUF_SIZE + 1];
char base;
bool sign;
// Check for length modifiers:
switch (*format) {
case 'h':
do_number = true;
number_size_bits = 16; // 16-bit (promoted to int in varargs)
format++;
break;
case 'l':
do_number = true;
number_size_bits = 64; // 64-bit
format++;
break;
default:
break;
}
if (do_number && !strcontains("duxob", *format)) {
PANIC("printf: expected number format specifier after %h or %l");
}
switch (*format) {
case 'd':
do_number = true;
base = 10;
sign = true;
break;
case 'u':
do_number = true;
base = 10;
sign = false;
break;
case 'x':
do_number = true;
base = 16;
sign = false;
break;
case 'o':
do_number = true;
base = 8;
sign = false;
case 'b':
do_number = true;
base = 2;
sign = false;
break;
case 'c': {
char ch = (char)va_arg(args, int);
putc(ch);
break;
}
case 's': {
char *str = va_arg(args, char *);
puts(str);
break;
}
case 'p': {
void *ptr = va_arg(args, void *);
putu64x((uint64_t)(intptr_t)ptr);
break;
}
case '%': {
putc('%');
break;
}
default: {
PANIC("printf: unsupported format specifier");
break;
}
}
if (do_number) {
if (number_size_bits == 64) {
long long value = va_arg(args, long long);
if (sign) {
itoa_ll(value, base, number_buffer);
} else {
utoa_ll((unsigned long long)value, base, number_buffer);
}
} else {
int value = va_arg(args, int);
if (sign) {
itoa(value, base, number_buffer);
} else {
utoa((unsigned int)value, base, number_buffer);
}
}
puts(number_buffer);
}
format++;
} else if (IS_PRINTABLE(*format) || *format == '\n') {
putc(*format);
format++;
} else {
// we disallow everything else for now (including \r, \t)
putc('[');
putu8x(*format);
putc(']');
format++;
}
}
va_end(args);
}
/* --- Debug helpers --- */
__attribute__((noreturn)) void panic(const char *file, unsigned int line, const char *msg) {
printf("PANIC@%s:%d: %s\n", file, line, msg);
while (1) {
// loop forever
}
}

View file

@ -1,7 +1,6 @@
#include "std.h"
#include "tar.h"
#include "bootboot.h"
#include "output.h"
extern BOOTBOOT bootboot; // see bootboot.h
@ -36,11 +35,8 @@ int tar_get_file(const char *name, struct tar_header *hd_out) {
struct tar_header hd;
find_begin:
if (hard_follow_count > 1) {
panic("tar error: hardlink points to hardlink?");
} else if (sym_follow_count == SYM_FOLLOW_CAP) {
panic("tar error: symlink chain too long");
}
ASSERT(hard_follow_count <= 1);
ASSERT(sym_follow_count < SYM_FOLLOW_CAP);
uint64_t p = bootboot.initrd_ptr;
while (p < end) {

View file

@ -1,31 +1,31 @@
#include "x86_64/asm.h"
uint8_t in8(int port) {
unsigned char value;
__asm__ ("inb %%dx" : "=a"(value) : "d"(port));
return value;
unsigned char value;
__asm__("inb %%dx" : "=a"(value) : "d"(port));
return value;
}
uint16_t in16(int port) {
uint16_t value;
__asm__ ("inw %%dx" : "=a"(value) : "d"(port));
return value;
uint16_t value;
__asm__("inw %%dx" : "=a"(value) : "d"(port));
return value;
}
uint32_t in32(int port) {
uint32_t value;
__asm__ ("inl %%dx" : "=a"(value) : "d"(port));
__asm__("inl %%dx" : "=a"(value) : "d"(port));
return value;
}
void out8(int port, uint8_t value) {
__asm__ ("outb %%dx" :: "d"(port), "a"(value));
__asm__("outb %%dx" ::"d"(port), "a"(value));
}
void out16(int port, uint16_t value) {
__asm__ ("outw %%dx" :: "d"(port), "a"(value));
__asm__("outw %%dx" ::"d"(port), "a"(value));
}
void out32(int port, uint32_t value) {
__asm__ ("outl %%dx" :: "d"(port), "a"(value));
__asm__("outl %%dx" ::"d"(port), "a"(value));
}

View file

@ -1,35 +1,30 @@
#include <stdint.h>
#include "output.h" // remove later, this is only for interrupt handler
#include "std.h" // remove later, this is only for interrupt handler
uint64_t gdt[3];
void write_segment_descriptor(uint64_t *entry, uint8_t dpl, uint8_t executable) {
uint8_t access_byte =
(1 << 7) // present bit
| (dpl << 5)
| (1 << 4) // S
| (executable << 3)
| (0 << 2) // DC
uint8_t access_byte = (1 << 7) // present bit
| (dpl << 5) | (1 << 4) // S
| (executable << 3) | (0 << 2) // DC
| (1 << 1) // RW
| (0 << 0) // A
;
;
uint8_t flags =
(1 << 3) // G
uint8_t flags = (1 << 3) // G
| (0 << 2) // DB
| (1 << 1) // L
| (0 << 0) // reserved
;
*entry =
0xffff // limit
;
*entry = 0xffff // limit
| ((uint64_t)0x0000 << 16) // base
| ((uint64_t)0x00 << 32) // base
| ((uint64_t)access_byte << 40) // access byte
| ((uint64_t)0xf << 48) // limit
| ((uint64_t)flags << 52) // flags
| ((uint64_t)0x00 << 56) // base
;
;
}
#define CODE_SEGMENT 1
@ -42,13 +37,13 @@ void init_gdt() {
uint8_t gdtr[10];
*(uint16_t*)gdtr = sizeof(gdt) - 1;
*(uint64_t**)(gdtr + 2) = (uint64_t*)gdt;
*(uint16_t *)gdtr = sizeof(gdt) - 1;
*(uint64_t **)(gdtr + 2) = (uint64_t *)gdt;
__asm__ ("lgdt (%0)" :: "r"(gdtr));
__asm__("lgdt (%0)" ::"r"(gdtr));
__asm__ ("mov %0, %%ds" :: "r"(DATA_SEGMENT << 3));
// TODO set code segment -> iret?
__asm__("mov %0, %%ds" ::"r"(DATA_SEGMENT << 3));
// TODO set code segment -> iret?
}
__attribute__ ((packed))
@ -88,7 +83,7 @@ void write_int_desc_entry(struct int_desc_entry *e, uint64_t offset) {
}
void basic_interrupt_handler(void) {
panic("Hello Interrupt!\n");
PANIC("Hello Interrupt!");
}
#define NUM_INTERRUPTS 256

View file

@ -2,13 +2,13 @@
#define COM1_BASE_PORT 0x3F8
void
uart_write_char(char c)
{
while (1) {
int line_status = in8(COM1_BASE_PORT + 5);
if (line_status & 0x20) break;
}
void uart_write_char(char c) {
while (1) {
int line_status = in8(COM1_BASE_PORT + 5);
if (line_status & 0x20) {
break;
}
}
out8(COM1_BASE_PORT, c);
out8(COM1_BASE_PORT, c);
}