Compare commits
14 commits
dea2d91cdd
...
5ac28f75ee
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ac28f75ee | |||
| 1844224924 | |||
| 0e730bf6ba | |||
| a32efe8e39 | |||
| 4032d153e0 | |||
| dc146741a4 | |||
| 683a125b0e | |||
| d834536e79 | |||
| 371ef3d571 | |||
| ea76c409c3 | |||
| dbcd40f3d7 | |||
| df294bc125 | |||
| 45a3549050 | |||
| 6a424beb6a |
15 changed files with 521 additions and 198 deletions
4
.gdbinit
Normal file
4
.gdbinit
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
file build/boot/sys/core
|
||||||
|
target remote :3117
|
||||||
|
b _start
|
||||||
|
c
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,3 +1,5 @@
|
||||||
config.mk
|
config.mk
|
||||||
build/
|
build/
|
||||||
drive.img
|
drive.img
|
||||||
|
/compile_commands.json
|
||||||
|
/opt
|
||||||
|
|
|
||||||
3
Makefile
3
Makefile
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
include config.mk
|
include config.mk
|
||||||
|
|
||||||
|
CFLAGS += -ggdb
|
||||||
|
|
||||||
# Kernel sources which are specific to the x86_64 architecture.
|
# Kernel sources which are specific to the x86_64 architecture.
|
||||||
# Add new source files (C or Assembler) here,
|
# Add new source files (C or Assembler) here,
|
||||||
# preferentially in alphabetical order.
|
# preferentially in alphabetical order.
|
||||||
|
|
@ -16,7 +18,6 @@ KERNEL_SOURCES_x86_64 := \
|
||||||
# preferentially in alphabetical order.
|
# preferentially in alphabetical order.
|
||||||
KERNEL_SOURCES := \
|
KERNEL_SOURCES := \
|
||||||
src/kernel.c \
|
src/kernel.c \
|
||||||
src/output.c \
|
|
||||||
src/pci.c \
|
src/pci.c \
|
||||||
src/tar.c \
|
src/tar.c \
|
||||||
src/std.c \
|
src/std.c \
|
||||||
|
|
|
||||||
3
debug-run-qemu.sh
Executable file
3
debug-run-qemu.sh
Executable 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
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef KARLOS_PCI_H
|
#ifndef KARLOS_PCI_H
|
||||||
#define KARLOS_PCI_H
|
#define KARLOS_PCI_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
uint16_t pci_bdf_make(uint8_t bus, uint8_t dev, uint8_t fun);
|
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);
|
uint32_t pci_config_read_u32(uint16_t bdf, uint8_t offset);
|
||||||
uint16_t pci_config_read_u16(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 {
|
struct pci_bar_desc {
|
||||||
#define PCI_BAR_TYPE_MEM 0
|
#define PCI_BAR_TYPE_MEM 0
|
||||||
#define PCI_BAR_TYPE_IO 1
|
#define PCI_BAR_TYPE_IO 1
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
#define PCI_BAR_LOCATABLE_32 0
|
#define PCI_BAR_LOCATABLE_32 0
|
||||||
#define PCI_BAR_LOCATABLE_SMALL 1
|
#define PCI_BAR_LOCATABLE_SMALL 1
|
||||||
#define PCI_BAR_LOCATABLE_64 2
|
#define PCI_BAR_LOCATABLE_64 2
|
||||||
uint8_t locatable;
|
uint8_t locatable;
|
||||||
uint8_t prefetchable;
|
uint8_t prefetchable;
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pci_bar_desc pci_bar_desc_read(uint16_t bdf, uint8_t barnum);
|
struct pci_bar_desc pci_bar_desc_read(uint16_t bdf, uint8_t barnum);
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,52 @@
|
||||||
#define KARLOS_STD_H
|
#define KARLOS_STD_H
|
||||||
|
|
||||||
#include <stdbool.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);
|
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
|
||||||
|
|
|
||||||
72
src/kernel.c
72
src/kernel.c
|
|
@ -28,26 +28,27 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "bootboot.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "x86_64/mem.h"
|
#include "x86_64/mem.h"
|
||||||
#include "x86_64/asm.h"
|
#include "x86_64/asm.h"
|
||||||
|
#include "bootboot.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
#include "std.h"
|
||||||
#include "tar.h"
|
#include "tar.h"
|
||||||
|
|
||||||
/* imported virtual addresses, see linker script */
|
/* 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 unsigned char environment[4096]; // configuration, UTF-8 text key=value pairs
|
||||||
extern uint8_t fb; // linear framebuffer mapped
|
extern uint8_t fb; // linear framebuffer mapped
|
||||||
|
|
||||||
void print_virtio_blk_bars() {
|
void print_virtio_blk_bars() {
|
||||||
uint16_t bdf;
|
uint16_t bdf;
|
||||||
if (pci_search(0x1AF4, 0x1001, &bdf) && pci_search(0x1AF4, 0x1042, &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 ");
|
puts("found virtio_blk device at bdf ");
|
||||||
print_u16x(bdf);
|
putu16x(bdf);
|
||||||
println(".");
|
printf(".\n");
|
||||||
// read BARs
|
// read BARs
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
struct pci_bar_desc desc = pci_bar_desc_read(bdf, i);
|
struct pci_bar_desc desc = pci_bar_desc_read(bdf, i);
|
||||||
|
|
@ -56,65 +57,77 @@ void print_virtio_blk_bars() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_initrd() {
|
void check_initrd() {
|
||||||
println("");
|
putln();
|
||||||
uint64_t printed_in_line = 0;
|
uint64_t printed_in_line = 0;
|
||||||
for (uint64_t off = 0; off < bootboot.initrd_size; off++) {
|
for (uint64_t off = 0; off < bootboot.initrd_size; off++) {
|
||||||
uint8_t byte = ((uint8_t*)bootboot.initrd_ptr)[off];
|
uint8_t byte = ((uint8_t*)bootboot.initrd_ptr)[off];
|
||||||
|
|
||||||
print_u8x(byte);
|
putu8x(byte);
|
||||||
putc(' ');
|
putc(' ');
|
||||||
|
|
||||||
if (++printed_in_line % 32 == 0) {
|
if (++printed_in_line % 32 == 0) {
|
||||||
printed_in_line = 0;
|
printed_in_line = 0;
|
||||||
println("");
|
putln();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println("");
|
putln();
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
* Entry point, called by BOOTBOOT Loader *
|
* Entry point, called by BOOTBOOT Loader *
|
||||||
******************************************/
|
******************************************/
|
||||||
void _start()
|
void _start() {
|
||||||
{
|
|
||||||
/*** NOTE: this code runs on all cores in parallel ***/
|
/*** 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
|
// cross-hair to see screen dimension detected correctly
|
||||||
for(y=0;y<h;y++) { *((uint32_t*)(&fb + s*y + (w*2)))=0x00FFFFFF; }
|
for (y = 0; y < h; y++) {
|
||||||
for(x=0;x<w;x++) { *((uint32_t*)(&fb + s*(h/2)+x*4))=0x00FFFFFF; }
|
*((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
|
// 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(y=0;y<20;y++) { for(x=0;x<20;x++) { *((uint32_t*)(&fb + s*(y+20) + (x+50)*4))=0x0000FF00; } }
|
for (x = 0; x < 20; x++) {
|
||||||
for(y=0;y<20;y++) { for(x=0;x<20;x++) { *((uint32_t*)(&fb + s*(y+20) + (x+80)*4))=0x000000FF; } }
|
*((uint32_t *)(&fb + s * (y + 20) + (x + 20) * 4)) = 0x00FF0000;
|
||||||
|
}
|
||||||
// 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 + 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
|
// memory stuff
|
||||||
init_gdt();
|
init_gdt();
|
||||||
init_idt();
|
init_idt();
|
||||||
|
|
||||||
println("Test after init");
|
printf("Test after init\n");
|
||||||
|
|
||||||
// __asm__("int $0x80" :: );
|
// __asm__("int $0x80" :: );
|
||||||
|
|
||||||
struct tar_header hd;
|
struct tar_header hd;
|
||||||
int res = tar_get_file("hello.txt", &hd);
|
int res = tar_get_file("hello.txt", &hd);
|
||||||
assert(res == 1, "file not found");
|
ASSERT(res == 1);
|
||||||
println(hd.name);
|
puts(hd.name);
|
||||||
print_u32x(hd.size);
|
putu32x(hd.size);
|
||||||
println("");
|
putln();
|
||||||
for (uint64_t i = 0; i < hd.size; i++) {
|
for (uint64_t i = 0; i < hd.size; i++) {
|
||||||
putc(((char *)hd.data)[i]);
|
putc(((char *)hd.data)[i]);
|
||||||
}
|
}
|
||||||
println("");
|
putln();
|
||||||
|
|
||||||
// hang for now
|
// hang for now
|
||||||
panic("end of kernel");
|
PANIC("end of kernel");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
|
|
@ -131,4 +144,5 @@ typedef struct {
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint8_t glyphs;
|
uint8_t glyphs;
|
||||||
} __attribute__((packed)) psf2_t;
|
} __attribute__((packed)) psf2_t;
|
||||||
|
|
||||||
extern volatile unsigned char _binary_font_psf_start;
|
extern volatile unsigned char _binary_font_psf_start;
|
||||||
|
|
|
||||||
61
src/output.c
61
src/output.c
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
61
src/pci.c
61
src/pci.c
|
|
@ -1,21 +1,18 @@
|
||||||
#include "output.h"
|
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
|
||||||
#include "x86_64/asm.h"
|
#include "x86_64/asm.h"
|
||||||
|
#include "std.h"
|
||||||
|
|
||||||
#define PCI_CONFIG_ADDR_PORT 0xCF8
|
#define PCI_CONFIG_ADDR_PORT 0xCF8
|
||||||
#define PCI_CONFIG_DATA_PORT 0xCFC
|
#define PCI_CONFIG_DATA_PORT 0xCFC
|
||||||
|
|
||||||
uint16_t pci_bdf_make(uint8_t bus, uint8_t dev, uint8_t fun) {
|
uint16_t pci_bdf_make(uint8_t bus, uint8_t dev, uint8_t fun) {
|
||||||
if (dev >= 32 || fun >= 8) {
|
ASSERT(dev < 32 && fun < 8);
|
||||||
panic("pci_bdf_make");
|
|
||||||
}
|
|
||||||
return ((uint16_t)bus << 8) | ((uint16_t)dev << 3) | (uint16_t)fun;
|
return ((uint16_t)bus << 8) | ((uint16_t)dev << 3) | (uint16_t)fun;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t pci_address(uint16_t bdf, uint8_t offset) {
|
static uint32_t pci_address(uint16_t bdf, uint8_t offset) {
|
||||||
return ((uint32_t)bdf << 8)
|
return ((uint32_t)bdf << 8) | ((uint32_t)offset & 0xfc) | ((uint32_t)0x80000000);
|
||||||
| ((uint32_t)offset & 0xfc)
|
|
||||||
| ((uint32_t)0x80000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pci_config_read_u32(uint16_t bdf, uint8_t offset) {
|
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) {
|
struct pci_bar_desc pci_bar_desc_read(uint16_t bdf, uint8_t barnum) {
|
||||||
if (barnum >= 6) {
|
ASSERT(barnum < 6);
|
||||||
panic("pci_config_read_bar");
|
|
||||||
}
|
|
||||||
|
|
||||||
// get basic information
|
// get basic information
|
||||||
// https://en.wikipedia.org/wiki/PCI_configuration_space
|
// https://en.wikipedia.org/wiki/PCI_configuration_space
|
||||||
uint8_t offset = 0x10 + (barnum << 2);
|
uint8_t offset = 0x10 + (barnum << 2);
|
||||||
uint32_t bar = pci_config_read_u32(bdf, offset);
|
uint32_t bar = pci_config_read_u32(bdf, offset);
|
||||||
struct pci_bar_desc desc;
|
struct pci_bar_desc desc;
|
||||||
desc.type = bar & 0x1;
|
desc.type = bar & 0x1;
|
||||||
if (desc.type == PCI_BAR_TYPE_MEM) {
|
if (desc.type == PCI_BAR_TYPE_MEM) {
|
||||||
desc.locatable = (bar >> 1) & 0x3;
|
desc.locatable = (bar >> 1) & 0x3;
|
||||||
if (desc.locatable == 3) {
|
ASSERT(desc.locatable != 3);
|
||||||
panic("pci_config_read_bar");
|
|
||||||
}
|
|
||||||
desc.prefetchable = (bar >> 3) & 0x1;
|
desc.prefetchable = (bar >> 3) & 0x1;
|
||||||
desc.address = bar & 0xfffffff0;
|
desc.address = bar & 0xfffffff0;
|
||||||
} else {
|
} else {
|
||||||
desc.address = bar & 0xfffffffc;
|
desc.address = bar & 0xfffffffc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get length
|
// get length
|
||||||
// https://stackoverflow.com/questions/19006632/how-is-a-pci-pcie-bar-size-determined
|
// https://stackoverflow.com/questions/19006632/how-is-a-pci-pcie-bar-size-determined
|
||||||
pci_config_write_u32(bdf, offset, 0xffffffff);
|
pci_config_write_u32(bdf, offset, 0xffffffff);
|
||||||
bar = pci_config_read_u32(bdf, offset);
|
bar = pci_config_read_u32(bdf, offset);
|
||||||
desc.length = (~(bar & 0xfffffff0)) + 1;
|
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) {
|
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) {
|
if (desc->type == PCI_BAR_TYPE_MEM) {
|
||||||
println(" type = MEM");
|
printf(" type = MEM\n");
|
||||||
if (desc->locatable == PCI_BAR_LOCATABLE_32) {
|
if (desc->locatable == PCI_BAR_LOCATABLE_32) {
|
||||||
println(" locatable = 32");
|
printf(" locatable = 32\n");
|
||||||
} else if (desc->locatable == PCI_BAR_LOCATABLE_SMALL) {
|
} else if (desc->locatable == PCI_BAR_LOCATABLE_SMALL) {
|
||||||
println(" locatable = SMALL");
|
printf(" locatable = SMALL\n");
|
||||||
} else {
|
} else {
|
||||||
println(" locatable = 64");
|
printf(" locatable = 64\n");
|
||||||
}
|
}
|
||||||
puts(" prefetchable = ");
|
printf(" prefetchable = %s\n", desc->prefetchable ? "true" : "false");
|
||||||
println(desc->prefetchable ? "true" : "false");
|
printf(" address = %u\n", desc->address);
|
||||||
puts(" address = ");
|
printf(" length = %u\n", desc->length);
|
||||||
print_u32x(desc->address);
|
|
||||||
println("");
|
|
||||||
puts(" length = ");
|
|
||||||
print_u32x(desc->length);
|
|
||||||
println("");
|
|
||||||
} else {
|
} else {
|
||||||
println(" type = IO");
|
printf(" type = IO\n");
|
||||||
puts(" address = ");
|
printf(" address = %u\n", desc->address);
|
||||||
print_u32x(desc->address);
|
printf(" length = %u\n", desc->length);
|
||||||
println("");
|
|
||||||
puts(" length = ");
|
|
||||||
print_u32x(desc->length);
|
|
||||||
println("");
|
|
||||||
}
|
}
|
||||||
println("}");
|
printf("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int pci_search(uint16_t vendor_id, uint16_t device_id, uint16_t *found_out) {
|
int pci_search(uint16_t vendor_id, uint16_t device_id, uint16_t *found_out) {
|
||||||
|
|
|
||||||
355
src/std.c
Normal file
355
src/std.c
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include "std.h"
|
#include "std.h"
|
||||||
#include "tar.h"
|
#include "tar.h"
|
||||||
#include "bootboot.h"
|
#include "bootboot.h"
|
||||||
#include "output.h"
|
|
||||||
|
|
||||||
extern BOOTBOOT bootboot; // see bootboot.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;
|
struct tar_header hd;
|
||||||
|
|
||||||
find_begin:
|
find_begin:
|
||||||
if (hard_follow_count > 1) {
|
ASSERT(hard_follow_count <= 1);
|
||||||
panic("tar error: hardlink points to hardlink?");
|
ASSERT(sym_follow_count < SYM_FOLLOW_CAP);
|
||||||
} else if (sym_follow_count == SYM_FOLLOW_CAP) {
|
|
||||||
panic("tar error: symlink chain too long");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t p = bootboot.initrd_ptr;
|
uint64_t p = bootboot.initrd_ptr;
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,31 @@
|
||||||
#include "x86_64/asm.h"
|
#include "x86_64/asm.h"
|
||||||
|
|
||||||
uint8_t in8(int port) {
|
uint8_t in8(int port) {
|
||||||
unsigned char value;
|
unsigned char value;
|
||||||
__asm__ ("inb %%dx" : "=a"(value) : "d"(port));
|
__asm__("inb %%dx" : "=a"(value) : "d"(port));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t in16(int port) {
|
uint16_t in16(int port) {
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
__asm__ ("inw %%dx" : "=a"(value) : "d"(port));
|
__asm__("inw %%dx" : "=a"(value) : "d"(port));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t in32(int port) {
|
uint32_t in32(int port) {
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
__asm__ ("inl %%dx" : "=a"(value) : "d"(port));
|
__asm__("inl %%dx" : "=a"(value) : "d"(port));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void out8(int port, uint8_t 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) {
|
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) {
|
void out32(int port, uint32_t value) {
|
||||||
__asm__ ("outl %%dx" :: "d"(port), "a"(value));
|
__asm__("outl %%dx" ::"d"(port), "a"(value));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,30 @@
|
||||||
#include <stdint.h>
|
#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];
|
uint64_t gdt[3];
|
||||||
|
|
||||||
void write_segment_descriptor(uint64_t *entry, uint8_t dpl, uint8_t executable) {
|
void write_segment_descriptor(uint64_t *entry, uint8_t dpl, uint8_t executable) {
|
||||||
uint8_t access_byte =
|
uint8_t access_byte = (1 << 7) // present bit
|
||||||
(1 << 7) // present bit
|
| (dpl << 5) | (1 << 4) // S
|
||||||
| (dpl << 5)
|
| (executable << 3) | (0 << 2) // DC
|
||||||
| (1 << 4) // S
|
|
||||||
| (executable << 3)
|
|
||||||
| (0 << 2) // DC
|
|
||||||
| (1 << 1) // RW
|
| (1 << 1) // RW
|
||||||
| (0 << 0) // A
|
| (0 << 0) // A
|
||||||
;
|
;
|
||||||
|
|
||||||
uint8_t flags =
|
uint8_t flags = (1 << 3) // G
|
||||||
(1 << 3) // G
|
|
||||||
| (0 << 2) // DB
|
| (0 << 2) // DB
|
||||||
| (1 << 1) // L
|
| (1 << 1) // L
|
||||||
| (0 << 0) // reserved
|
| (0 << 0) // reserved
|
||||||
;
|
;
|
||||||
|
|
||||||
*entry =
|
*entry = 0xffff // limit
|
||||||
0xffff // limit
|
|
||||||
| ((uint64_t)0x0000 << 16) // base
|
| ((uint64_t)0x0000 << 16) // base
|
||||||
| ((uint64_t)0x00 << 32) // base
|
| ((uint64_t)0x00 << 32) // base
|
||||||
| ((uint64_t)access_byte << 40) // access byte
|
| ((uint64_t)access_byte << 40) // access byte
|
||||||
| ((uint64_t)0xf << 48) // limit
|
| ((uint64_t)0xf << 48) // limit
|
||||||
| ((uint64_t)flags << 52) // flags
|
| ((uint64_t)flags << 52) // flags
|
||||||
| ((uint64_t)0x00 << 56) // base
|
| ((uint64_t)0x00 << 56) // base
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CODE_SEGMENT 1
|
#define CODE_SEGMENT 1
|
||||||
|
|
@ -42,13 +37,13 @@ void init_gdt() {
|
||||||
|
|
||||||
uint8_t gdtr[10];
|
uint8_t gdtr[10];
|
||||||
|
|
||||||
*(uint16_t*)gdtr = sizeof(gdt) - 1;
|
*(uint16_t *)gdtr = sizeof(gdt) - 1;
|
||||||
*(uint64_t**)(gdtr + 2) = (uint64_t*)gdt;
|
*(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));
|
__asm__("mov %0, %%ds" ::"r"(DATA_SEGMENT << 3));
|
||||||
// TODO set code segment -> iret?
|
// TODO set code segment -> iret?
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((packed))
|
__attribute__ ((packed))
|
||||||
|
|
@ -88,7 +83,7 @@ void write_int_desc_entry(struct int_desc_entry *e, uint64_t offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_interrupt_handler(void) {
|
void basic_interrupt_handler(void) {
|
||||||
panic("Hello Interrupt!\n");
|
PANIC("Hello Interrupt!");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NUM_INTERRUPTS 256
|
#define NUM_INTERRUPTS 256
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
#define COM1_BASE_PORT 0x3F8
|
#define COM1_BASE_PORT 0x3F8
|
||||||
|
|
||||||
void
|
void uart_write_char(char c) {
|
||||||
uart_write_char(char c)
|
while (1) {
|
||||||
{
|
int line_status = in8(COM1_BASE_PORT + 5);
|
||||||
while (1) {
|
if (line_status & 0x20) {
|
||||||
int line_status = in8(COM1_BASE_PORT + 5);
|
break;
|
||||||
if (line_status & 0x20) break;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out8(COM1_BASE_PORT, c);
|
out8(COM1_BASE_PORT, c);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue