Formating tweaks overall
This commit is contained in:
parent
8dd5e81399
commit
ba85d9337d
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -10,6 +10,6 @@
|
|||||||
"**/*.d": true,
|
"**/*.d": true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"C_Cpp.default.includePath": ["src/kernel/include"],
|
"C_Cpp.default.includePath": ["src/kernel/include", "sysroot/usr/include"],
|
||||||
"C_Cpp.default.cStandard": "c2x",
|
"C_Cpp.default.cStandard": "c17",
|
||||||
}
|
}
|
@ -9,42 +9,51 @@ extern gfx_context kernel_fb;
|
|||||||
int *position = (void *)0x20000;
|
int *position = (void *)0x20000;
|
||||||
|
|
||||||
void thread1() {
|
void thread1() {
|
||||||
int a = 1;
|
int a = 1;
|
||||||
gfx_context *ctx = framebuffer_make_subcontext(&kernel_fb, 700, 300, 100, 100);
|
gfx_context *ctx =
|
||||||
while(1) {
|
framebuffer_make_subcontext(&kernel_fb, 700, 300, 100, 100);
|
||||||
putCharacter(term_fb, *position, *position, RGB(255,255,0), RGB(0,0,0), '0'+(a++%10));
|
while(1) {
|
||||||
flip(term_fb);
|
putCharacter(term_fb,
|
||||||
draw_line(ctx, 0, 100, 50, ((a-1)%100), RGB(0,0,0));
|
*position, *position,
|
||||||
draw_line(ctx, 0, 100, 50, (a%100), RGB(255,0,0));
|
RGB(255,255,0), RGB(0,0,0),
|
||||||
flip(ctx);
|
'0'+(a++%10)
|
||||||
sched_yield();
|
);
|
||||||
}
|
flip(term_fb);
|
||||||
|
draw_line(ctx, 0, 100, 50, ((a-1)%100), RGB(0,0,0));
|
||||||
|
draw_line(ctx, 0, 100, 50, (a%100), RGB(255,0,0));
|
||||||
|
flip(ctx);
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread2() {
|
void thread2() {
|
||||||
int a = 0;
|
int a = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
putCharacter(term_fb, *position, *position, RGB(0,255,255), RGB(0,0,0), 'A'+(a++%10));
|
putCharacter(term_fb,
|
||||||
flip(term_fb);
|
*position, *position,
|
||||||
sched_yield();
|
RGB(0,255,255), RGB(0,0,0),
|
||||||
}
|
'A'+(a++%10)
|
||||||
|
);
|
||||||
|
flip(term_fb);
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TEMP_test_scheduler() {
|
void TEMP_test_scheduler() {
|
||||||
struct process *th1 = new_process(thread1);
|
struct process *th1 = new_process(thread1);
|
||||||
scheduler_insert(th1);
|
scheduler_insert(th1);
|
||||||
|
|
||||||
struct process *th2 = new_process(thread2);
|
struct process *th2 = new_process(thread2);
|
||||||
scheduler_insert(th2);
|
scheduler_insert(th2);
|
||||||
|
|
||||||
uint64_t p1 = pmm_alloc();
|
uint64_t p1 = pmm_alloc();
|
||||||
uint64_t p2 = pmm_alloc();
|
uint64_t p2 = pmm_alloc();
|
||||||
vmm_set_page(th1->P4, 0x20000, p1, PAGE_PRESENT);
|
vmm_set_page(th1->P4, 0x20000, p1, PAGE_PRESENT);
|
||||||
vmm_set_page(th2->P4, 0x20000, p2, PAGE_PRESENT);
|
vmm_set_page(th2->P4, 0x20000, p2, PAGE_PRESENT);
|
||||||
// Write different values into the position variable for the two processes
|
// Write different values into the position variable for the two processes
|
||||||
int *a = P2V(p1);
|
int *a = P2V(p1);
|
||||||
*a = 20;
|
*a = 20;
|
||||||
a = P2V(p2);
|
a = P2V(p2);
|
||||||
*a = 70;
|
*a = 70;
|
||||||
}
|
}
|
@ -15,45 +15,46 @@ struct kernel_boot_data_st kernel_boot_data;
|
|||||||
|
|
||||||
registers *kbd_handler(registers *r)
|
registers *kbd_handler(registers *r)
|
||||||
{
|
{
|
||||||
while(inb(0x64) & 0x2);
|
while(inb(0x64) & 0x2);
|
||||||
uint8_t scancode = inb(0x60);
|
uint8_t scancode = inb(0x60);
|
||||||
debug("Keyboard: %x\n", scancode);
|
debug("Keyboard: %x\n", scancode);
|
||||||
irq_ack();
|
irq_ack();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kmain(uint64_t multiboot_magic, void *multiboot_data) {
|
void kmain(uint64_t multiboot_magic, void *multiboot_data) {
|
||||||
musl_init();
|
musl_init();
|
||||||
debug_info("Started kernel\n");
|
debug_info("Started kernel\n");
|
||||||
multiboot_init(multiboot_magic, P2V(multiboot_data));
|
multiboot_init(multiboot_magic, P2V(multiboot_data));
|
||||||
debug_info("Kernel loaded with command line: \"%s\" by <%s>\n",
|
debug_info("Kernel loaded with command line: \"%s\" by <%s>\n",
|
||||||
kernel_boot_data.commandline,
|
kernel_boot_data.commandline,
|
||||||
kernel_boot_data.bootloader);
|
kernel_boot_data.bootloader
|
||||||
|
);
|
||||||
|
|
||||||
early_cpu_init();
|
early_cpu_init();
|
||||||
debug_info("Set up boot CPU\n");
|
debug_info("Set up boot CPU\n");
|
||||||
memory_init();
|
memory_init();
|
||||||
debug_info("Set up memory management\n");
|
debug_info("Set up memory management\n");
|
||||||
|
|
||||||
terminal_init();
|
terminal_init();
|
||||||
debug_info("Set up debug terminal\n");
|
debug_info("Set up debug terminal\n");
|
||||||
|
|
||||||
cpu_init();
|
cpu_init();
|
||||||
|
|
||||||
__asm__("sti");
|
__asm__("sti");
|
||||||
|
|
||||||
debug_info("Boot complete\n");
|
debug_info("Boot complete\n");
|
||||||
|
|
||||||
|
|
||||||
bind_interrupt(IRQ_INTERRUPT(IRQ_PS2_KBD), kbd_handler);
|
bind_interrupt(IRQ_INTERRUPT(IRQ_PS2_KBD), kbd_handler);
|
||||||
irq_unmask(IRQ_PS2_KBD);
|
irq_unmask(IRQ_PS2_KBD);
|
||||||
TEMP_test_scheduler();
|
TEMP_test_scheduler();
|
||||||
|
|
||||||
|
|
||||||
start_scheduler();
|
start_scheduler();
|
||||||
|
|
||||||
PANIC("End of kernel function!");
|
PANIC("End of kernel function!");
|
||||||
|
|
||||||
debug_info("Broke out of panic");
|
debug_info("Broke out of panic");
|
||||||
for(;;);
|
for(;;);
|
||||||
}
|
}
|
@ -8,106 +8,119 @@
|
|||||||
// https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
|
// https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
|
||||||
|
|
||||||
struct taglist {
|
struct taglist {
|
||||||
uint32_t total_size;
|
uint32_t total_size;
|
||||||
uint32_t reserved;
|
uint32_t reserved;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct tag {
|
struct tag {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct mmap_entry {
|
struct mmap_entry {
|
||||||
uint64_t base;
|
uint64_t base;
|
||||||
uint64_t len;
|
uint64_t len;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t reserved;
|
uint32_t reserved;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct mmap {
|
struct mmap {
|
||||||
uint32_t entry_size;
|
uint32_t entry_size;
|
||||||
uint32_t entry_version;
|
uint32_t entry_version;
|
||||||
struct mmap_entry entries[];
|
struct mmap_entry entries[];
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
static int parse_multiboot2(struct taglist *tags) {
|
static int parse_multiboot2(struct taglist *tags) {
|
||||||
struct mmap *mmap;
|
struct mmap *mmap;
|
||||||
|
|
||||||
struct tag *tag = incptr(tags, sizeof(struct taglist));
|
struct tag *tag = incptr(tags, sizeof(struct taglist));
|
||||||
kernel_boot_data.mboot_tags = tag;
|
kernel_boot_data.mboot_tags = tag;
|
||||||
kernel_boot_data.tags_length = tags->total_size;
|
kernel_boot_data.tags_length = tags->total_size;
|
||||||
while(tag->type) {
|
while(tag->type) {
|
||||||
switch(tag->type) {
|
switch(tag->type) {
|
||||||
case MBOOT2_TAG_BOOTLOADER:
|
case MBOOT2_TAG_BOOTLOADER:
|
||||||
kernel_boot_data.bootloader = (char *)tag->data;
|
kernel_boot_data.bootloader = (char *)tag->data;
|
||||||
break;
|
break;
|
||||||
case MBOOT2_TAG_CMDLINE:
|
case MBOOT2_TAG_CMDLINE:
|
||||||
kernel_boot_data.commandline = (char *)tag->data;
|
kernel_boot_data.commandline = (char *)tag->data;
|
||||||
break;
|
break;
|
||||||
case MBOOT2_TAG_MMAP:
|
case MBOOT2_TAG_MMAP:
|
||||||
mmap = kernel_boot_data.mmap = (void *)tag->data;
|
mmap = kernel_boot_data.mmap = (void *)tag->data;
|
||||||
kernel_boot_data.mmap_len = (tag->size - 8)/mmap->entry_size;
|
kernel_boot_data.mmap_len = (tag->size - 8)/mmap->entry_size;
|
||||||
kernel_boot_data.mmap_size = (tag->size - 8);
|
kernel_boot_data.mmap_size = (tag->size - 8);
|
||||||
break;
|
break;
|
||||||
case MBOOT2_TAG_FBINFO:
|
case MBOOT2_TAG_FBINFO:
|
||||||
kernel_boot_data.fbinfo = (void *)tag->data;
|
kernel_boot_data.fbinfo = (void *)tag->data;
|
||||||
break;
|
break;
|
||||||
case MBOOT2_TAG_OLD_RSDP:
|
case MBOOT2_TAG_OLD_RSDP:
|
||||||
case MBOOT2_TAG_NEW_RSDP:
|
case MBOOT2_TAG_NEW_RSDP:
|
||||||
kernel_boot_data.rsdp = (void *)tag->data;
|
kernel_boot_data.rsdp = (void *)tag->data;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// Tags are 8 byte alligned, so make sure we look for the next one in the right place
|
|
||||||
int padded_size = tag->size + ((tag->size % 8)?(8-(tag->size%8)):0);
|
|
||||||
tag = incptr(tag, padded_size);
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
// Tags are 8 byte alligned, so make sure we look for the next one
|
||||||
|
// in the right place
|
||||||
|
int padded_size = tag->size + ((tag->size % 8)?(8-(tag->size%8)):0);
|
||||||
|
tag = incptr(tag, padded_size);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int multiboot_init(uint64_t magic, void *mboot_info) {
|
int multiboot_init(uint64_t magic, void *mboot_info) {
|
||||||
if(magic == MBOOT2_REPLY) {
|
if(magic == MBOOT2_REPLY) {
|
||||||
kernel_boot_data.multiboot_version = 2;
|
kernel_boot_data.multiboot_version = 2;
|
||||||
parse_multiboot2(mboot_info);
|
parse_multiboot2(mboot_info);
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int multiboot_get_memory_area(size_t index, uintptr_t *start, uintptr_t *end, uint32_t *type) {
|
int multiboot_get_memory_area(
|
||||||
if(index >= kernel_boot_data.mmap_len) return 1;
|
size_t index,
|
||||||
|
uintptr_t *start,
|
||||||
|
uintptr_t *end,
|
||||||
|
uint32_t *type
|
||||||
|
) {
|
||||||
|
if(index >= kernel_boot_data.mmap_len) return 1;
|
||||||
|
|
||||||
struct mmap *mmap = kernel_boot_data.mmap;
|
struct mmap *mmap = kernel_boot_data.mmap;
|
||||||
struct mmap_entry *entry = mmap->entries;
|
struct mmap_entry *entry = mmap->entries;
|
||||||
entry = incptr(entry, index*mmap->entry_size);
|
entry = incptr(entry, index*mmap->entry_size);
|
||||||
|
|
||||||
*start = entry->base;
|
*start = entry->base;
|
||||||
*end = entry->base + entry->len;
|
*end = entry->base + entry->len;
|
||||||
*type = entry->type;
|
*type = entry->type;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int multiboot_page_used(uintptr_t page) {
|
int multiboot_page_used(uintptr_t page) {
|
||||||
#define within_page(st, l) (((uintptr_t)st + l) > page && (uintptr_t)st < (page + PAGE_SIZE))
|
#define within_page(st, l) (((uintptr_t)st + l) > page && \
|
||||||
|
(uintptr_t)st < (page + PAGE_SIZE))
|
||||||
|
|
||||||
size_t fb_size = 0;
|
size_t fb_size = 0;
|
||||||
uintptr_t fb_start = 0;
|
uintptr_t fb_start = 0;
|
||||||
if(kernel_boot_data.fbinfo) {
|
if(kernel_boot_data.fbinfo) {
|
||||||
fb_start = kernel_boot_data.fbinfo->framebuffer_addr;
|
fb_start = kernel_boot_data.fbinfo->framebuffer_addr;
|
||||||
fb_size = kernel_boot_data.fbinfo->framebuffer_pitch*(kernel_boot_data.fbinfo->framebuffer_height + 1);
|
fb_size = kernel_boot_data.fbinfo->framebuffer_pitch *
|
||||||
}
|
(kernel_boot_data.fbinfo->framebuffer_height + 1);
|
||||||
if(
|
}
|
||||||
within_page(kernel_boot_data.mboot_tags, kernel_boot_data.tags_length) ||
|
if(
|
||||||
within_page(kernel_boot_data.bootloader, strlen(kernel_boot_data.bootloader)) ||
|
within_page(kernel_boot_data.mboot_tags,
|
||||||
within_page(kernel_boot_data.commandline, strlen(kernel_boot_data.commandline)) ||
|
kernel_boot_data.tags_length
|
||||||
within_page(kernel_boot_data.mmap, kernel_boot_data.mmap_size) ||
|
) ||
|
||||||
within_page(fb_start, fb_size) ||
|
within_page(kernel_boot_data.bootloader,
|
||||||
0
|
strlen(kernel_boot_data.bootloader)
|
||||||
) {
|
) ||
|
||||||
return 1;
|
within_page(kernel_boot_data.commandline,
|
||||||
}
|
strlen(kernel_boot_data.commandline)
|
||||||
return 0;
|
) ||
|
||||||
|
within_page(kernel_boot_data.mmap, kernel_boot_data.mmap_size) ||
|
||||||
|
within_page(fb_start, fb_size) ||
|
||||||
|
0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -4,22 +4,23 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
// ACPI Specification https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf
|
// ACPI Specification:
|
||||||
|
// https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf
|
||||||
|
|
||||||
struct rsdp { // 5.2.5.3
|
struct rsdp { // 5.2.5.3
|
||||||
char signature[8];
|
char signature[8];
|
||||||
uint8_t checksum;
|
uint8_t checksum;
|
||||||
char OEMID[6];
|
char OEMID[6];
|
||||||
uint8_t revision;
|
uint8_t revision;
|
||||||
uint32_t rsdt_p;
|
uint32_t rsdt_p;
|
||||||
uint8_t _[14]; // Fields for revision >= 2
|
uint8_t _[14]; // Fields for revision >= 2
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct sdt {
|
struct sdt {
|
||||||
char signature[4];
|
char signature[4];
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint8_t _[28];
|
uint8_t _[28];
|
||||||
uint32_t data[];
|
uint32_t data[];
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
@ -29,83 +30,79 @@ struct sdt {
|
|||||||
#define MADT_TYPE_ISO 2
|
#define MADT_TYPE_ISO 2
|
||||||
|
|
||||||
struct madt_field {
|
struct madt_field {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t length;
|
uint8_t length;
|
||||||
union {
|
union {
|
||||||
// Processor Local APIC (5.2.12.2)
|
struct { // Processor Local APIC (5.2.12.2)
|
||||||
struct {
|
uint8_t id;
|
||||||
uint8_t id;
|
uint8_t apic;
|
||||||
uint8_t apic;
|
uint32_t flags;
|
||||||
uint32_t flags;
|
}__attribute__((packed)) lapic;
|
||||||
}__attribute__((packed)) lapic;
|
struct { // I/O APIC (5.2.12.3)
|
||||||
// I/O APIC (5.2.12.3)
|
uint8_t id;
|
||||||
struct {
|
uint8_t reserved;
|
||||||
uint8_t id;
|
uint32_t address;
|
||||||
uint8_t reserved;
|
uint32_t base;
|
||||||
uint32_t address;
|
}__attribute__((packed)) ioapic;
|
||||||
uint32_t base;
|
struct { // Interrupt source override (5.2.12.5)
|
||||||
}__attribute__((packed)) ioapic;
|
uint8_t bus;
|
||||||
// Interrupt source override (5.2.12.5)
|
uint8_t source;
|
||||||
struct {
|
uint32_t interrupt;
|
||||||
uint8_t bus;
|
uint16_t flags;
|
||||||
uint8_t source;
|
}__attribute__((packed)) iso;
|
||||||
uint32_t interrupt;
|
};
|
||||||
uint16_t flags;
|
|
||||||
}__attribute__((packed)) iso;
|
|
||||||
};
|
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct madt_header {
|
struct madt_header {
|
||||||
uint32_t controllerAddress;
|
uint32_t controllerAddress;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
struct madt_field fields[];
|
struct madt_field fields[];
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
static void madt_parse(struct madt_header *madt, size_t length)
|
static void madt_parse(struct madt_header *madt, size_t length)
|
||||||
{
|
{
|
||||||
int cpu_i=0;
|
int cpu_i=0;
|
||||||
for(
|
for(struct madt_field *f = madt->fields;
|
||||||
struct madt_field *f = madt->fields;
|
(size_t)f <= (size_t)madt + length;
|
||||||
(size_t)f <= (size_t)madt + length;
|
f = incptr(f, f->length)
|
||||||
f = incptr(f, f->length)
|
) {
|
||||||
) {
|
switch(f->type) {
|
||||||
switch(f->type) {
|
case MADT_TYPE_LAPIC: {
|
||||||
case MADT_TYPE_LAPIC: {
|
struct cpu *cpu = P2V(pmm_alloc());
|
||||||
struct cpu *cpu = P2V(pmm_alloc());
|
cpus[cpu_i++] = cpu;
|
||||||
cpus[cpu_i++] = cpu;
|
cpu->id = f->lapic.id;
|
||||||
cpu->id = f->lapic.id;
|
cpu->apic_id = f->lapic.apic;
|
||||||
cpu->apic_id = f->lapic.apic;
|
cpu->flags = f->lapic.flags;
|
||||||
cpu->flags = f->lapic.flags;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case MADT_TYPE_IOAPIC: {
|
||||||
case MADT_TYPE_IOAPIC: {
|
ioapic.id = f->ioapic.id;
|
||||||
ioapic.id = f->ioapic.id;
|
ioapic.addr = f->ioapic.address;
|
||||||
ioapic.addr = f->ioapic.address;
|
ioapic.base = f->ioapic.base;
|
||||||
ioapic.base = f->ioapic.base;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case MADT_TYPE_ISO: {
|
||||||
case MADT_TYPE_ISO: {
|
irq_redirects[f->iso.source] = f->iso.interrupt;
|
||||||
irq_redirects[f->iso.source] = f->iso.interrupt;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
default:
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_parse(void *_rsdp) {
|
void acpi_parse(void *_rsdp) {
|
||||||
struct rsdp *rsdp = _rsdp;
|
struct rsdp *rsdp = _rsdp;
|
||||||
|
|
||||||
struct sdt *rsdt = P2V(rsdp->rsdt_p);
|
struct sdt *rsdt = P2V(rsdp->rsdt_p);
|
||||||
int rsdt_entries = (rsdt->length - sizeof(struct sdt))/sizeof(uint32_t);
|
int rsdt_entries = (rsdt->length - sizeof(struct sdt))/sizeof(uint32_t);
|
||||||
|
|
||||||
for(int i = 0; i < rsdt_entries; i++) {
|
for(int i = 0; i < rsdt_entries; i++) {
|
||||||
struct sdt *h = P2V(rsdt->data[i]);
|
struct sdt *h = P2V(rsdt->data[i]);
|
||||||
if(h->length == 0) continue;
|
if(h->length == 0) continue;
|
||||||
|
|
||||||
if(!strncmp(h->signature, "APIC", 4)) { // 5.2.12
|
if(!strncmp(h->signature, "APIC", 4)) { // 5.2.12
|
||||||
madt_parse(P2V(h->data), h->length - sizeof(struct sdt));
|
madt_parse(P2V(h->data), h->length - sizeof(struct sdt));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -14,82 +14,90 @@
|
|||||||
#define IOREDTBL(irq) (0x10 + (irq)*2)
|
#define IOREDTBL(irq) (0x10 + (irq)*2)
|
||||||
|
|
||||||
union iored {
|
union iored {
|
||||||
struct {
|
struct {
|
||||||
uint8_t vector;
|
uint8_t vector;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t mask;
|
uint8_t mask;
|
||||||
uint32_t reserved;
|
uint32_t reserved;
|
||||||
uint8_t target;
|
uint8_t target;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
struct {
|
struct {
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
uint32_t h;
|
uint32_t h;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t ioapic_read(int reg) {
|
static uint32_t ioapic_read(int reg) {
|
||||||
uint32_t volatile *ioregsel = P2V(ioapic.addr);
|
uint32_t volatile *ioregsel = P2V(ioapic.addr);
|
||||||
uint32_t volatile *iowin = P2V(ioapic.addr + 0x10);
|
uint32_t volatile *iowin = P2V(ioapic.addr + 0x10);
|
||||||
*ioregsel = reg;
|
*ioregsel = reg;
|
||||||
return *iowin;
|
return *iowin;
|
||||||
}
|
}
|
||||||
static void ioapic_write(int reg, uint32_t value) {
|
static void ioapic_write(int reg, uint32_t value) {
|
||||||
uint32_t volatile *ioregsel = P2V(ioapic.addr);
|
uint32_t volatile *ioregsel = P2V(ioapic.addr);
|
||||||
uint32_t volatile *iowin = P2V(ioapic.addr + 0x10);
|
uint32_t volatile *iowin = P2V(ioapic.addr + 0x10);
|
||||||
*ioregsel = reg;
|
*ioregsel = reg;
|
||||||
*iowin = value;
|
*iowin = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t ioapic_read_redirection(int irq) {
|
static uint64_t ioapic_read_redirection(int irq) {
|
||||||
union iored retval;
|
union iored retval;
|
||||||
retval.l = ioapic_read(IOREDTBL(irq));
|
retval.l = ioapic_read(IOREDTBL(irq));
|
||||||
retval.h = ioapic_read(IOREDTBL(irq)+1);
|
retval.h = ioapic_read(IOREDTBL(irq)+1);
|
||||||
return retval.val;
|
return retval.val;
|
||||||
}
|
}
|
||||||
static void ioapic_write_redirection(int irq, uint64_t val) {
|
static void ioapic_write_redirection(int irq, uint64_t val) {
|
||||||
union iored value;
|
union iored value;
|
||||||
value.val = val;
|
value.val = val;
|
||||||
ioapic_write(IOREDTBL(irq), value.l);
|
ioapic_write(IOREDTBL(irq), value.l);
|
||||||
ioapic_write(IOREDTBL(irq) + 1, value.h);
|
ioapic_write(IOREDTBL(irq) + 1, value.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_ack() {
|
void irq_ack() {
|
||||||
APIC_REG(APIC_EOI) = 0;
|
APIC_REG(APIC_EOI) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_mask(int irq) {
|
void irq_mask(int irq) {
|
||||||
union iored iored;
|
union iored iored;
|
||||||
iored.val = ioapic_read_redirection(irq_redirects[irq]);
|
iored.val = ioapic_read_redirection(irq_redirects[irq]);
|
||||||
iored.mask |= 0x1;
|
iored.mask |= 0x1;
|
||||||
ioapic_write_redirection(irq_redirects[irq], iored.val);
|
ioapic_write_redirection(irq_redirects[irq], iored.val);
|
||||||
}
|
}
|
||||||
void irq_unmask(int irq) {
|
void irq_unmask(int irq) {
|
||||||
union iored iored;
|
union iored iored;
|
||||||
iored.val = ioapic_read_redirection(irq_redirects[irq]);
|
iored.val = ioapic_read_redirection(irq_redirects[irq]);
|
||||||
iored.mask &= ~0x1;
|
iored.mask &= ~0x1;
|
||||||
ioapic_write_redirection(irq_redirects[irq], iored.val);
|
ioapic_write_redirection(irq_redirects[irq], iored.val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ioapic_init() {
|
void ioapic_init() {
|
||||||
// Map ioapic offset into kernel memory
|
// Map ioapic offset into kernel memory
|
||||||
vmm_set_page(kernel_P4, (uintptr_t)P2V(ioapic.addr), ioapic.addr, PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL);
|
vmm_set_page(kernel_P4,
|
||||||
|
(uintptr_t)P2V(ioapic.addr),
|
||||||
|
ioapic.addr,
|
||||||
|
PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL
|
||||||
|
);
|
||||||
|
|
||||||
union iored iored;
|
union iored iored;
|
||||||
for(int i = 0; i < 24; i++) {
|
for(int i = 0; i < 24; i++) {
|
||||||
iored.val = ioapic_read_redirection(i);
|
iored.val = ioapic_read_redirection(i);
|
||||||
iored.vector = IRQ_BASE+i;
|
iored.vector = IRQ_BASE+i;
|
||||||
iored.flags = 0x0;
|
iored.flags = 0x0;
|
||||||
iored.mask |= 1;
|
iored.mask |= 1;
|
||||||
iored.target = 0x0;
|
iored.target = 0x0;
|
||||||
ioapic_write_redirection(i, iored.val);
|
ioapic_write_redirection(i, iored.val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void apic_init() {
|
void apic_init() {
|
||||||
// Map apic offset into kernel memory
|
// Map apic offset into kernel memory
|
||||||
vmm_set_page(kernel_P4, (uintptr_t)P2V(APIC_BASE), APIC_BASE, PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL);
|
vmm_set_page(kernel_P4,
|
||||||
|
(uintptr_t)P2V(APIC_BASE),
|
||||||
|
APIC_BASE,
|
||||||
|
PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL
|
||||||
|
);
|
||||||
|
|
||||||
// Allow LAPIC to receive interrupts
|
// Allow LAPIC to receive interrupts
|
||||||
APIC_REG(APIC_SPURIOUS) = APIC_REG(APIC_SPURIOUS) | 0x100 | IRQ_SPURIOUS;
|
APIC_REG(APIC_SPURIOUS) = APIC_REG(APIC_SPURIOUS) | 0x100 | IRQ_SPURIOUS;
|
||||||
}
|
}
|
@ -4,24 +4,26 @@
|
|||||||
|
|
||||||
struct cpu *cpus[16];
|
struct cpu *cpus[16];
|
||||||
struct ioapic ioapic = {0,0,0};
|
struct ioapic ioapic = {0,0,0};
|
||||||
uint8_t irq_redirects[MAX_IRQS] = \
|
uint8_t irq_redirects[MAX_IRQS] = {
|
||||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||||
|
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
|
||||||
|
};
|
||||||
|
|
||||||
#define PIC1_ADDR 0x20
|
#define PIC1_ADDR 0x20
|
||||||
#define PIC2_ADDR 0xA0
|
#define PIC2_ADDR 0xA0
|
||||||
static void pic_disable() {
|
static void pic_disable() {
|
||||||
// Mask all interrupts
|
// Mask all interrupts
|
||||||
outb(PIC1_ADDR | 1, 0xFF);
|
outb(PIC1_ADDR | 1, 0xFF);
|
||||||
outb(PIC2_ADDR | 1, 0xFF);
|
outb(PIC2_ADDR | 1, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void early_cpu_init() {
|
void early_cpu_init() {
|
||||||
interrupt_init();
|
interrupt_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_init() {
|
void cpu_init() {
|
||||||
acpi_parse(kernel_boot_data.rsdp);
|
acpi_parse(kernel_boot_data.rsdp);
|
||||||
pic_disable();
|
pic_disable();
|
||||||
apic_init();
|
apic_init();
|
||||||
ioapic_init();
|
ioapic_init();
|
||||||
}
|
}
|
@ -6,18 +6,18 @@
|
|||||||
#define GDT_LONG (1<<21)
|
#define GDT_LONG (1<<21)
|
||||||
|
|
||||||
struct gdt {
|
struct gdt {
|
||||||
uint32_t _;
|
uint32_t _;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct gdtp {
|
struct gdtp {
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
struct gdt *gdt;
|
struct gdt *gdt;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct gdt BootGDT[] = {
|
struct gdt BootGDT[] = {
|
||||||
{0, 0},
|
{0, 0},
|
||||||
{0, GDT_PRESENT | GDT_DPL(0) | GDT_CODE | GDT_LONG}
|
{0, GDT_PRESENT | GDT_DPL(0) | GDT_CODE | GDT_LONG}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gdtp GDTp = {2*8-1, BootGDT};
|
struct gdtp GDTp = {2*8-1, BootGDT};
|
@ -11,67 +11,70 @@
|
|||||||
#define NUM_INTERRUPTS 256
|
#define NUM_INTERRUPTS 256
|
||||||
|
|
||||||
struct idt {
|
struct idt {
|
||||||
uint16_t base_l;
|
uint16_t base_l;
|
||||||
uint16_t cs;
|
uint16_t cs;
|
||||||
uint8_t ist;
|
uint8_t ist;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint16_t base_m;
|
uint16_t base_m;
|
||||||
uint32_t base_h;
|
uint32_t base_h;
|
||||||
uint32_t _;
|
uint32_t _;
|
||||||
}__attribute__((packed)) idt[NUM_INTERRUPTS];
|
}__attribute__((packed)) idt[NUM_INTERRUPTS];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
struct idt *addr;
|
struct idt *addr;
|
||||||
}__attribute__((packed)) idtr;
|
}__attribute__((packed)) idtr;
|
||||||
|
|
||||||
extern uintptr_t isr_table[];
|
extern uintptr_t isr_table[];
|
||||||
int_handler_t int_handlers[NUM_INTERRUPTS];
|
int_handler_t int_handlers[NUM_INTERRUPTS];
|
||||||
|
|
||||||
void interrupt_init() {
|
void interrupt_init() {
|
||||||
memset(idt, 0, sizeof(idt));
|
memset(idt, 0, sizeof(idt));
|
||||||
for(int i=0; i < NUM_INTERRUPTS; i++) {
|
for(int i=0; i < NUM_INTERRUPTS; i++) {
|
||||||
idt[i].base_l = isr_table[i] & 0xFFFF;
|
idt[i].base_l = isr_table[i] & 0xFFFF;
|
||||||
idt[i].base_m = (isr_table[i] >> 16) & 0xFFFF;
|
idt[i].base_m = (isr_table[i] >> 16) & 0xFFFF;
|
||||||
idt[i].base_h = (isr_table[i] >> 32) & 0xFFFFFFFF;
|
idt[i].base_h = (isr_table[i] >> 32) & 0xFFFFFFFF;
|
||||||
idt[i].cs = 0x8;
|
idt[i].cs = 0x8;
|
||||||
idt[i].ist = 0;
|
idt[i].ist = 0;
|
||||||
idt[i].flags = IDT_PRESENT | IDT_DPL0 | IDT_INTERRUPT;
|
idt[i].flags = IDT_PRESENT | IDT_DPL0 | IDT_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
idtr.addr = idt;
|
idtr.addr = idt;
|
||||||
idtr.len = sizeof(idt)-1;
|
idtr.len = sizeof(idt)-1;
|
||||||
load_idt(&idtr); // cpu/registers.S
|
load_idt(&idtr); // cpu/registers.S
|
||||||
}
|
}
|
||||||
|
|
||||||
int_handler_t bind_interrupt(uint32_t num, int_handler_t fn) {
|
int_handler_t bind_interrupt(uint32_t num, int_handler_t fn) {
|
||||||
int_handler_t old = int_handlers[num];
|
int_handler_t old = int_handlers[num];
|
||||||
int_handlers[num] = fn;
|
int_handlers[num] = fn;
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
registers *int_handler(registers *r) {
|
registers *int_handler(registers *r) {
|
||||||
if(int_handlers[r->int_no])
|
if(int_handlers[r->int_no])
|
||||||
return int_handlers[r->int_no](r);
|
return int_handlers[r->int_no](r);
|
||||||
if(r->int_no < IRQ_BASE) {
|
if(r->int_no < IRQ_BASE) {
|
||||||
debug_error("UNHANDLED EXCEPTION\n");
|
debug_error("UNHANDLED EXCEPTION\n");
|
||||||
switch(r->int_no) {
|
switch(r->int_no) {
|
||||||
case 14:
|
case 14:
|
||||||
debug_error("Page fault\n");
|
debug_error("Page fault\n");
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
debug_error("Invalid opcode\n");
|
debug_error("Invalid opcode\n");
|
||||||
}
|
|
||||||
debug_error("Interrupt number: %d, Error code: %d\n", r->int_no, r->err_code);
|
|
||||||
PANIC("Unhandled interrupt\n");
|
|
||||||
} else if(r->int_no < IRQ_BASE + MAX_IRQS) {
|
|
||||||
debug_error("UNHANDLED IRQ\n");
|
|
||||||
debug_error("IRQ: %d", r->int_no - IRQ_BASE);
|
|
||||||
PANIC("Unhandled IRQ\n");
|
|
||||||
} else {
|
|
||||||
debug_error("UNKNOWN INTERRUPT\n");
|
|
||||||
debug_error("Interrupt number: %d\n", r->int_no);
|
|
||||||
PANIC("Unknown interrupt\n");
|
|
||||||
}
|
}
|
||||||
return r;
|
debug_error("Interrupt number: %d, Error code: %d\n",
|
||||||
|
r->int_no,
|
||||||
|
r->err_code
|
||||||
|
);
|
||||||
|
PANIC("Unhandled interrupt\n");
|
||||||
|
} else if(r->int_no < IRQ_BASE + MAX_IRQS) {
|
||||||
|
debug_error("UNHANDLED IRQ\n");
|
||||||
|
debug_error("IRQ: %d", r->int_no - IRQ_BASE);
|
||||||
|
PANIC("Unhandled IRQ\n");
|
||||||
|
} else {
|
||||||
|
debug_error("UNKNOWN INTERRUPT\n");
|
||||||
|
debug_error("Interrupt number: %d\n", r->int_no);
|
||||||
|
PANIC("Unknown interrupt\n");
|
||||||
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
@ -8,47 +8,63 @@ gfx_context *term_fb;
|
|||||||
static int setup = 0;
|
static int setup = 0;
|
||||||
|
|
||||||
void fbterm_movecursor(unsigned int cursor) {
|
void fbterm_movecursor(unsigned int cursor) {
|
||||||
(void) cursor;
|
(void) cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fbterm_flush(struct vga_cell *buffer) {
|
void fbterm_flush(struct vga_cell *buffer) {
|
||||||
if(!setup) return;
|
if(!setup) return;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(int row = 0; row < VGA_ROWS; row++) {
|
for(int row = 0; row < VGA_ROWS; row++) {
|
||||||
for(int col=0; col < VGA_COLS; col++) {
|
for(int col=0; col < VGA_COLS; col++) {
|
||||||
putCharacter(term_fb, col*8, row*16, 0xebdbb2, 0x282828, (char)buffer[i++].c);
|
putCharacter(term_fb,
|
||||||
}
|
col*8, row*16,
|
||||||
|
0xebdbb2, 0x282828,
|
||||||
|
(char)buffer[i++].c
|
||||||
|
);
|
||||||
}
|
}
|
||||||
flip(term_fb);
|
}
|
||||||
|
flip(term_fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fbterm_init(struct fbinfo *fbinfo) {
|
void fbterm_init(struct fbinfo *fbinfo) {
|
||||||
kernel_fb.width = fbinfo->framebuffer_width;
|
kernel_fb = (gfx_context){
|
||||||
kernel_fb.height = fbinfo->framebuffer_height;
|
.width = fbinfo->framebuffer_width,
|
||||||
kernel_fb.bpp = fbinfo->framebuffer_bpp/8;
|
.height = fbinfo->framebuffer_height,
|
||||||
kernel_fb.pitch = fbinfo->framebuffer_pitch/kernel_fb.bpp;
|
.bpp = fbinfo->framebuffer_bpp/8,
|
||||||
kernel_fb.addr = P2V(fbinfo->framebuffer_addr);
|
.pitch = fbinfo->framebuffer_pitch/(fbinfo->framebuffer_bpp/8),
|
||||||
kernel_fb.size = fbinfo->framebuffer_pitch * (kernel_fb.height);
|
.addr = P2V(fbinfo->framebuffer_addr),
|
||||||
kernel_fb.buffer = calloc(1, kernel_fb.size);
|
.size = fbinfo->framebuffer_pitch * (fbinfo->framebuffer_height),
|
||||||
|
};
|
||||||
|
kernel_fb.buffer = calloc(1, kernel_fb.size);
|
||||||
|
|
||||||
for(
|
for(uintptr_t p = (uintptr_t)kernel_fb.addr;
|
||||||
uintptr_t p = (uintptr_t)kernel_fb.addr;
|
p < ((uintptr_t)kernel_fb.addr + kernel_fb.size);
|
||||||
p < ((uintptr_t)kernel_fb.addr + kernel_fb.size);
|
p += PAGE_SIZE
|
||||||
p += PAGE_SIZE
|
) {
|
||||||
) {
|
vmm_set_page(kernel_P4,
|
||||||
vmm_set_page(kernel_P4, p, V2P(p), PAGE_GLOBAL | PAGE_WRITE | PAGE_PRESENT);
|
p,
|
||||||
}
|
V2P(p),
|
||||||
|
PAGE_GLOBAL | PAGE_WRITE | PAGE_PRESENT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
draw_rect(&kernel_fb, 20, 20, 8*VGA_COLS+8, 16*VGA_ROWS+8, RGB(255, 0, 0));
|
draw_rect(&kernel_fb,
|
||||||
flip(&kernel_fb);
|
20, 20,
|
||||||
term_fb = framebuffer_make_subcontext(&kernel_fb, 24, 24, 8*VGA_COLS, 16*VGA_ROWS);
|
8*VGA_COLS+8, 16*VGA_ROWS+8,
|
||||||
flip(term_fb);
|
RGB(255, 0, 0)
|
||||||
setup = 1;
|
);
|
||||||
|
flip(&kernel_fb);
|
||||||
|
term_fb = framebuffer_make_subcontext(&kernel_fb,
|
||||||
|
24, 24,
|
||||||
|
8*VGA_COLS, 16*VGA_ROWS
|
||||||
|
);
|
||||||
|
flip(term_fb);
|
||||||
|
setup = 1;
|
||||||
|
|
||||||
draw_line(&kernel_fb, 750, 850, 120, 120, RGB(255,0,0));
|
draw_line(&kernel_fb, 750, 850, 120, 120, RGB(255,0,0));
|
||||||
draw_line(&kernel_fb, 750, 750, 120, 220, RGB(0,255,0));
|
draw_line(&kernel_fb, 750, 750, 120, 220, RGB(0,255,0));
|
||||||
draw_line(&kernel_fb, 750, 850, 120, 220, RGB(0,0,255));
|
draw_line(&kernel_fb, 750, 850, 120, 220, RGB(0,0,255));
|
||||||
draw_line(&kernel_fb, 750, 800, 120, 220, RGB(255,0,255));
|
draw_line(&kernel_fb, 750, 800, 120, 220, RGB(255,0,255));
|
||||||
draw_line(&kernel_fb, 750, 850, 120, 170, RGB(255,255,0));
|
draw_line(&kernel_fb, 750, 850, 120, 170, RGB(255,255,0));
|
||||||
flip(&kernel_fb);
|
flip(&kernel_fb);
|
||||||
}
|
}
|
@ -20,86 +20,91 @@ uint8_t format = 0x7;
|
|||||||
static int terminal_type;
|
static int terminal_type;
|
||||||
|
|
||||||
static void scroll() {
|
static void scroll() {
|
||||||
while(cursor >= VGA_SIZE) {
|
while(cursor >= VGA_SIZE) {
|
||||||
memmove(buffer, &buffer[VGA_POS(1,0)], VGA_COLS*(VGA_ROWS-1)*sizeof(struct vga_cell));
|
memmove(buffer,
|
||||||
memset(&buffer[VGA_POS(VGA_ROWS-1, 0)], 0, VGA_COLS*sizeof(struct vga_cell));
|
&buffer[VGA_POS(1,0)],
|
||||||
cursor -= VGA_COLS;
|
VGA_COLS*(VGA_ROWS-1)*sizeof(struct vga_cell)
|
||||||
}
|
);
|
||||||
|
memset(&buffer[VGA_POS(VGA_ROWS-1, 0)],
|
||||||
|
0,
|
||||||
|
VGA_COLS*sizeof(struct vga_cell)
|
||||||
|
);
|
||||||
|
cursor -= VGA_COLS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void terminal_write(char c) {
|
static void terminal_write(char c) {
|
||||||
int doflush = 0;
|
int doflush = 0;
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case '\n':
|
case '\n':
|
||||||
cursor += VGA_COLS - VGA_COL(cursor);
|
cursor += VGA_COLS - VGA_COL(cursor);
|
||||||
doflush = 1;
|
doflush = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buffer[cursor++] = (struct vga_cell){.c = c, .f = format};
|
buffer[cursor++] = (struct vga_cell){.c = c, .f = format};
|
||||||
}
|
}
|
||||||
scroll();
|
scroll();
|
||||||
switch(terminal_type) {
|
switch(terminal_type) {
|
||||||
case FRAMEBUFFER:
|
case FRAMEBUFFER:
|
||||||
if(doflush)
|
if(doflush)
|
||||||
fbterm_flush(buffer);
|
fbterm_flush(buffer);
|
||||||
fbterm_movecursor(cursor);
|
fbterm_movecursor(cursor);
|
||||||
break;
|
break;
|
||||||
case EGA_TEXT:
|
case EGA_TEXT:
|
||||||
if(doflush)
|
if(doflush)
|
||||||
vga_flush(buffer);
|
vga_flush(buffer);
|
||||||
vga_movecursor(cursor);
|
vga_movecursor(cursor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void terminal_putsn(char *s, size_t n) {
|
static void terminal_putsn(char *s, size_t n) {
|
||||||
while(n--)
|
while(n--)
|
||||||
terminal_write(*s++);
|
terminal_write(*s++);
|
||||||
}
|
}
|
||||||
|
|
||||||
long k_ioctl(long fd, long cmd, long arg3, long, long, long) {
|
long k_ioctl(long fd, long cmd, long arg3, long, long, long) {
|
||||||
if(fd == 1 && cmd == 0x5413) {
|
if(fd == 1 && cmd == 0x5413) {
|
||||||
struct {
|
struct {
|
||||||
unsigned short ws_row;
|
unsigned short ws_row;
|
||||||
unsigned short ws_col;
|
unsigned short ws_col;
|
||||||
unsigned short ws_xp;
|
unsigned short ws_xp;
|
||||||
unsigned short ws_yp;
|
unsigned short ws_yp;
|
||||||
} *wsz = (void *)arg3;
|
} *wsz = (void *)arg3;
|
||||||
wsz->ws_row = 24;
|
wsz->ws_row = 24;
|
||||||
wsz->ws_col = 80;
|
wsz->ws_col = 80;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
long retval = -1;
|
long retval = -1;
|
||||||
PANIC("Unknown IOCTL request: fd: %d, command: %x\n", fd, cmd);
|
PANIC("Unknown IOCTL request: fd: %d, command: %x\n", fd, cmd);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
long k_writev(long fd, long iov, long iovcnt, long, long, long) {
|
long k_writev(long fd, long iov, long iovcnt, long, long, long) {
|
||||||
if(fd == 1)
|
if(fd == 1) {
|
||||||
{
|
size_t len = 0;
|
||||||
size_t len = 0;
|
struct iovec *v = (void *) iov;
|
||||||
struct iovec *v = (void *) iov;
|
for(int i = 0; i < iovcnt; i++) {
|
||||||
for(int i = 0; i < iovcnt; i++) {
|
terminal_putsn(v[i].iov_base, v[i].iov_len);
|
||||||
terminal_putsn(v[i].iov_base, v[i].iov_len);
|
len += v[i].iov_len;
|
||||||
len += v[i].iov_len;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
long retval = 0;
|
return len;
|
||||||
PANIC("Unknown writev request: fd: %d\n", fd);
|
}
|
||||||
return retval;
|
long retval = 0;
|
||||||
|
PANIC("Unknown writev request: fd: %d\n", fd);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_init() {
|
void terminal_init() {
|
||||||
struct fbinfo *fbinfo = kernel_boot_data.fbinfo;
|
struct fbinfo *fbinfo = kernel_boot_data.fbinfo;
|
||||||
terminal_type = fbinfo->framebuffer_type;
|
terminal_type = fbinfo->framebuffer_type;
|
||||||
|
|
||||||
switch(terminal_type) {
|
switch(terminal_type) {
|
||||||
case FRAMEBUFFER:
|
case FRAMEBUFFER:
|
||||||
fbterm_init(fbinfo);
|
fbterm_init(fbinfo);
|
||||||
break;
|
break;
|
||||||
case EGA_TEXT:
|
case EGA_TEXT:
|
||||||
vga_init(fbinfo);
|
vga_init(fbinfo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,21 +16,21 @@ static void *vidmem;
|
|||||||
static int setup = 0;
|
static int setup = 0;
|
||||||
|
|
||||||
void vga_init(struct fbinfo *fbinfo) {
|
void vga_init(struct fbinfo *fbinfo) {
|
||||||
(void) fbinfo;
|
(void) fbinfo;
|
||||||
vidmem = VGA_MEMORY;
|
vidmem = VGA_MEMORY;
|
||||||
memset(vidmem, 0, VGA_SIZE*sizeof(struct vga_cell));
|
memset(vidmem, 0, VGA_SIZE*sizeof(struct vga_cell));
|
||||||
setup = 1;
|
setup = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vga_movecursor(unsigned int cursor) {
|
void vga_movecursor(unsigned int cursor) {
|
||||||
if(!setup) return;
|
if(!setup) return;
|
||||||
outb(VGA_ADDRESS_PORT, VGA_REGISTER_CURSOR_POS_LOW);
|
outb(VGA_ADDRESS_PORT, VGA_REGISTER_CURSOR_POS_LOW);
|
||||||
outb(VGA_DATA_PORT, (uint8_t)(cursor & 0xFF));
|
outb(VGA_DATA_PORT, (uint8_t)(cursor & 0xFF));
|
||||||
outb(VGA_ADDRESS_PORT, VGA_REGISTER_CURSOR_POS_HIGH);
|
outb(VGA_ADDRESS_PORT, VGA_REGISTER_CURSOR_POS_HIGH);
|
||||||
outb(VGA_DATA_PORT, (uint8_t)((cursor >> 8) & 0xFF));
|
outb(VGA_DATA_PORT, (uint8_t)((cursor >> 8) & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
void vga_flush(struct vga_cell *buffer) {
|
void vga_flush(struct vga_cell *buffer) {
|
||||||
if(!setup) return;
|
if(!setup) return;
|
||||||
memcpy(vidmem, buffer, VGA_SIZE*2);
|
memcpy(vidmem, buffer, VGA_SIZE*2);
|
||||||
}
|
}
|
||||||
|
@ -13,43 +13,43 @@
|
|||||||
#define IRQ_SPURIOUS 0xFF
|
#define IRQ_SPURIOUS 0xFF
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t rax;
|
uint64_t rax;
|
||||||
uint64_t rbx;
|
uint64_t rbx;
|
||||||
uint64_t rcx;
|
uint64_t rcx;
|
||||||
uint64_t rdx;
|
uint64_t rdx;
|
||||||
uint64_t rsi;
|
uint64_t rsi;
|
||||||
uint64_t rdi;
|
uint64_t rdi;
|
||||||
uint64_t rbp;
|
uint64_t rbp;
|
||||||
uint64_t r8;
|
uint64_t r8;
|
||||||
uint64_t r9;
|
uint64_t r9;
|
||||||
uint64_t r10;
|
uint64_t r10;
|
||||||
uint64_t r11;
|
uint64_t r11;
|
||||||
uint64_t r12;
|
uint64_t r12;
|
||||||
uint64_t r13;
|
uint64_t r13;
|
||||||
uint64_t r14;
|
uint64_t r14;
|
||||||
uint64_t r15;
|
uint64_t r15;
|
||||||
|
|
||||||
uint64_t int_no;
|
uint64_t int_no;
|
||||||
uint64_t err_code;
|
uint64_t err_code;
|
||||||
|
|
||||||
uint64_t rip;
|
uint64_t rip;
|
||||||
uint64_t cs;
|
uint64_t cs;
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
uint64_t rsp;
|
uint64_t rsp;
|
||||||
uint64_t ss;
|
uint64_t ss;
|
||||||
} registers;
|
} registers;
|
||||||
|
|
||||||
typedef registers *(*int_handler_t)(registers *);
|
typedef registers *(*int_handler_t)(registers *);
|
||||||
|
|
||||||
struct cpu {
|
struct cpu {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
uint8_t apic_id;
|
uint8_t apic_id;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
};
|
};
|
||||||
struct ioapic {
|
struct ioapic {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct cpu *cpus[MAX_CPUS];
|
extern struct cpu *cpus[MAX_CPUS];
|
||||||
|
@ -26,12 +26,12 @@
|
|||||||
|
|
||||||
#define PANIC(...) \
|
#define PANIC(...) \
|
||||||
do { \
|
do { \
|
||||||
debug("\n\nKERNEL PANIC!\n%s:%d\n", __FILE__, __LINE__); \
|
debug("\n\nKERNEL PANIC!\n%s:%d\n", __FILE__, __LINE__); \
|
||||||
debug(__VA_ARGS__); \
|
debug(__VA_ARGS__); \
|
||||||
debug("\n"); \
|
debug("\n"); \
|
||||||
volatile int _override = 0; \
|
volatile int _override = 0; \
|
||||||
while(1) { \
|
while(1) { \
|
||||||
__asm__("panic_breakpoint_" S__LINE__ ":"); \
|
__asm__("panic_breakpoint_" S__LINE__ ":"); \
|
||||||
if(_override) break; \
|
if(_override) break; \
|
||||||
} \
|
} \
|
||||||
}while(0)
|
}while(0)
|
||||||
|
@ -12,40 +12,40 @@
|
|||||||
#define ENTRIES_PER_PT 512
|
#define ENTRIES_PER_PT 512
|
||||||
|
|
||||||
#ifdef __ASSEMBLER__
|
#ifdef __ASSEMBLER__
|
||||||
#define V2P(a) ((a) - KERNEL_OFFSET)
|
#define V2P(a) ((a) - KERNEL_OFFSET)
|
||||||
#define P2V(a) ((a) + KERNEL_OFFSET)
|
#define P2V(a) ((a) + KERNEL_OFFSET)
|
||||||
#else
|
#else
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#define V2P(a) ((uintptr_t)(a) &~KERNEL_OFFSET)
|
#define V2P(a) ((uintptr_t)(a) &~KERNEL_OFFSET)
|
||||||
#define P2V(a) ((void *)((uintptr_t)(a) | KERNEL_OFFSET))
|
#define P2V(a) ((void *)((uintptr_t)(a) | KERNEL_OFFSET))
|
||||||
|
|
||||||
#define incptr(p, n) ((void *)(((uintptr_t)(p)) + (n)))
|
#define incptr(p, n) ((void *)(((uintptr_t)(p)) + (n)))
|
||||||
|
|
||||||
#define P1_OFFSET(a) (((a)>>12) & 0x1FF)
|
#define P1_OFFSET(a) (((a)>>12) & 0x1FF)
|
||||||
#define P2_OFFSET(a) (((a)>>21) & 0x1FF)
|
#define P2_OFFSET(a) (((a)>>21) & 0x1FF)
|
||||||
#define P3_OFFSET(a) (((a)>>30) & 0x1FF)
|
#define P3_OFFSET(a) (((a)>>30) & 0x1FF)
|
||||||
#define P4_OFFSET(a) (((a)>>39) & 0x1FF)
|
#define P4_OFFSET(a) (((a)>>39) & 0x1FF)
|
||||||
|
|
||||||
// memory/memory.c
|
// memory/memory.c
|
||||||
void memory_init();
|
void memory_init();
|
||||||
extern uint64_t kernel_P4;
|
extern uint64_t kernel_P4;
|
||||||
|
|
||||||
// memory/vmm.c
|
// memory/vmm.c
|
||||||
uint64_t new_P4();
|
uint64_t new_P4();
|
||||||
uint64_t vmm_get_page(uint64_t P4, uint64_t addr);
|
uint64_t vmm_get_page(uint64_t P4, uint64_t addr);
|
||||||
int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags);
|
int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags);
|
||||||
void vmm_clear_page(uint64_t P4, uint64_t addr, int free);
|
void vmm_clear_page(uint64_t P4, uint64_t addr, int free);
|
||||||
|
|
||||||
// memory/pmm.c
|
// memory/pmm.c
|
||||||
void pmm_free(uint64_t page);
|
void pmm_free(uint64_t page);
|
||||||
uint64_t pmm_alloc();
|
uint64_t pmm_alloc();
|
||||||
uint64_t pmm_calloc();
|
uint64_t pmm_calloc();
|
||||||
|
|
||||||
// Link.ld
|
// Link.ld
|
||||||
extern int kernel_start, kernel_end;
|
extern int kernel_start, kernel_end;
|
||||||
|
|
||||||
// boot/boot_PT.s
|
// boot/boot_PT.s
|
||||||
extern uint64_t BootP4;
|
extern uint64_t BootP4;
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -18,27 +18,27 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct fbinfo {
|
struct fbinfo {
|
||||||
uint64_t framebuffer_addr;
|
uint64_t framebuffer_addr;
|
||||||
uint32_t framebuffer_pitch;
|
uint32_t framebuffer_pitch;
|
||||||
uint32_t framebuffer_width;
|
uint32_t framebuffer_width;
|
||||||
uint32_t framebuffer_height;
|
uint32_t framebuffer_height;
|
||||||
uint8_t framebuffer_bpp;
|
uint8_t framebuffer_bpp;
|
||||||
uint8_t framebuffer_type;
|
uint8_t framebuffer_type;
|
||||||
uint8_t reserved;
|
uint8_t reserved;
|
||||||
uint8_t color_info[];
|
uint8_t color_info[];
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct kernel_boot_data_st {
|
struct kernel_boot_data_st {
|
||||||
int multiboot_version;
|
int multiboot_version;
|
||||||
void *mboot_tags;
|
void *mboot_tags;
|
||||||
size_t tags_length;
|
size_t tags_length;
|
||||||
char *bootloader;
|
char *bootloader;
|
||||||
char *commandline;
|
char *commandline;
|
||||||
size_t mmap_size;
|
size_t mmap_size;
|
||||||
unsigned int mmap_len;
|
unsigned int mmap_len;
|
||||||
void *mmap;
|
void *mmap;
|
||||||
struct fbinfo *fbinfo;
|
struct fbinfo *fbinfo;
|
||||||
void *rsdp;
|
void *rsdp;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MMAP_FREE 1
|
#define MMAP_FREE 1
|
||||||
|
@ -26,23 +26,23 @@ long k_sched_yield(long, long, long, long, long, long);
|
|||||||
|
|
||||||
|
|
||||||
struct __locale_struct {
|
struct __locale_struct {
|
||||||
const struct __locale_map *cat[6];
|
const struct __locale_map *cat[6];
|
||||||
};
|
};
|
||||||
struct tls_module {
|
struct tls_module {
|
||||||
struct tls_module *next;
|
struct tls_module *next;
|
||||||
void *image;
|
void *image;
|
||||||
size_t len, size, align, offset;
|
size_t len, size, align, offset;
|
||||||
};
|
};
|
||||||
struct __libc {
|
struct __libc {
|
||||||
char can_do_threads;
|
char can_do_threads;
|
||||||
char threaded;
|
char threaded;
|
||||||
char secure;
|
char secure;
|
||||||
volatile signed char need_locks;
|
volatile signed char need_locks;
|
||||||
int threads_minus_1;
|
int threads_minus_1;
|
||||||
size_t *auxv;
|
size_t *auxv;
|
||||||
struct tls_module *tls_head;
|
struct tls_module *tls_head;
|
||||||
size_t tls_size, tls_align, tls_cnt;
|
size_t tls_size, tls_align, tls_cnt;
|
||||||
size_t page_size;
|
size_t page_size;
|
||||||
struct __locale_struct global_locale;
|
struct __locale_struct global_locale;
|
||||||
};
|
};
|
||||||
extern struct __libc __libc;
|
extern struct __libc __libc;
|
@ -2,13 +2,13 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
static __inline void _outb(uint16_t port, uint8_t value) {
|
static __inline void _outb(uint16_t port, uint8_t value) {
|
||||||
__asm__ volatile("outb %1, %0" : : "dN" (port), "a" (value));
|
__asm__ volatile("outb %1, %0" : : "dN" (port), "a" (value));
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline uint8_t _inb(uint16_t port) {
|
static __inline uint8_t _inb(uint16_t port) {
|
||||||
uint8_t ret;
|
uint8_t ret;
|
||||||
__asm__ volatile("inb %1, %0" : "=a" (ret) : "dN" (port));
|
__asm__ volatile("inb %1, %0" : "=a" (ret) : "dN" (port));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define outb _outb
|
#define outb _outb
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
uint64_t pid;
|
uint64_t pid;
|
||||||
void *stack_ptr;
|
void *stack_ptr;
|
||||||
uint64_t state;
|
uint64_t state;
|
||||||
uint64_t P4;
|
uint64_t P4;
|
||||||
struct process *q_next;
|
struct process *q_next;
|
||||||
uint8_t stack[];
|
uint8_t stack[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// proc/process.c
|
// proc/process.c
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
#define VGA_MEMORY P2V(0xB8000)
|
#define VGA_MEMORY P2V(0xB8000)
|
||||||
|
|
||||||
struct vga_cell {
|
struct vga_cell {
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
uint8_t f;
|
uint8_t f;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,85 +2,89 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
syscall_handler syscall_handlers[440] = {
|
syscall_handler syscall_handlers[440] = {
|
||||||
[SYSCALL_BRK] = k_brk,
|
[SYSCALL_BRK] = k_brk,
|
||||||
[SYSCALL_IOCTL] = k_ioctl,
|
[SYSCALL_IOCTL] = k_ioctl,
|
||||||
[SYSCALL_WRITEV] = k_writev,
|
[SYSCALL_WRITEV] = k_writev,
|
||||||
[SYSCALL_SCHED_YIELD] = k_sched_yield,
|
[SYSCALL_SCHED_YIELD] = k_sched_yield,
|
||||||
[SYSCALL_MMAP] = k_mmap,
|
[SYSCALL_MMAP] = k_mmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
syscall_handler set_syscall_handler(long num, syscall_handler handler) {
|
syscall_handler set_syscall_handler(long num, syscall_handler handler) {
|
||||||
syscall_handler old = syscall_handlers[num];
|
syscall_handler old = syscall_handlers[num];
|
||||||
syscall_handlers[num] = handler;
|
syscall_handlers[num] = handler;
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
long syscall0(long num) {
|
long syscall0(long num) {
|
||||||
long retval = 0;
|
long retval = 0;
|
||||||
if(syscall_handlers[num])
|
if(syscall_handlers[num])
|
||||||
retval = syscall_handlers[num](0, 0, 0, 0, 0, 0);
|
retval = syscall_handlers[num](0, 0, 0, 0, 0, 0);
|
||||||
else
|
else
|
||||||
PANIC("Unknown syscall: %d()\n", num);
|
PANIC("Unknown syscall: %d()\n", num);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
long syscall1(long num, long a1) {
|
long syscall1(long num, long a1) {
|
||||||
long retval = 0;
|
long retval = 0;
|
||||||
if(syscall_handlers[num])
|
if(syscall_handlers[num])
|
||||||
retval = syscall_handlers[num](a1, 0, 0, 0, 0, 0);
|
retval = syscall_handlers[num](a1, 0, 0, 0, 0, 0);
|
||||||
else
|
else
|
||||||
PANIC("Unknown syscall: %d(%x)\n", num, a1);
|
PANIC("Unknown syscall: %d(%x)\n", num, a1);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
long syscall2(long num, long a1, long a2) {
|
long syscall2(long num, long a1, long a2) {
|
||||||
long retval = 0;
|
long retval = 0;
|
||||||
if(syscall_handlers[num])
|
if(syscall_handlers[num])
|
||||||
retval = syscall_handlers[num](a1, a2, 0, 0, 0, 0);
|
retval = syscall_handlers[num](a1, a2, 0, 0, 0, 0);
|
||||||
else
|
else
|
||||||
PANIC("Unknown syscall: %d(%x, %x)\n", num, a1, a2);
|
PANIC("Unknown syscall: %d(%x, %x)\n", num, a1, a2);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
long syscall3(long num, long a1, long a2, long a3) {
|
long syscall3(long num, long a1, long a2, long a3) {
|
||||||
long retval = 0;
|
long retval = 0;
|
||||||
if(syscall_handlers[num])
|
if(syscall_handlers[num])
|
||||||
retval = syscall_handlers[num](a1, a2, a3, 0, 0, 0);
|
retval = syscall_handlers[num](a1, a2, a3, 0, 0, 0);
|
||||||
else
|
else
|
||||||
PANIC("Unknown syscall: %d(%x, %x, %x)\n", num, a1, a2, a3);
|
PANIC("Unknown syscall: %d(%x, %x, %x)\n", num, a1, a2, a3);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
long syscall4(long num, long a1, long a2, long a3, long a4) {
|
long syscall4(long num, long a1, long a2, long a3, long a4) {
|
||||||
long retval = 0;
|
long retval = 0;
|
||||||
if(syscall_handlers[num])
|
if(syscall_handlers[num])
|
||||||
retval = syscall_handlers[num](a1, a2, a3, a4, 0, 0);
|
retval = syscall_handlers[num](a1, a2, a3, a4, 0, 0);
|
||||||
else
|
else
|
||||||
PANIC("Unknown syscall: %d(%x, %x, %x, %x)\n", num, a1, a2, a3, a4);
|
PANIC("Unknown syscall: %d(%x, %x, %x, %x)\n", num, a1, a2, a3, a4);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
long syscall5(long num, long a1, long a2, long a3, long a4, long a5) {
|
long syscall5(long num, long a1, long a2, long a3, long a4, long a5) {
|
||||||
long retval = 0;
|
long retval = 0;
|
||||||
if(syscall_handlers[num])
|
if(syscall_handlers[num])
|
||||||
retval = syscall_handlers[num](a1, a2, a3, a4, a5, 0);
|
retval = syscall_handlers[num](a1, a2, a3, a4, a5, 0);
|
||||||
else
|
else
|
||||||
PANIC("Unknown syscall: %d(%x, %x, %x, %x, %x)\n", num, a1, a2, a3, a4, a5);
|
PANIC("Unknown syscall: %d(%x, %x, %x, %x, %x)\n",
|
||||||
return retval;
|
num, a1, a2, a3, a4, a5
|
||||||
|
);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
long syscall6(long num, long a1, long a2, long a3, long a4, long a5, long a6) {
|
long syscall6(long num, long a1, long a2, long a3, long a4, long a5, long a6) {
|
||||||
long retval = 0;
|
long retval = 0;
|
||||||
if(syscall_handlers[num])
|
if(syscall_handlers[num])
|
||||||
retval = syscall_handlers[num](a1, a2, a3, a4, a5, a6);
|
retval = syscall_handlers[num](a1, a2, a3, a4, a5, a6);
|
||||||
else
|
else
|
||||||
PANIC("Unknown syscall: %d(%x, %x, %x, %x, %x, %x)\n", num, a1, a2, a3, a4, a5, a6);
|
PANIC("Unknown syscall: %d(%x, %x, %x, %x, %x, %x)\n",
|
||||||
return retval;
|
num, a1, a2, a3, a4, a5, a6
|
||||||
|
);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t auxv[] = {0};
|
size_t auxv[] = {0};
|
||||||
|
|
||||||
void musl_init() {
|
void musl_init() {
|
||||||
__libc.auxv = auxv;
|
__libc.auxv = auxv;
|
||||||
}
|
}
|
@ -5,27 +5,42 @@ static long _brk = KERNEL_BRK0;
|
|||||||
static long _mmap = KERNEL_MMAP;
|
static long _mmap = KERNEL_MMAP;
|
||||||
|
|
||||||
long k_brk(long brk, long, long, long, long, long) {
|
long k_brk(long brk, long, long, long, long, long) {
|
||||||
if(brk) {
|
if(brk) {
|
||||||
while(_brk < brk) {
|
while(_brk < brk) {
|
||||||
vmm_set_page(kernel_P4, _brk, pmm_alloc(), PAGE_GLOBAL | PAGE_WRITE | PAGE_PRESENT);
|
vmm_set_page(kernel_P4,
|
||||||
_brk += PAGE_SIZE;
|
_brk,
|
||||||
}
|
pmm_alloc(),
|
||||||
|
PAGE_GLOBAL | PAGE_WRITE | PAGE_PRESENT
|
||||||
|
);
|
||||||
|
_brk += PAGE_SIZE;
|
||||||
}
|
}
|
||||||
return _brk;
|
}
|
||||||
|
return _brk;
|
||||||
}
|
}
|
||||||
|
|
||||||
long k_mmap(long addr, long length, long prot, long flags, long fd, long offset) {
|
long k_mmap(
|
||||||
(void)addr;
|
long addr,
|
||||||
(void)prot;
|
long length,
|
||||||
(void)flags;
|
long prot,
|
||||||
(void)offset;
|
long flags,
|
||||||
if(fd != -1)
|
long fd,
|
||||||
PANIC("Unknown mmap request\n");
|
long offset
|
||||||
long retval = _mmap;
|
) {
|
||||||
while(length > 0) {
|
(void)addr;
|
||||||
vmm_set_page(kernel_P4, _mmap, pmm_alloc(), PAGE_GLOBAL | PAGE_WRITE | PAGE_PRESENT);
|
(void)prot;
|
||||||
_mmap += PAGE_SIZE;
|
(void)flags;
|
||||||
length -= PAGE_SIZE;
|
(void)offset;
|
||||||
}
|
|
||||||
return retval;
|
if(fd != -1)
|
||||||
|
PANIC("Unknown mmap request\n");
|
||||||
|
long retval = _mmap;
|
||||||
|
while(length > 0) {
|
||||||
|
vmm_set_page(kernel_P4,
|
||||||
|
_mmap, pmm_alloc(),
|
||||||
|
PAGE_GLOBAL | PAGE_WRITE | PAGE_PRESENT
|
||||||
|
);
|
||||||
|
_mmap += PAGE_SIZE;
|
||||||
|
length -= PAGE_SIZE;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
}
|
}
|
@ -7,27 +7,27 @@
|
|||||||
uint64_t kernel_P4;
|
uint64_t kernel_P4;
|
||||||
|
|
||||||
void memory_init() {
|
void memory_init() {
|
||||||
kernel_P4 = (uint64_t)&BootP4;
|
kernel_P4 = (uint64_t)&BootP4;
|
||||||
|
|
||||||
uint64_t start, end;
|
uint64_t start, end;
|
||||||
uint32_t type, i = 0;
|
uint32_t type, i = 0;
|
||||||
while(!multiboot_get_memory_area(i++, &start, &end, &type)) {
|
while(!multiboot_get_memory_area(i++, &start, &end, &type)) {
|
||||||
for(uint64_t p = start; p < end; p += PAGE_SIZE) {
|
for(uint64_t p = start; p < end; p += PAGE_SIZE) {
|
||||||
uint64_t vaddr = (uint64_t)P2V(p);
|
uint64_t vaddr = (uint64_t)P2V(p);
|
||||||
uint64_t page = vmm_get_page(kernel_P4, vaddr);
|
uint64_t page = vmm_get_page(kernel_P4, vaddr);
|
||||||
if(page == (uint64_t)-1 || !(page & PAGE_PRESENT)) {
|
if(page == (uint64_t)-1 || !(page & PAGE_PRESENT)) {
|
||||||
uint16_t flags = PAGE_GLOBAL | PAGE_WRITE | PAGE_PRESENT;
|
uint16_t flags = PAGE_GLOBAL | PAGE_WRITE | PAGE_PRESENT;
|
||||||
vmm_set_page(kernel_P4, vaddr, p, flags);
|
vmm_set_page(kernel_P4, vaddr, p, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type != MMAP_FREE)
|
if(type != MMAP_FREE)
|
||||||
continue;
|
continue;
|
||||||
if(p >= V2P(&kernel_start) && p < V2P(&kernel_end))
|
if(p >= V2P(&kernel_start) && p < V2P(&kernel_end))
|
||||||
continue;
|
continue;
|
||||||
if(multiboot_page_used((uintptr_t)P2V(p)))
|
if(multiboot_page_used((uintptr_t)P2V(p)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pmm_free(p);
|
pmm_free(p);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -6,19 +6,19 @@
|
|||||||
uint64_t next = 0;
|
uint64_t next = 0;
|
||||||
|
|
||||||
void pmm_free(uint64_t page) {
|
void pmm_free(uint64_t page) {
|
||||||
*(uint64_t *)P2V(page) = next;
|
*(uint64_t *)P2V(page) = next;
|
||||||
next = page;
|
next = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t pmm_alloc() {
|
uint64_t pmm_alloc() {
|
||||||
if(!next) return 0;
|
if(!next) return 0;
|
||||||
uint64_t page = next;
|
uint64_t page = next;
|
||||||
next = *(uint64_t *)P2V(page);
|
next = *(uint64_t *)P2V(page);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t pmm_calloc() {
|
uint64_t pmm_calloc() {
|
||||||
uint64_t page = pmm_alloc();
|
uint64_t page = pmm_alloc();
|
||||||
memset(P2V(page), 0, PAGE_SIZE);
|
memset(P2V(page), 0, PAGE_SIZE);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
@ -17,80 +17,79 @@
|
|||||||
|
|
||||||
|
|
||||||
static int P1_exists(uint64_t P4, uint64_t addr) {
|
static int P1_exists(uint64_t P4, uint64_t addr) {
|
||||||
|
if (P4 && PRESENT(P4E(P4, addr)) && PRESENT(P3E(P4, addr)) && PRESENT(P2E(P4, addr)))
|
||||||
if (P4 && PRESENT(P4E(P4, addr)) && PRESENT(P3E(P4, addr)) && PRESENT(P2E(P4, addr)))
|
return 1;
|
||||||
return 1;
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int touch_P1(uint64_t P4, uint64_t addr, uint16_t flags) {
|
static int touch_P1(uint64_t P4, uint64_t addr, uint16_t flags) {
|
||||||
if (!P4) return -1;
|
if (!P4) return -1;
|
||||||
|
|
||||||
if(!PRESENT(P4E(P4, addr)) && (!(P4E(P4,addr) = pmm_calloc())))
|
if(!PRESENT(P4E(P4, addr)) && (!(P4E(P4,addr) = pmm_calloc())))
|
||||||
return -1;
|
return -1;
|
||||||
P4E(P4, addr) |= flags | PAGE_PRESENT;
|
P4E(P4, addr) |= flags | PAGE_PRESENT;
|
||||||
|
|
||||||
if(!PRESENT(P3E(P4, addr)) && (!(P3E(P4, addr) = pmm_calloc())))
|
if(!PRESENT(P3E(P4, addr)) && (!(P3E(P4, addr) = pmm_calloc())))
|
||||||
return -1;
|
return -1;
|
||||||
P3E(P4, addr) |= flags | PAGE_PRESENT;
|
P3E(P4, addr) |= flags | PAGE_PRESENT;
|
||||||
|
|
||||||
if(!PRESENT(P2E(P4, addr)) && (!(P2E(P4, addr) = pmm_calloc())))
|
if(!PRESENT(P2E(P4, addr)) && (!(P2E(P4, addr) = pmm_calloc())))
|
||||||
return -1;
|
return -1;
|
||||||
P2E(P4, addr) |= flags | PAGE_PRESENT;
|
P2E(P4, addr) |= flags | PAGE_PRESENT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t new_P4() {
|
uint64_t new_P4() {
|
||||||
uint64_t p4 = pmm_alloc();
|
uint64_t p4 = pmm_alloc();
|
||||||
memcpy(P2V(p4), (void *)kernel_P4, PAGE_SIZE);
|
memcpy(P2V(p4), (void *)kernel_P4, PAGE_SIZE);
|
||||||
return p4;
|
return p4;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t vmm_get_page(uint64_t P4, uint64_t addr) {
|
uint64_t vmm_get_page(uint64_t P4, uint64_t addr) {
|
||||||
if(P1_exists(P4, addr))
|
if(P1_exists(P4, addr))
|
||||||
return P1E(P4, addr);
|
return P1E(P4, addr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags) {
|
int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags) {
|
||||||
if(!P1_exists(P4, addr))
|
if(!P1_exists(P4, addr))
|
||||||
if(touch_P1(P4, addr, flags))
|
if(touch_P1(P4, addr, flags))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
P1E(P4, addr) = page | flags;
|
P1E(P4, addr) = page | flags;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vmm_clear_page(uint64_t P4, uint64_t addr, int free) {
|
void vmm_clear_page(uint64_t P4, uint64_t addr, int free) {
|
||||||
if(!P1_exists(P4, addr))
|
if(!P1_exists(P4, addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint64_t *pt;
|
uint64_t *pt;
|
||||||
|
|
||||||
P1E(P4, addr) = 0;
|
P1E(P4, addr) = 0;
|
||||||
|
|
||||||
if(!free)
|
if(!free)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pt = PT(P2E(P4, addr));
|
pt = PT(P2E(P4, addr));
|
||||||
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
||||||
if(pt[i])
|
if(pt[i])
|
||||||
return;
|
return;
|
||||||
pmm_free(MASK_FLAGS(P2E(P4, addr)));
|
pmm_free(MASK_FLAGS(P2E(P4, addr)));
|
||||||
P2E(P4, addr) = 0;
|
P2E(P4, addr) = 0;
|
||||||
|
|
||||||
pt = PT(P3E(P4, addr));
|
pt = PT(P3E(P4, addr));
|
||||||
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
||||||
if(pt[i])
|
if(pt[i])
|
||||||
return;
|
return;
|
||||||
pmm_free(MASK_FLAGS(P3E(P4, addr)));
|
pmm_free(MASK_FLAGS(P3E(P4, addr)));
|
||||||
P3E(P4, addr) = 0;
|
P3E(P4, addr) = 0;
|
||||||
|
|
||||||
pt = PT(P4E(P4, addr));
|
pt = PT(P4E(P4, addr));
|
||||||
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
||||||
if(pt[i])
|
if(pt[i])
|
||||||
return;
|
return;
|
||||||
pmm_free(MASK_FLAGS(P4E(P4, addr)));
|
pmm_free(MASK_FLAGS(P4E(P4, addr)));
|
||||||
P4E(P4, addr) = 0;
|
P4E(P4, addr) = 0;
|
||||||
}
|
}
|
@ -3,14 +3,14 @@
|
|||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
struct swtch_stack {
|
struct swtch_stack {
|
||||||
uint64_t RBP;
|
uint64_t RBP;
|
||||||
uint64_t RBX;
|
uint64_t RBX;
|
||||||
uint64_t R12;
|
uint64_t R12;
|
||||||
uint64_t R13;
|
uint64_t R13;
|
||||||
uint64_t R14;
|
uint64_t R14;
|
||||||
uint64_t R15;
|
uint64_t R15;
|
||||||
uint64_t RBP2;
|
uint64_t RBP2;
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint64_t next_pid = 1;
|
static uint64_t next_pid = 1;
|
||||||
@ -18,19 +18,19 @@ static uint64_t next_pid = 1;
|
|||||||
struct process *current_proc;
|
struct process *current_proc;
|
||||||
|
|
||||||
struct process *new_process(void (*function)(void)) {
|
struct process *new_process(void (*function)(void)) {
|
||||||
struct process *p = P2V(pmm_calloc());
|
struct process *p = P2V(pmm_calloc());
|
||||||
p->pid = next_pid++;
|
p->pid = next_pid++;
|
||||||
p->stack_ptr = incptr(p, PAGE_SIZE - sizeof(struct swtch_stack));
|
p->stack_ptr = incptr(p, PAGE_SIZE - sizeof(struct swtch_stack));
|
||||||
p->q_next = 0;
|
p->q_next = 0;
|
||||||
p->P4 = new_P4();
|
p->P4 = new_P4();
|
||||||
|
|
||||||
struct swtch_stack *stck = p->stack_ptr;
|
struct swtch_stack *stck = p->stack_ptr;
|
||||||
stck->RBP = (uint64_t)&stck->RBP2;
|
stck->RBP = (uint64_t)&stck->RBP2;
|
||||||
stck->ret = (uint64_t)function;
|
stck->ret = (uint64_t)function;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct process *proc() {
|
struct process *proc() {
|
||||||
return current_proc;
|
return current_proc;
|
||||||
}
|
}
|
@ -2,52 +2,52 @@
|
|||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
struct process *first;
|
struct process *first;
|
||||||
struct process *last;
|
struct process *last;
|
||||||
} run_q = {0,0};
|
} run_q = {0,0};
|
||||||
|
|
||||||
static struct process *scheduler_proc;
|
static struct process *scheduler_proc;
|
||||||
|
|
||||||
static struct process *scheduler_next() {
|
static struct process *scheduler_next() {
|
||||||
struct process *ret = run_q.first;
|
struct process *ret = run_q.first;
|
||||||
if(run_q.first && !(run_q.first = run_q.first->q_next))
|
if(run_q.first && !(run_q.first = run_q.first->q_next))
|
||||||
run_q.last = 0;
|
run_q.last = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduler_insert(struct process *new) {
|
void scheduler_insert(struct process *new) {
|
||||||
if(run_q.last) {
|
if(run_q.last) {
|
||||||
run_q.last->q_next = new;
|
run_q.last->q_next = new;
|
||||||
run_q.last = new;
|
run_q.last = new;
|
||||||
} else {
|
} else {
|
||||||
run_q.first = run_q.last = new;
|
run_q.first = run_q.last = new;
|
||||||
}
|
}
|
||||||
new->q_next = 0;
|
new->q_next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduler() {
|
void scheduler() {
|
||||||
while(1) {
|
while(1) {
|
||||||
struct process *new = 0;
|
struct process *new = 0;
|
||||||
while(!(new = scheduler_next()));
|
while(!(new = scheduler_next()));
|
||||||
|
|
||||||
current_proc = new;
|
current_proc = new;
|
||||||
write_cr3(new->P4);
|
write_cr3(new->P4);
|
||||||
switch_stack(&scheduler_proc->stack_ptr, &new->stack_ptr);
|
switch_stack(&scheduler_proc->stack_ptr, &new->stack_ptr);
|
||||||
|
|
||||||
scheduler_insert(current_proc);
|
scheduler_insert(current_proc);
|
||||||
current_proc = 0;
|
current_proc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long k_sched_yield(long, long, long, long, long, long) {
|
long k_sched_yield(long, long, long, long, long, long) {
|
||||||
switch_stack(¤t_proc->stack_ptr, &scheduler_proc->stack_ptr);
|
switch_stack(¤t_proc->stack_ptr, &scheduler_proc->stack_ptr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_scheduler() {
|
void start_scheduler() {
|
||||||
scheduler_proc = new_process(scheduler);
|
scheduler_proc = new_process(scheduler);
|
||||||
scheduler_proc->pid = (uint64_t)-1;
|
scheduler_proc->pid = (uint64_t)-1;
|
||||||
|
|
||||||
uint64_t stack;
|
uint64_t stack;
|
||||||
switch_stack(&stack, &scheduler_proc->stack_ptr);
|
switch_stack(&stack, &scheduler_proc->stack_ptr);
|
||||||
}
|
}
|
@ -11,96 +11,125 @@
|
|||||||
#define STEP_X(ctx) 1
|
#define STEP_X(ctx) 1
|
||||||
#define STEP_Y(ctx) (ctx)->pitch
|
#define STEP_Y(ctx) (ctx)->pitch
|
||||||
|
|
||||||
void putpixel(gfx_context *ctx, uint64_t x, uint64_t y, uint32_t clr) {
|
void putpixel(
|
||||||
if(x >= ctx->width || y >= ctx->height) return;
|
gfx_context *ctx,
|
||||||
uint32_t *fb = (uint32_t *)ctx->buffer;
|
uint64_t x, uint64_t y,
|
||||||
|
uint32_t clr
|
||||||
|
) {
|
||||||
|
if(x >= ctx->width || y >= ctx->height) return;
|
||||||
|
uint32_t *fb = (uint32_t *)ctx->buffer;
|
||||||
|
fb[PXL(ctx, x, y)] = clr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_line(
|
||||||
|
gfx_context *ctx,
|
||||||
|
uint64_t x0, uint64_t x1,
|
||||||
|
uint64_t y0, uint64_t y1,
|
||||||
|
uint32_t clr
|
||||||
|
) {
|
||||||
|
int64_t dx = x1 > x0 ? x1 - x0 : x0 - x1;
|
||||||
|
int64_t dy = y1 > y0 ? y1 - y0 : y0 - y1;
|
||||||
|
int sx = x1 > x0 ? 1 : -1;
|
||||||
|
int sy = y1 > y0 ? 1 : -1;
|
||||||
|
uint64_t x = x0, y = y0;
|
||||||
|
int64_t diff = dx - dy;
|
||||||
|
uint32_t *fb = (uint32_t *)ctx->buffer;
|
||||||
|
while(1) {
|
||||||
fb[PXL(ctx, x, y)] = clr;
|
fb[PXL(ctx, x, y)] = clr;
|
||||||
|
if(x == x1 && y == y1) break;
|
||||||
|
|
||||||
|
if((2*diff) > -dy) {
|
||||||
|
diff -= dy;
|
||||||
|
x += sx;
|
||||||
|
} else {
|
||||||
|
diff += dx;
|
||||||
|
y += sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_line(gfx_context *ctx, uint64_t x0, uint64_t x1, uint64_t y0, uint64_t y1, uint32_t clr) {
|
void draw_rect(
|
||||||
int64_t dx = x1 > x0 ? x1 - x0 : x0 - x1;
|
gfx_context *ctx,
|
||||||
int64_t dy = y1 > y0 ? y1 - y0 : y0 - y1;
|
uint64_t x, uint64_t y,
|
||||||
int sx = x1 > x0 ? 1 : -1;
|
uint64_t width, uint64_t height,
|
||||||
int sy = y1 > y0 ? 1 : -1;
|
uint32_t clr
|
||||||
uint64_t x = x0, y = y0;
|
) {
|
||||||
int64_t diff = dx - dy;
|
uint32_t *fb = (uint32_t *)ctx->buffer;
|
||||||
uint32_t *fb = (uint32_t *)ctx->buffer;
|
uint64_t l1 = PXL(ctx, x, y);
|
||||||
while(1) {
|
uint64_t l2 = PXL(ctx, x, y + height);
|
||||||
fb[PXL(ctx, x, y)] = clr;
|
for(uint64_t _x = 0; _x <= width; _x++) {
|
||||||
if(x == x1 && y == y1) break;
|
fb[l1] = fb[l2] = clr;
|
||||||
|
l1 += STEP_X(ctx);
|
||||||
if((2*diff) > -dy) {
|
l2 += STEP_X(ctx);
|
||||||
diff -= dy;
|
}
|
||||||
x += sx;
|
l1 = PXL(ctx, x, y);
|
||||||
} else {
|
l2 = PXL(ctx, x + width, y);
|
||||||
diff += dx;
|
for(uint64_t _y = 0; _y <= height; _y++) {
|
||||||
y += sy;
|
fb[l1] = fb[l2] = clr;
|
||||||
}
|
l1 += STEP_Y(ctx);
|
||||||
}
|
l2 += STEP_Y(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_rect(gfx_context *ctx, uint64_t x, uint64_t y, uint64_t width, uint64_t height, uint32_t clr) {
|
void fill_rect(
|
||||||
uint32_t *fb = (uint32_t *)ctx->buffer;
|
gfx_context *ctx,
|
||||||
uint64_t l1 = PXL(ctx, x, y);
|
uint64_t x, uint64_t y,
|
||||||
uint64_t l2 = PXL(ctx, x, y + height);
|
uint64_t width, uint64_t height,
|
||||||
for(uint64_t _x = 0; _x <= width; _x++) {
|
uint32_t clr
|
||||||
fb[l1] = fb[l2] = clr;
|
) {
|
||||||
l1 += STEP_X(ctx);
|
uint32_t *fb = (uint32_t *)ctx->buffer;
|
||||||
l2 += STEP_X(ctx);
|
uint64_t loc = PXL(ctx, x, y);
|
||||||
}
|
for(uint64_t _y = 0; _y <= height; _y++) {
|
||||||
l1 = PXL(ctx, x, y);
|
for(uint64_t _x = 0; _x <= width; _x += STEP_X(ctx)) {
|
||||||
l2 = PXL(ctx, x + width, y);
|
fb[loc + _x] = clr;
|
||||||
for(uint64_t _y = 0; _y <= height; _y++) {
|
|
||||||
fb[l1] = fb[l2] = clr;
|
|
||||||
l1 += STEP_Y(ctx);
|
|
||||||
l2 += STEP_Y(ctx);
|
|
||||||
}
|
}
|
||||||
|
loc += STEP_Y(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_rect(gfx_context *ctx, uint64_t x, uint64_t y, uint64_t width, uint64_t height, uint32_t clr) {
|
void putCharacter(
|
||||||
uint32_t *fb = (uint32_t *)ctx->buffer;
|
gfx_context *ctx,
|
||||||
uint64_t loc = PXL(ctx, x, y);
|
uint64_t x, uint64_t y,
|
||||||
for(uint64_t _y = 0; _y <= height; _y++) {
|
uint32_t clr_fg, uint32_t clr_bg,
|
||||||
for(uint64_t _x = 0; _x <= width; _x += STEP_X(ctx)) {
|
char c
|
||||||
fb[loc + _x] = clr;
|
) {
|
||||||
}
|
unsigned char *chr = c ? font[(int)c-0x20]: font[0];
|
||||||
loc += STEP_Y(ctx);
|
if(x >= ctx->width || y >= ctx->height) return;
|
||||||
}
|
uint32_t *fb = (uint32_t *)ctx->buffer;
|
||||||
}
|
uint64_t loc = y * ctx->pitch + x;
|
||||||
|
for(int row = 0; row < 16; row++) {
|
||||||
void putCharacter(gfx_context *ctx, uint64_t x, uint64_t y, uint32_t clr_fg, uint32_t clr_bg, char c) {
|
for(int col = 0; col < 8; col++) {
|
||||||
unsigned char *chr = c ? font[(int)c-0x20]: font[0];
|
fb[loc+col] = ((chr[row]>>(7-col))&0x1) ? clr_fg : clr_bg;
|
||||||
if(x >= ctx->width || y >= ctx->height) return;
|
|
||||||
uint32_t *fb = (uint32_t *)ctx->buffer;
|
|
||||||
uint64_t loc = y * ctx->pitch + x;
|
|
||||||
for(int row = 0; row < 16; row++) {
|
|
||||||
for(int col = 0; col < 8; col++) {
|
|
||||||
fb[loc+col] = ((chr[row]>>(7-col))&0x1) ? clr_fg : clr_bg;
|
|
||||||
}
|
|
||||||
loc += ctx->pitch;
|
|
||||||
}
|
}
|
||||||
|
loc += ctx->pitch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip(gfx_context *ctx) {
|
void flip(gfx_context *ctx) {
|
||||||
for(uint64_t y = 0; y < ctx->height; y++) {
|
for(uint64_t y = 0; y < ctx->height; y++) {
|
||||||
memcpy(
|
memcpy(
|
||||||
incptr(ctx->addr, y*ctx->pitch*ctx->bpp),
|
incptr(ctx->addr, y*ctx->pitch*ctx->bpp),
|
||||||
incptr(ctx->buffer, y*ctx->pitch*ctx->bpp),
|
incptr(ctx->buffer, y*ctx->pitch*ctx->bpp),
|
||||||
ctx->width*ctx->bpp);
|
ctx->width*ctx->bpp
|
||||||
}
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx_context *framebuffer_make_subcontext(gfx_context *ctx, uint64_t x, uint64_t y, uint64_t width, uint64_t height) {
|
gfx_context *framebuffer_make_subcontext(
|
||||||
gfx_context *out = malloc(sizeof(gfx_context));
|
gfx_context *ctx,
|
||||||
uint64_t loc = y * ctx->pitch + x;
|
uint64_t x, uint64_t y,
|
||||||
|
uint64_t width, uint64_t height
|
||||||
|
) {
|
||||||
|
gfx_context *out = malloc(sizeof(gfx_context));
|
||||||
|
uint64_t loc = y * ctx->pitch + x;
|
||||||
|
|
||||||
out->width = width;
|
out->width = width;
|
||||||
out->height = height;
|
out->height = height;
|
||||||
out->bpp = ctx->bpp;
|
out->bpp = ctx->bpp;
|
||||||
out->pitch = ctx->pitch;
|
out->pitch = ctx->pitch;
|
||||||
out->addr = incptr(ctx->addr, loc*ctx->bpp);
|
out->addr = incptr(ctx->addr, loc*ctx->bpp);
|
||||||
out->size = ctx->pitch * height * ctx->bpp;
|
out->size = ctx->pitch * height * ctx->bpp;
|
||||||
out->buffer = calloc(1, out->size);
|
out->buffer = calloc(1, out->size);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
@ -2,13 +2,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t bpp;
|
uint32_t bpp;
|
||||||
uint32_t pitch;
|
uint32_t pitch;
|
||||||
void *addr;
|
void *addr;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
size_t size;
|
size_t size;
|
||||||
} gfx_context;
|
} gfx_context;
|
||||||
|
|
||||||
#define RGB(r, g, b) (((uint32_t) (r<<16) + (g<<8) + (b)))
|
#define RGB(r, g, b) (((uint32_t) (r<<16) + (g<<8) + (b)))
|
||||||
|
@ -10,25 +10,29 @@ extern long syscall5(long, long, long, long, long, long);
|
|||||||
extern long syscall6(long, long, long, long, long, long, long);
|
extern long syscall6(long, long, long, long, long, long, long);
|
||||||
|
|
||||||
static __inline long __syscall0(long n) {
|
static __inline long __syscall0(long n) {
|
||||||
return syscall0(n);
|
return syscall0(n);
|
||||||
}
|
}
|
||||||
static __inline long __syscall1(long n, long a1) {
|
static __inline long __syscall1(long n, long a1) {
|
||||||
return syscall1(n, a1);
|
return syscall1(n, a1);
|
||||||
}
|
}
|
||||||
static __inline long __syscall2(long n, long a1, long a2) {
|
static __inline long __syscall2(long n, long a1, long a2) {
|
||||||
return syscall2(n, a1, a2);
|
return syscall2(n, a1, a2);
|
||||||
}
|
}
|
||||||
static __inline long __syscall3(long n, long a1, long a2, long a3) {
|
static __inline long __syscall3(long n, long a1, long a2, long a3) {
|
||||||
return syscall3(n, a1, a2, a3);
|
return syscall3(n, a1, a2, a3);
|
||||||
}
|
}
|
||||||
static __inline long __syscall4(long n, long a1, long a2, long a3, long a4) {
|
static __inline long __syscall4(long n, long a1, long a2, long a3, long a4) {
|
||||||
return syscall4(n, a1, a2, a3, a4);
|
return syscall4(n, a1, a2, a3, a4);
|
||||||
}
|
}
|
||||||
static __inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) {
|
static __inline long __syscall5(long n, long a1, long a2, long a3, long a4,
|
||||||
return syscall5(n, a1, a2, a3, a4, a5);
|
long a5
|
||||||
|
) {
|
||||||
|
return syscall5(n, a1, a2, a3, a4, a5);
|
||||||
}
|
}
|
||||||
static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) {
|
static __inline long __syscall6(long n, long a1, long a2, long a3, long a4,
|
||||||
return syscall6(n, a1, a2, a3, a4, a5, a6);
|
long a5, long a6
|
||||||
|
) {
|
||||||
|
return syscall6(n, a1, a2, a3, a4, a5, a6);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VDSO_USEFUL
|
#define VDSO_USEFUL
|
||||||
|
Loading…
x
Reference in New Issue
Block a user