genusOS/src/main.c

346 lines
7.9 KiB
C

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "../include/limine.h"
#include "prompt/lex.h"
#include "prompt/file.h"
void print_tok(struct token* tok);
#include "acpi.h"
#include "ahci.h"
#include "alloc.h"
#include "apic.h"
#include "common.h"
#include "fat32.h"
#include "print.h"
#include "lib/stdio.h"
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup
// code
__attribute__((
used,
section(".limine_requests"))) static volatile u64 limine_base_revision[] =
LIMINE_BASE_REVISION(4);
__attribute__((
used,
section(
".limine_requests"))) static volatile struct limine_framebuffer_request
fb_req = {.id = LIMINE_FRAMEBUFFER_REQUEST_ID, .revision = 0};
__attribute__((
used,
section(".limine_requests"))) static volatile struct limine_hhdm_request
hhdm_req = {.id = LIMINE_HHDM_REQUEST_ID, .revision = 0};
__attribute__((
used,
section(".limine_requests"))) static volatile struct limine_rsdp_request
rsdp_req = {.id = LIMINE_RSDP_REQUEST_ID, .revision = 0};
u64 hhdm_offset;
__attribute__((used, section(".limine_requests_start"))) static volatile u64
limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
__attribute__((used, section(".limine_requests_end"))) static volatile u64
limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
void *memcpy(void *restrict dst, const void *src, size_t n) {
u8 *restrict pdst = (u8 *restrict)dst;
const u8 *restrict psrc = (const u8 *restrict)src;
for (size_t i = 0; i < n; i++) {
pdst[i] = psrc[i];
}
return dst;
}
void *memset(void *s, int c, size_t n) {
u8 *p = (u8 *)s;
for (size_t i = 0; i < n; i++) {
p[i] = (u8)c;
}
return s;
}
void *memmove(void *dst, const void *src, size_t n) {
u8 *restrict pdst = (u8 *restrict)dst;
const u8 *restrict psrc = (const u8 *restrict)src;
if (src > dst) {
for (size_t i = 0; i < n; i++) {
pdst[i] = psrc[i];
}
} else if (src < dst) {
for (size_t i = n; i > 0; i--) {
pdst[i - 1] = psrc[i - 1];
}
}
return dst;
}
int memcmp(const void *s1, const void *s2, size_t n) {
const u8 *p1 = (const u8 *)s1;
const u8 *p2 = (const u8 *)s2;
for (size_t i = 0; i < n; i++) {
if (p1[i] != p2[i]) {
return p1[i] < p2[i] ? -1 : 1;
}
}
return 0;
}
void hang() {
for (;;) {
asm("hlt");
}
}
struct limine_framebuffer *fb;
void draw() {
for (size_t y = 0; y < fb->height; y++) {
for (size_t x = 0; x < fb->width; x++) {
volatile u32 *fb_ptr = fb->address;
int tone = ((x ^ y) & 0xFF);
fb_ptr[y * fb->width + x] = (tone << 16);
}
}
}
extern void init_idt(void);
extern u32 fg;
extern u32 bg;
void enable_ps2_keyboard_interrupts(void) {
// Read PS/2 configuration byte
outb(0x64, 0x20);
while (!(inb(0x64) & 0x01))
; // Wait for data
u8 config = inb(0x60);
// Enable keyboard interrupt (bit 0) and clock (clear bit 4)
config |= 0x01; // Enable first port interrupt
config &= ~0x10; // Enable first port clock
// Write config back
outb(0x64, 0x60);
outb(0x60, config);
// Enable keyboard port
outb(0x64, 0xAE);
}
void ls(int port, int indent, fat32_vol_t* vol, u32 cluster) {
u32 cluster_size = vol->sectors_per_cluster * TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE;
u8* lsbuff = alloc(4096);
do {
fat32_read_cluster(port, vol, cluster, lsbuff);
fat32_dirent_t* dir = (fat32_dirent_t*) lsbuff;
u32 cnt = cluster_size / sizeof(fat32_dirent_t);
for(size_t i = 0; i < cnt; i++) {
if(dir[i].name[0] == 0x00) {
return;
}
for(int i = 0; i < indent; i++) {
printf("----");
}
printf("[%d] ", i);
if(dir[i].name[0] == 0xE5) {
printf("[DELETED]\n");
continue;
}
if((dir[i].attr & 0x3F) == ATTR_LFN) {
printf("Long File Name\n", i);
continue;
}
if(dir[i].attr & ATTR_VOL_ID) {
printf("Volume ID\n");
continue;
}
for(size_t c = 0; c < 8 && dir[i].name[c] != ' '; c++) {
put(dir[i].name[c]);
}
if(dir[i].ext[0] && dir[i].ext[0] != ' ') {
put('.');
for(size_t c = 0; c < 8 && dir[i].ext[c] != ' '; c++) {
put(dir[i].ext[c]);
}
}
printf(" %d", dir[i].file_size);
put('\n');
if(dir[i].attr & ATTR_DIR) {
if(dir[i].name[0] != '.')
ls(port, indent + 1, vol, dir[i].cluster_low + ((u32)(dir[i].cluster_high) << 16));
}
}
cluster = fat32_next(port, vol, cluster);
} while(!fat32_is_eof(cluster));
printf("All Done\n");
}
void kmain() {
if (LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
hang();
}
if (fb_req.response == NULL || fb_req.response->framebuffer_count < 1) {
hang();
}
fb = fb_req.response->framebuffers[0];
draw();
print_init(fb);
init_idt();
fg = 0xFFFFFF;
bg = 0x000000;
if (!hhdm_req.response) {
print("Failed to get higher half direct mapping\n.");
hang();
}
hhdm_offset = hhdm_req.response->offset;
if (!rsdp_req.response) {
print("Failed to find rsdp\n.");
hang();
}
alloc_init();
rsdp = (struct acpi_rsdp_header *)(rsdp_req.response->address);
print("Found RSDP @ 0x");
print64((u64)rsdp);
put('\n');
print("With signature: ");
printn((char *)rsdp->signature, sizeof(rsdp->signature));
print(" v");
print8(rsdp->revision);
print("\nRSDT at 0x");
struct acpi_rsdt *rsdt =
(struct acpi_rsdt *)((rsdp->revision ? rsdp->ptr64 : rsdp->ptr32) +
hhdm_offset);
print64((u64)rsdt);
print("\nSDT Signature: ");
printn((const char *)rsdt->signature, sizeof(rsdt->signature));
print("\nAPIC Local Base: ");
/* I should check cpuid to ensure its supported but it will
* be for my machines ;^) */
/* APIC stuff */
apic_enable();
print("APIC Enabled\n");
ioapic_init();
asm volatile("sti");
ahci_init();
i8 port = -1;
for(u8 i = 0; i < 32; i++) {
if(ahci_port_active(i)) {
// assume we want the first port
if(port < 0)
port = i;
printf("Port %d is active!\n", i);
}
}
if(port < 0) {
printf("Couldn't find a port to read the FS from :(\n");
hang();
}
fat32_mbr_t* mbr = alloc(1<<12);
ahci_read(port, 0, 1, mbr);
i8 bootpart = -1;
fat32_mbr_partition_t bpart;
printf("Fat32 Partitions:\n");
for(size_t i = 0; i < 4; i++) {
fat32_mbr_partition_t* part = &mbr->partitions[i];
u32 lba_start = part->lba_start;
u32 lba_end = lba_start + part->sector_count;
if(bootpart < 0 && part->status == 0x80) {
bootpart = i;
bpart = *part;
}
printf("\t%s, %d Sectors [0x%x-0x%x]\n",
(part->status == 0x80)? "[BOOTABLE]" : "[UNBOOTABLE]",
part->sector_count,
lba_start, lba_end);
}
if(bootpart < 0) {
printf("Failed to find boot partition :(\n");
}
// reuse buffer
fat32_bpb_t* bpb = (fat32_bpb_t*) mbr;
mbr = NULL;
// hardcode for now :(
u32 part_lba = 2048;
ahci_read(port, part_lba, 1, bpb);
fat32_vol_t vol = vol_from_bpb(bpb, part_lba);
u64 root_lba = fat32_cluster_to_lba(&vol, vol.root_cluster);
printf("root_lba=%u\n", (u32)root_lba);
u8 *raw = alloc(4096);
ahci_read(port, root_lba, vol.sectors_per_cluster, raw);
printf("raw: ");
for(int i = 0; i < 64; i++)
printf("%x ", raw[i]);
printf("\n");
ls(port, 0, &vol, vol.root_cluster);
struct FILE* fortune = fat32_find_path(port, &vol, "fort/fortu.ne");
printf("Fortune size: %d\n", fortune->info.file_size);
u8* fort = slurp(fortune);
printn(fort, fortune->info.file_size);
free(fort);
hang();
}