346 lines
7.9 KiB
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();
|
|
}
|