#include #include #include #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(); }