added preliminary support for FAT32
This commit is contained in:
parent
c6b416d2d4
commit
a83b935482
@ -16,13 +16,14 @@ make -C limine
|
|||||||
./limine/limine bios-install image.hdd
|
./limine/limine bios-install image.hdd
|
||||||
|
|
||||||
# Format the image as fat32.
|
# Format the image as fat32.
|
||||||
mformat -i image.hdd@@1M
|
mformat -i image.hdd@@1M -F
|
||||||
|
|
||||||
# Make relevant subdirectories.
|
# Make relevant subdirectories.
|
||||||
mmd -i image.hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine
|
mmd -i image.hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine ::/fort
|
||||||
|
|
||||||
# Copy over the relevant files.
|
# Copy over the relevant files.
|
||||||
mcopy -i image.hdd@@1M bin/os ::/boot
|
mcopy -i image.hdd@@1M bin/os ::/boot
|
||||||
mcopy -i image.hdd@@1M limine.conf limine/limine-bios.sys ::/boot/limine
|
mcopy -i image.hdd@@1M limine.conf limine/limine-bios.sys ::/boot/limine
|
||||||
mcopy -i image.hdd@@1M limine/BOOTX64.EFI ::/EFI/BOOT
|
mcopy -i image.hdd@@1M limine/BOOTX64.EFI ::/EFI/BOOT
|
||||||
mcopy -i image.hdd@@1M limine/BOOTIA32.EFI ::/EFI/BOOT
|
mcopy -i image.hdd@@1M limine/BOOTIA32.EFI ::/EFI/BOOT
|
||||||
|
mcopy -i image.hdd@@1M fortune ::/fort/fortu.ne
|
||||||
|
|||||||
BIN
mnt/EFI/BOOT/BOOTIA32.EFI
Normal file
BIN
mnt/EFI/BOOT/BOOTIA32.EFI
Normal file
Binary file not shown.
BIN
mnt/EFI/BOOT/BOOTX64.EFI
Normal file
BIN
mnt/EFI/BOOT/BOOTX64.EFI
Normal file
Binary file not shown.
BIN
mnt/boot/limine/limine-bios.sys
Normal file
BIN
mnt/boot/limine/limine-bios.sys
Normal file
Binary file not shown.
5
mnt/boot/limine/limine.conf
Normal file
5
mnt/boot/limine/limine.conf
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
timeout: 5
|
||||||
|
|
||||||
|
/LispOS
|
||||||
|
protocol: limine
|
||||||
|
path: boot():/boot/os
|
||||||
BIN
mnt/boot/os
Executable file
BIN
mnt/boot/os
Executable file
Binary file not shown.
BIN
obj/src/int.c.o
BIN
obj/src/int.c.o
Binary file not shown.
@ -1,19 +1,19 @@
|
|||||||
obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \
|
obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \
|
||||||
src/prompt/file.h src/acpi.h src/common.h src/alloc.h src/apic.h \
|
src/prompt/file.h src/acpi.h src/common.h src/ahci.h src/alloc.h \
|
||||||
src/kbd.h src/map.h src/print.h src/lib/stdio.h src/lib/malloc.h \
|
src/apic.h src/fat32.h src/lib/stdio.h src/lib/malloc.h \
|
||||||
src/lib/../common.h src/lib/../kbd.h src/lib/../print.h
|
src/lib/../common.h src/lib/../kbd.h src/lib/../print.h src/print.h
|
||||||
src/../include/limine.h:
|
src/../include/limine.h:
|
||||||
src/prompt/lex.h:
|
src/prompt/lex.h:
|
||||||
src/prompt/file.h:
|
src/prompt/file.h:
|
||||||
src/acpi.h:
|
src/acpi.h:
|
||||||
src/common.h:
|
src/common.h:
|
||||||
|
src/ahci.h:
|
||||||
src/alloc.h:
|
src/alloc.h:
|
||||||
src/apic.h:
|
src/apic.h:
|
||||||
src/kbd.h:
|
src/fat32.h:
|
||||||
src/map.h:
|
|
||||||
src/print.h:
|
|
||||||
src/lib/stdio.h:
|
src/lib/stdio.h:
|
||||||
src/lib/malloc.h:
|
src/lib/malloc.h:
|
||||||
src/lib/../common.h:
|
src/lib/../common.h:
|
||||||
src/lib/../kbd.h:
|
src/lib/../kbd.h:
|
||||||
src/lib/../print.h:
|
src/lib/../print.h:
|
||||||
|
src/print.h:
|
||||||
|
|||||||
BIN
obj/src/main.c.o
BIN
obj/src/main.c.o
Binary file not shown.
6
run.sh
6
run.sh
@ -1,2 +1,6 @@
|
|||||||
qemu-system-x86_64 image.hdd
|
qemu-system-x86_64 \
|
||||||
|
-drive id=disk0,file=image.hdd,format=raw,if=none \
|
||||||
|
-device ich9-ahci,id=ahci0 \
|
||||||
|
-device ide-hd,drive=disk0,bus=ahci0.0
|
||||||
|
|
||||||
#/mnt/c/'Program Files'/qemu/qemu-system-x86_64.exe image.hdd
|
#/mnt/c/'Program Files'/qemu/qemu-system-x86_64.exe image.hdd
|
||||||
|
|||||||
492
src/ahci.c
Normal file
492
src/ahci.c
Normal file
@ -0,0 +1,492 @@
|
|||||||
|
#include "alloc.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "print.h"
|
||||||
|
#include "lib/stdio.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "lib/malloc.h"
|
||||||
|
|
||||||
|
#define PCI_CONFIG_ADDR 0xCF8
|
||||||
|
#define PCI_CONFIG_DATA 0xCFC
|
||||||
|
|
||||||
|
static u32 pci_read(u8 bus, u8 slot, u8 func, u8 offset) {
|
||||||
|
u32 addr = (1u << 31) | ((u32)bus << 16) | ((u32)slot << 11) |
|
||||||
|
((u32)func << 8) | (offset & 0xFC);
|
||||||
|
outd(PCI_CONFIG_ADDR, addr);
|
||||||
|
return ind(PCI_CONFIG_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pci_write(u8 bus, u8 slot, u8 func, u8 offset, u32 value) {
|
||||||
|
u32 addr = (1u << 31) | ((u32)bus << 16) | ((u32)slot << 11) |
|
||||||
|
((u32)func << 8) | (offset & 0xFC);
|
||||||
|
outd(PCI_CONFIG_ADDR, addr);
|
||||||
|
outd(PCI_CONFIG_DATA, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 dba;
|
||||||
|
u32 dbau;
|
||||||
|
u32 reserved;
|
||||||
|
u32 dbc; // byte count - 1, bit 31 = interrupt on completion
|
||||||
|
} hba_prdt_t;
|
||||||
|
|
||||||
|
#define AHCI_PRDT_PER_TABLE 8
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 cfis[64];
|
||||||
|
u8 acmd[16];
|
||||||
|
u8 reserved[48];
|
||||||
|
hba_prdt_t prdt[AHCI_PRDT_PER_TABLE];
|
||||||
|
} hba_cmd_table_t;
|
||||||
|
|
||||||
|
// hba_cmd_table_t size = 64 + 16 + 48 + (8 * 16) = 256 bytes
|
||||||
|
// two fit per 4KiB page
|
||||||
|
typedef struct {
|
||||||
|
u16 flags; // [4:0] FIS len in DWORDs, [6] write
|
||||||
|
u16 prdtl;
|
||||||
|
u32 prdbc;
|
||||||
|
u32 ctba;
|
||||||
|
u32 ctbau;
|
||||||
|
u32 reserved[4];
|
||||||
|
} hba_cmd_header_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 dsfis[28];
|
||||||
|
u8 pad0[4];
|
||||||
|
u8 psfis[20];
|
||||||
|
u8 pad1[12];
|
||||||
|
u8 rfis[20];
|
||||||
|
u8 pad2[4];
|
||||||
|
u8 sdbfis[8];
|
||||||
|
u8 ufis[64];
|
||||||
|
u8 reserved[96];
|
||||||
|
} hba_fis_t;
|
||||||
|
|
||||||
|
// sizeof(hba_fis_t) = 256 bytes
|
||||||
|
|
||||||
|
typedef volatile struct {
|
||||||
|
u32 clb, clbu;
|
||||||
|
u32 fb, fbu;
|
||||||
|
u32 is;
|
||||||
|
u32 ie;
|
||||||
|
u32 cmd;
|
||||||
|
u32 reserved0;
|
||||||
|
u32 tfd;
|
||||||
|
u32 sig;
|
||||||
|
u32 ssts;
|
||||||
|
u32 sctl;
|
||||||
|
u32 serr;
|
||||||
|
u32 sact;
|
||||||
|
u32 ci;
|
||||||
|
u32 sntf;
|
||||||
|
u32 fbs;
|
||||||
|
u32 reserved1[11];
|
||||||
|
u32 vendor[4];
|
||||||
|
} hba_port_t;
|
||||||
|
|
||||||
|
typedef volatile struct {
|
||||||
|
u32 cap;
|
||||||
|
u32 ghc;
|
||||||
|
u32 is;
|
||||||
|
u32 pi;
|
||||||
|
u32 vs;
|
||||||
|
u32 ccc_ctl;
|
||||||
|
u32 ccc_pts;
|
||||||
|
u32 em_loc;
|
||||||
|
u32 em_ctl;
|
||||||
|
u32 cap2;
|
||||||
|
u32 bohc;
|
||||||
|
u8 reserved[0xA0 - 0x2C];
|
||||||
|
u8 vendor[0x100 - 0xA0];
|
||||||
|
hba_port_t ports[32];
|
||||||
|
} hba_mem_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 fis_type; // 0x27
|
||||||
|
u8 c; // bit 7 = command
|
||||||
|
u8 command;
|
||||||
|
u8 featurel;
|
||||||
|
u8 lba0, lba1, lba2;
|
||||||
|
u8 device;
|
||||||
|
u8 lba3, lba4, lba5;
|
||||||
|
u8 featureh;
|
||||||
|
u8 countl, counth;
|
||||||
|
u8 icc;
|
||||||
|
u8 control;
|
||||||
|
u8 reserved[4];
|
||||||
|
} fis_reg_h2d_t;
|
||||||
|
|
||||||
|
#define ATA_CMD_READ_DMA_EXT 0x25
|
||||||
|
#define ATA_CMD_WRITE_DMA_EXT 0x35
|
||||||
|
#define ATA_CMD_IDENTIFY 0xEC
|
||||||
|
#define ATA_DEV_BUSY 0x80
|
||||||
|
#define ATA_DEV_DRQ 0x08
|
||||||
|
|
||||||
|
|
||||||
|
#define HBA_GHC_AE (1u << 31)
|
||||||
|
#define HBA_CMD_ST (1u << 0)
|
||||||
|
#define HBA_CMD_FRE (1u << 4)
|
||||||
|
#define HBA_CMD_FR (1u << 14)
|
||||||
|
#define HBA_CMD_CR (1u << 15)
|
||||||
|
#define HBA_IS_TFES (1u << 30) // task file error status
|
||||||
|
|
||||||
|
|
||||||
|
#define AHCI_MAX_PORTS 32
|
||||||
|
#define AHCI_CMD_SLOTS 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hba_cmd_header_t *cmd_list; // virtual, 1 page (1KB used)
|
||||||
|
hba_fis_t *fis; // virtual, fits after cmd_list
|
||||||
|
hba_cmd_table_t *cmd_tables[AHCI_CMD_SLOTS]; // virtual pointers
|
||||||
|
int active;
|
||||||
|
u64 sector_count;
|
||||||
|
u64 sector_size;
|
||||||
|
} ahci_port_t;
|
||||||
|
|
||||||
|
static hba_mem_t *hba;
|
||||||
|
static ahci_port_t ports[AHCI_MAX_PORTS];
|
||||||
|
|
||||||
|
static void port_stop(hba_port_t *port) {
|
||||||
|
port->cmd &= ~HBA_CMD_ST;
|
||||||
|
port->cmd &= ~HBA_CMD_FRE;
|
||||||
|
while (port->cmd & (HBA_CMD_CR | HBA_CMD_FR))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void port_start(hba_port_t *port) {
|
||||||
|
while (port->cmd & HBA_CMD_CR)
|
||||||
|
;
|
||||||
|
port->cmd |= HBA_CMD_FRE;
|
||||||
|
port->cmd |= HBA_CMD_ST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_free_slot(hba_port_t *port) {
|
||||||
|
u32 slots = port->sact | port->ci;
|
||||||
|
for (int i = 0; i < AHCI_CMD_SLOTS; i++)
|
||||||
|
if (!(slots & (1u << i)))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void port_init(int idx) {
|
||||||
|
hba_port_t *port = &hba->ports[idx];
|
||||||
|
ahci_port_t *p = &ports[idx];
|
||||||
|
|
||||||
|
port_stop(port);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Page 0: command list (1024 bytes) + FIS buffer (256 bytes)
|
||||||
|
//
|
||||||
|
// [0 .. 1023] : hba_cmd_header_t[32] (command list)
|
||||||
|
// [1024.. 1279] : hba_fis_t (received FIS)
|
||||||
|
//
|
||||||
|
// Both fit in one 4KiB page. FIS is 256-byte aligned because 1024
|
||||||
|
// is a multiple of 256.
|
||||||
|
//
|
||||||
|
u8 *page0 = (u8 *)alloc(4096);
|
||||||
|
memset(page0, 0, 4096);
|
||||||
|
|
||||||
|
p->cmd_list = (hba_cmd_header_t *)page0;
|
||||||
|
p->fis = (hba_fis_t *)(page0 + 1024);
|
||||||
|
|
||||||
|
u64 phys0 = virt_to_phys(page0);
|
||||||
|
u64 phys_fis = phys0 + 1024;
|
||||||
|
|
||||||
|
port->clb = (u32)(phys0);
|
||||||
|
port->clbu = (u32)(phys0 >> 32);
|
||||||
|
port->fb = (u32)(phys_fis);
|
||||||
|
port->fbu = (u32)(phys_fis >> 32);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Command tables: 256 bytes each, two per 4KiB page.
|
||||||
|
// 32 slots → 16 pages.
|
||||||
|
//
|
||||||
|
for (int i = 0; i < AHCI_CMD_SLOTS; i += 2) {
|
||||||
|
u8 *page = (u8 *)alloc(4096);
|
||||||
|
memset(page, 0, 4096);
|
||||||
|
|
||||||
|
u64 phys = virt_to_phys(page);
|
||||||
|
|
||||||
|
for (int j = 0; j < 2 && (i + j) < AHCI_CMD_SLOTS; j++) {
|
||||||
|
int slot = i + j;
|
||||||
|
hba_cmd_table_t *tbl = (hba_cmd_table_t *)(page + j * 256);
|
||||||
|
p->cmd_tables[slot] = tbl;
|
||||||
|
|
||||||
|
u64 tbl_phys = phys + j * 256;
|
||||||
|
p->cmd_list[slot].ctba = (u32)(tbl_phys);
|
||||||
|
p->cmd_list[slot].ctbau = (u32)(tbl_phys >> 32);
|
||||||
|
p->cmd_list[slot].prdtl = AHCI_PRDT_PER_TABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear pending errors and interrupts
|
||||||
|
port->serr = 0xFFFFFFFF;
|
||||||
|
port->is = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// Enable D2H register FIS interrupt + task file error
|
||||||
|
port->ie = (1u << 0) | HBA_IS_TFES;
|
||||||
|
|
||||||
|
port_start(port);
|
||||||
|
p->active = 1;
|
||||||
|
|
||||||
|
|
||||||
|
printf("AHCI: port %d initialized, sig=%x\n", idx, port->sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void port_identify(int idx) {
|
||||||
|
ahci_port_t *p = &ports[idx];
|
||||||
|
hba_port_t *port = &hba->ports[idx];
|
||||||
|
|
||||||
|
// IDENTIFY needs a 512-byte buffer; alloc gives us a page
|
||||||
|
u16 *buf = (u16 *)alloc(4096);
|
||||||
|
u64 phys = virt_to_phys(buf);
|
||||||
|
|
||||||
|
int slot = find_free_slot(port);
|
||||||
|
if (slot < 0) return;
|
||||||
|
|
||||||
|
hba_cmd_header_t *hdr = &p->cmd_list[slot];
|
||||||
|
hdr->flags = sizeof(fis_reg_h2d_t) / 4; // FIS length, no write bit
|
||||||
|
hdr->prdtl = 1;
|
||||||
|
hdr->prdbc = 0;
|
||||||
|
|
||||||
|
hba_cmd_table_t *tbl = p->cmd_tables[slot];
|
||||||
|
memset(tbl, 0, sizeof(hba_cmd_table_t));
|
||||||
|
|
||||||
|
tbl->prdt[0].dba = (u32)(phys);
|
||||||
|
tbl->prdt[0].dbau = (u32)(phys >> 32);
|
||||||
|
tbl->prdt[0].dbc = 511; // 512 bytes - 1, no interrupt bit needed
|
||||||
|
|
||||||
|
fis_reg_h2d_t *fis = (fis_reg_h2d_t *)tbl->cfis;
|
||||||
|
fis->fis_type = 0x27;
|
||||||
|
fis->c = (1 << 7);
|
||||||
|
fis->command = ATA_CMD_IDENTIFY;
|
||||||
|
fis->device = 0;
|
||||||
|
|
||||||
|
// Wait for idle
|
||||||
|
int spin = 0;
|
||||||
|
while ((port->tfd & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && ++spin < 1000000)
|
||||||
|
;
|
||||||
|
|
||||||
|
port->ci = (1u << slot);
|
||||||
|
|
||||||
|
while (port->ci & (1u << slot)) {
|
||||||
|
if (port->is & HBA_IS_TFES) {
|
||||||
|
printf("AHCI: identify error on port %d\n", idx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Word 100-103: 48-bit LBA sector count
|
||||||
|
p->sector_count = ((u64)buf[103] << 48) | ((u64)buf[102] << 32) |
|
||||||
|
((u64)buf[101] << 16) | ((u64)buf[100]);
|
||||||
|
|
||||||
|
|
||||||
|
// word 106 contains sector size info
|
||||||
|
u16 w106 = buf[106];
|
||||||
|
|
||||||
|
if (w106 & (1 << 14) && !(w106 & (1 << 15))) {
|
||||||
|
// words 117-118: logical sector size in words (if bit 12 of w106 is set)
|
||||||
|
if (w106 & (1 << 12)) {
|
||||||
|
u32 logical_size = ((u32)buf[118] << 16) | buf[117];
|
||||||
|
logical_size *= 2; // words to bytes
|
||||||
|
p->sector_size = logical_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("AHCI: port %d sections = %d\n", idx, p->sector_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// buf must be physically contiguous. For >AHCI_PRDT_PER_TABLE*4MB you'd need
|
||||||
|
// to split the request; at 8 PRDT entries of up to 4MB each that's 32MB max
|
||||||
|
// per call which is plenty for now.
|
||||||
|
static int ahci_rw(int idx, u64 lba, u32 sector_count, void *buf, int write) {
|
||||||
|
ahci_port_t *p = &ports[idx];
|
||||||
|
hba_port_t *port = &hba->ports[idx];
|
||||||
|
|
||||||
|
if (!p->active) {
|
||||||
|
print("AHCI: port not active\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int slot = find_free_slot(port);
|
||||||
|
if (slot < 0) {
|
||||||
|
print("AHCI: no free command slots\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hba_cmd_header_t *hdr = &p->cmd_list[slot];
|
||||||
|
hdr->flags = (u16)(sizeof(fis_reg_h2d_t) / 4);
|
||||||
|
if (write) hdr->flags |= (1 << 6);
|
||||||
|
hdr->prdbc = 0;
|
||||||
|
|
||||||
|
hba_cmd_table_t *tbl = p->cmd_tables[slot];
|
||||||
|
memset(tbl, 0, sizeof(hba_cmd_table_t));
|
||||||
|
|
||||||
|
// Fill PRDT — each entry covers up to 4MB (0x3FFFFF bytes + 1).
|
||||||
|
// We use 512KB chunks to stay conservative and keep entry count low.
|
||||||
|
#define CHUNK_SIZE (512 * 1024)
|
||||||
|
|
||||||
|
u32 remaining = sector_count * 512;
|
||||||
|
u64 buff_phys = virt_to_phys(buf);
|
||||||
|
u16 prdt_count = 0;
|
||||||
|
|
||||||
|
while (remaining > 0 && prdt_count < AHCI_PRDT_PER_TABLE) {
|
||||||
|
u32 chunk = remaining < CHUNK_SIZE ? remaining : CHUNK_SIZE;
|
||||||
|
|
||||||
|
tbl->prdt[prdt_count].dba = (u32)(buff_phys);
|
||||||
|
tbl->prdt[prdt_count].dbau = (u32)(buff_phys >> 32);
|
||||||
|
// dbc is bytes - 1; set interrupt on completion only on last entry
|
||||||
|
tbl->prdt[prdt_count].dbc = (chunk - 1);
|
||||||
|
|
||||||
|
buff_phys += chunk;
|
||||||
|
remaining -= chunk;
|
||||||
|
prdt_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interrupt on last PRDT entry
|
||||||
|
tbl->prdt[prdt_count - 1].dbc |= (1u << 31);
|
||||||
|
|
||||||
|
hdr->prdtl = prdt_count;
|
||||||
|
|
||||||
|
// Build the command FIS
|
||||||
|
fis_reg_h2d_t *fis = (fis_reg_h2d_t *)tbl->cfis;
|
||||||
|
fis->fis_type = 0x27;
|
||||||
|
fis->c = (1 << 7);
|
||||||
|
fis->command = write ? ATA_CMD_WRITE_DMA_EXT : ATA_CMD_READ_DMA_EXT;
|
||||||
|
fis->device = (1 << 6); // LBA mode
|
||||||
|
|
||||||
|
fis->lba0 = (u8)(lba >> 0);
|
||||||
|
fis->lba1 = (u8)(lba >> 8);
|
||||||
|
fis->lba2 = (u8)(lba >> 16);
|
||||||
|
fis->lba3 = (u8)(lba >> 24);
|
||||||
|
fis->lba4 = (u8)(lba >> 32);
|
||||||
|
fis->lba5 = (u8)(lba >> 40);
|
||||||
|
|
||||||
|
fis->countl = (u8)(sector_count >> 0);
|
||||||
|
fis->counth = (u8)(sector_count >> 8);
|
||||||
|
|
||||||
|
// Wait until port is not busy
|
||||||
|
int spin = 0;
|
||||||
|
while ((port->tfd & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && ++spin < 1000000)
|
||||||
|
;
|
||||||
|
if (spin >= 1000000) {
|
||||||
|
print("AHCI: port hung before issue\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
port->is = 0xFFFFFFFF; // clear interrupts before issuing
|
||||||
|
port->ci = (1u << slot);
|
||||||
|
|
||||||
|
// Poll for completion
|
||||||
|
while (1) {
|
||||||
|
if (!(port->ci & (1u << slot)))
|
||||||
|
break;
|
||||||
|
if (port->is & HBA_IS_TFES) {
|
||||||
|
print("AHCI: task file error (port ");
|
||||||
|
print32(idx);
|
||||||
|
print(")\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final error check after CI clears
|
||||||
|
if (port->is & HBA_IS_TFES) {
|
||||||
|
print("AHCI: task file error after completion\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ahci_read(int port, u64 lba, u32 count, void *buf) {
|
||||||
|
int ret = ahci_rw(port, lba, count, buf, 0);
|
||||||
|
if(ret < 0) {
|
||||||
|
printf("Failed ahci read (%d, 0x", port);
|
||||||
|
print64(lba);
|
||||||
|
printf(", %u, %u)\n", count, buf);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ahci_write(int port, u64 lba, u32 count, void *buf) {
|
||||||
|
return ahci_rw(port, lba, count, buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 ahci_sector_count(int port) {
|
||||||
|
return ports[port].sector_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ahci_port_active(int port) {
|
||||||
|
return ports[port].active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ahci_init() {
|
||||||
|
// Scan PCI for AHCI controller (class=0x01, subclass=0x06)
|
||||||
|
u8 found_bus = 0, found_slot = 0, found_func = 0;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
for (u32 bus = 0; bus < 256 && !found; bus++) {
|
||||||
|
for (u8 slot = 0; slot < 32 && !found; slot++) {
|
||||||
|
for (u8 func = 0; func < 8 && !found; func++) {
|
||||||
|
u32 id = pci_read(bus, slot, func, 0x00);
|
||||||
|
if ((id & 0xFFFF) == 0xFFFF) continue;
|
||||||
|
|
||||||
|
u32 class = pci_read(bus, slot, func, 0x08);
|
||||||
|
if (((class >> 24) & 0xFF) == 0x01 &&
|
||||||
|
((class >> 16) & 0xFF) == 0x06) {
|
||||||
|
found_bus = bus;
|
||||||
|
found_slot = slot;
|
||||||
|
found_func = func;
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
print("AHCI: no controller found\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable bus mastering + memory space
|
||||||
|
u32 pcicmd = pci_read(found_bus, found_slot, found_func, 0x04);
|
||||||
|
pcicmd |= (1 << 1) | (1 << 2);
|
||||||
|
pci_write(found_bus, found_slot, found_func, 0x04, pcicmd);
|
||||||
|
|
||||||
|
// BAR5 = ABAR
|
||||||
|
u32 bar5 = pci_read(found_bus, found_slot, found_func, 0x24);
|
||||||
|
u64 abar_phys = (u64)(bar5 & 0xFFFFF000);
|
||||||
|
|
||||||
|
hba = (hba_mem_t *)map_mmio(abar_phys, 1<<12);
|
||||||
|
if (!hba) {
|
||||||
|
print("AHCI: failed to map HBA\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("AHCI: HBA mapped, version=%d", hba->vs);
|
||||||
|
|
||||||
|
// Take AHCI ownership from BIOS if BOHC is supported (CAP2.BOH)
|
||||||
|
if (hba->cap2 & (1 << 0)) {
|
||||||
|
hba->bohc |= (1 << 1); // set OOS
|
||||||
|
while (hba->bohc & (1 << 0)) // wait for BOS to clear
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable AHCI mode
|
||||||
|
hba->ghc |= HBA_GHC_AE;
|
||||||
|
|
||||||
|
// Init all ports that have a device attached
|
||||||
|
u32 pi = hba->pi;
|
||||||
|
for (int i = 0; i < AHCI_MAX_PORTS; i++) {
|
||||||
|
if (!(pi & (1u << i))) continue;
|
||||||
|
|
||||||
|
u32 ssts = hba->ports[i].ssts;
|
||||||
|
u8 det = (ssts >> 0) & 0xF; // device detection
|
||||||
|
u8 ipm = (ssts >> 8) & 0xF; // interface power management
|
||||||
|
|
||||||
|
if (det == 3 && ipm == 1) {
|
||||||
|
port_init(i);
|
||||||
|
port_identify(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/ahci.h
Normal file
9
src/ahci.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int ahci_read(int port, u64 lba, u32 count, void *buf);
|
||||||
|
int ahci_write(int port, u64 lba, u32 count, void *buf);
|
||||||
|
u64 ahci_sector_count(int port);
|
||||||
|
int ahci_port_active(int port);
|
||||||
|
void ahci_init();
|
||||||
@ -2,6 +2,7 @@
|
|||||||
#include "../include/limine.h"
|
#include "../include/limine.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
#include "lib/stdio.h"
|
||||||
|
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
#define dprint(x) print(x)
|
#define dprint(x) print(x)
|
||||||
@ -115,7 +116,7 @@ static void *addr(size_t page) { return alloc_start + page * PAGE_SIZE; }
|
|||||||
static void usepage(size_t page) {
|
static void usepage(size_t page) {
|
||||||
size_t idx = page / 64;
|
size_t idx = page / 64;
|
||||||
size_t bit = page & 63;
|
size_t bit = page & 63;
|
||||||
alloc_bitmap[idx] |= (1 << bit);
|
alloc_bitmap[idx] |= (1ULL << bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usepagerange(size_t page, size_t len) {
|
static void usepagerange(size_t page, size_t len) {
|
||||||
@ -127,7 +128,7 @@ static void usepagerange(size_t page, size_t len) {
|
|||||||
static void unusepage(size_t page) {
|
static void unusepage(size_t page) {
|
||||||
size_t idx = page / 64;
|
size_t idx = page / 64;
|
||||||
size_t bit = page & 63;
|
size_t bit = page & 63;
|
||||||
alloc_bitmap[idx] &= ~(1 << bit);
|
alloc_bitmap[idx] &= ~(1ULL << bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unusepagerange(size_t page, size_t len) {
|
static void unusepagerange(size_t page, size_t len) {
|
||||||
@ -190,6 +191,7 @@ void *alloc(size_t size) {
|
|||||||
if (++consecutive >= pages) {
|
if (++consecutive >= pages) {
|
||||||
usepagerange(page, pages);
|
usepagerange(page, pages);
|
||||||
dprint("succeeded!\n");
|
dprint("succeeded!\n");
|
||||||
|
|
||||||
return addr(page);
|
return addr(page);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -34,12 +34,12 @@ static inline u8 inb(u16 port) {
|
|||||||
}
|
}
|
||||||
static inline u16 inw(u16 port) {
|
static inline u16 inw(u16 port) {
|
||||||
u16 value;
|
u16 value;
|
||||||
asm volatile("inw %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
|
asm volatile("inw %w1, %0" : "=a"(value) : "Nd"(port) : "memory");
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
static inline u32 ind(u16 port) {
|
static inline u32 ind(u16 port) {
|
||||||
u32 value;
|
u32 value;
|
||||||
asm volatile("ind %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
|
asm volatile("inl %w1, %0" : "=a"(value) : "Nd"(port) : "memory");
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
143
src/fat32.h
Normal file
143
src/fat32.h
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ahci.h"
|
||||||
|
#include "alloc.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "lib/stdio.h"
|
||||||
|
|
||||||
|
// FAT32 BPB (BIOS Parameter Block) sits at the start of sector 0
|
||||||
|
typedef pstruct {
|
||||||
|
u8 jump[3];
|
||||||
|
u8 oem[8];
|
||||||
|
u16 bytes_per_sector;
|
||||||
|
u8 sectors_per_cluster;
|
||||||
|
u16 reserved_sectors;
|
||||||
|
u8 fat_count;
|
||||||
|
u16 root_entry_count; // 0 for FAT32
|
||||||
|
u16 total_sectors_16; // 0 for FAT32
|
||||||
|
u8 media_type;
|
||||||
|
u16 fat_size_16; // 0 for FAT32
|
||||||
|
u16 sectors_per_track;
|
||||||
|
u16 head_count;
|
||||||
|
u32 hidden_sectors;
|
||||||
|
u32 total_sectors_32;
|
||||||
|
|
||||||
|
// FAT32 extended fields
|
||||||
|
u32 fat_size_32;
|
||||||
|
u16 ext_flags;
|
||||||
|
u16 fs_version; // must be 0x0000
|
||||||
|
u32 root_cluster; // usually 2
|
||||||
|
u16 fs_info_sector;
|
||||||
|
u16 backup_boot_sector;
|
||||||
|
u8 reserved[12];
|
||||||
|
u8 drive_number;
|
||||||
|
u8 reserved1;
|
||||||
|
u8 boot_signature; // 0x29
|
||||||
|
u32 volume_id;
|
||||||
|
u8 volume_label[11];
|
||||||
|
u8 fs_type[8]; // "FAT32 "
|
||||||
|
} fat32_bpb_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef pstruct {
|
||||||
|
u8 status; // 0x80 = bootable
|
||||||
|
u8 chs_first[3]; // legacy
|
||||||
|
u8 type; // partition type
|
||||||
|
u8 chs_last[3]; // legacy
|
||||||
|
u32 lba_start; // first sector of the partition
|
||||||
|
u32 sector_count; // size in sectors
|
||||||
|
} fat32_mbr_partition_t;
|
||||||
|
|
||||||
|
typedef pstruct {
|
||||||
|
u8 bootcode[446];
|
||||||
|
fat32_mbr_partition_t partitions[4];
|
||||||
|
u16 signature;
|
||||||
|
} fat32_mbr_t;
|
||||||
|
|
||||||
|
typedef pstruct {
|
||||||
|
u32 fat_start;
|
||||||
|
u32 data_start;
|
||||||
|
u32 sectors_per_cluster;
|
||||||
|
u32 root_cluster;
|
||||||
|
u32 part_start;
|
||||||
|
} fat32_vol_t;
|
||||||
|
|
||||||
|
static fat32_vol_t vol_from_bpb(fat32_bpb_t* bpb, u32 part_start) {
|
||||||
|
fat32_vol_t vol;
|
||||||
|
vol.part_start = part_start;
|
||||||
|
vol.sectors_per_cluster = bpb->sectors_per_cluster;
|
||||||
|
vol.fat_start = part_start + bpb->reserved_sectors;
|
||||||
|
vol.data_start = vol.fat_start + bpb->fat_count * bpb->fat_size_32;
|
||||||
|
vol.root_cluster = bpb->root_cluster;
|
||||||
|
|
||||||
|
return vol;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE 512
|
||||||
|
|
||||||
|
static u32 fat32_next(int port, fat32_vol_t* vol, u32 cluster) {
|
||||||
|
u32 fat_off = cluster*4;
|
||||||
|
u32 fat_sect = vol->fat_start + fat_off / TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE;
|
||||||
|
u32 fat_idx = (fat_off & (TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE-1));
|
||||||
|
|
||||||
|
printf("fat_next: cluster=%u fat_off=%u fat_sect=%u byte_off=%u\n",
|
||||||
|
cluster, fat_off, fat_sect, fat_off);
|
||||||
|
|
||||||
|
u8* buff = (u8*) alloc(4096);
|
||||||
|
if(ahci_read(port, fat_sect, 2, buff) < 0) {
|
||||||
|
printf("fat_next: read failed at lba=%u\n", fat_sect);
|
||||||
|
return 0x0FFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32* tbl = (u32*) (buff + fat_idx);
|
||||||
|
// mask top 4
|
||||||
|
return *tbl & 0x0FFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool fat32_is_eof(u32 cluster) {
|
||||||
|
return cluster >= 0x0FFFFFF8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 fat32_cluster_to_lba(fat32_vol_t* vol, u32 cluster) {
|
||||||
|
// first 2 are resv.
|
||||||
|
|
||||||
|
u64 lba = vol->data_start + (u64)(cluster-2) * vol->sectors_per_cluster;
|
||||||
|
|
||||||
|
return lba;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fat32_read_cluster(int port, fat32_vol_t* vol, u32 cluster, u8* buff) {
|
||||||
|
u64 lba = fat32_cluster_to_lba(vol, cluster);
|
||||||
|
return ahci_read(port, lba, vol->sectors_per_cluster, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* directory entries and files */
|
||||||
|
typedef pstruct {
|
||||||
|
u8 name[8];
|
||||||
|
u8 ext[3];
|
||||||
|
u8 attr;
|
||||||
|
u8 resv;
|
||||||
|
u8 creation_time_tenth;
|
||||||
|
u16 creation_time;
|
||||||
|
u16 creation_date;
|
||||||
|
u16 access_date;
|
||||||
|
u16 cluster_high; // high 16 bits of first cluster
|
||||||
|
u16 modify_time;
|
||||||
|
u16 modify_date;
|
||||||
|
u16 cluster_low; // low 16 bits of first cluster
|
||||||
|
u32 file_size;
|
||||||
|
} fat32_dirent_t;
|
||||||
|
|
||||||
|
enum fat32_attr {
|
||||||
|
ATTR_READ_ONLY = 1 << 0,
|
||||||
|
ATTR_HIDDEN = 1 << 1,
|
||||||
|
ATTR_SYSTEM = 1 << 2,
|
||||||
|
ATTR_VOL_ID = 1 << 3,
|
||||||
|
ATTR_DIR = 1 << 4,
|
||||||
|
ATTR_ARCH = 1 << 5,
|
||||||
|
ATTR_LFN = 0xF, // long file name entry
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32 fat32_dirent_cluster(fat32_dirent_t* dirent) {
|
||||||
|
return ((u32)dirent->cluster_high << 16) | dirent->cluster_low;
|
||||||
|
}
|
||||||
202
src/main.c
202
src/main.c
@ -9,11 +9,11 @@
|
|||||||
void print_tok(struct token* tok);
|
void print_tok(struct token* tok);
|
||||||
|
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
|
#include "ahci.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "kbd.h"
|
#include "fat32.h"
|
||||||
#include "map.h"
|
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "lib/stdio.h"
|
#include "lib/stdio.h"
|
||||||
|
|
||||||
@ -108,11 +108,11 @@ void hang() {
|
|||||||
|
|
||||||
struct limine_framebuffer *fb;
|
struct limine_framebuffer *fb;
|
||||||
|
|
||||||
void draw(u8 vect) {
|
void draw() {
|
||||||
for (size_t y = 0; y < fb->height; y++) {
|
for (size_t y = 0; y < fb->height; y++) {
|
||||||
for (size_t x = 0; x < fb->width; x++) {
|
for (size_t x = 0; x < fb->width; x++) {
|
||||||
volatile u32 *fb_ptr = fb->address;
|
volatile u32 *fb_ptr = fb->address;
|
||||||
int tone = ((x ^ y) & 0xFF) >> 6;
|
int tone = ((x ^ y) & 0xFF);
|
||||||
fb_ptr[y * fb->width + x] = (tone << 16);
|
fb_ptr[y * fb->width + x] = (tone << 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,6 +142,64 @@ void enable_ps2_keyboard_interrupts(void) {
|
|||||||
outb(0x64, 0xAE);
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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() {
|
void kmain() {
|
||||||
if (LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
|
if (LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
|
||||||
hang();
|
hang();
|
||||||
@ -153,7 +211,7 @@ void kmain() {
|
|||||||
|
|
||||||
fb = fb_req.response->framebuffers[0];
|
fb = fb_req.response->framebuffers[0];
|
||||||
|
|
||||||
draw(1);
|
draw();
|
||||||
print_init(fb);
|
print_init(fb);
|
||||||
init_idt();
|
init_idt();
|
||||||
fg = 0xFFFFFF;
|
fg = 0xFFFFFF;
|
||||||
@ -203,42 +261,112 @@ void kmain() {
|
|||||||
|
|
||||||
asm volatile("sti");
|
asm volatile("sti");
|
||||||
|
|
||||||
#define LINES 40
|
|
||||||
size_t max_len = MAX_LINE_LEN;
|
|
||||||
char* lines[LINES];
|
|
||||||
|
|
||||||
size_t n_lines = 0;
|
ahci_init();
|
||||||
for(n_lines = 0; n_lines < LINES; n_lines++) {
|
|
||||||
char* line = getline_alloc(max_len);
|
i8 port = -1;
|
||||||
if(!line)
|
for(u8 i = 0; i < 32; i++) {
|
||||||
break;
|
if(ahci_port_active(i)) {
|
||||||
if(line[0] == 'F' && line[1] == 'I' && line[2] == '\n')
|
// assume we want the first port
|
||||||
break;
|
if(port < 0)
|
||||||
lines[n_lines] = line;
|
port = i;
|
||||||
|
printf("Port %d is active!\n", i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* name = "stdin";
|
if(port < 0) {
|
||||||
struct file input = {
|
printf("Couldn't find a port to read the FS from :(\n");
|
||||||
.row = 0,
|
hang();
|
||||||
.col = 0,
|
|
||||||
.rows = n_lines,
|
|
||||||
.lines = (char**)lines,
|
|
||||||
.name = name,
|
|
||||||
.tokens = NULL,
|
|
||||||
.tail = &input.tokens,
|
|
||||||
};
|
|
||||||
|
|
||||||
int res = lex(&input);
|
|
||||||
|
|
||||||
print("Number of Errors: ");
|
|
||||||
print8(res);
|
|
||||||
|
|
||||||
printf("\n# of Tokens: %d\n", input.tokens->len);
|
|
||||||
struct token* token = input.tokens;
|
|
||||||
|
|
||||||
for(;token; token = token->next) {
|
|
||||||
print_tok(token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
//dealloc((void*) bpb, 1<<12);
|
||||||
|
|
||||||
|
// #define LINES 40
|
||||||
|
// size_t max_len = MAX_LINE_LEN;
|
||||||
|
// char* lines[LINES];
|
||||||
|
|
||||||
|
// size_t n_lines = 0;
|
||||||
|
// for(n_lines = 0; n_lines < LINES; n_lines++) {
|
||||||
|
// char* line = getline_alloc(max_len);
|
||||||
|
// if(!line)
|
||||||
|
// break;
|
||||||
|
// if(line[0] == 'F' && line[1] == 'I' && line[2] == '\n')
|
||||||
|
// break;
|
||||||
|
// lines[n_lines] = line;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const char* name = "stdin";
|
||||||
|
// struct file input = {
|
||||||
|
// .row = 0,
|
||||||
|
// .col = 0,
|
||||||
|
// .rows = n_lines,
|
||||||
|
// .lines = (char**)lines,
|
||||||
|
// .name = name,
|
||||||
|
// .tokens = NULL,
|
||||||
|
// .tail = &input.tokens,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// int res = lex(&input);
|
||||||
|
|
||||||
|
// print("Number of Errors: ");
|
||||||
|
// print8(res);
|
||||||
|
|
||||||
|
// printf("\n# of Tokens: %d\n", input.tokens->len);
|
||||||
|
// struct token* token = input.tokens;
|
||||||
|
|
||||||
|
// for(;token; token = token->next) {
|
||||||
|
// print_tok(token);
|
||||||
|
// }
|
||||||
|
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,7 +75,7 @@ void put(int ch) {
|
|||||||
size_t off = (py + y) * fb_width + (px + x);
|
size_t off = (py + y) * fb_width + (px + x);
|
||||||
bool padding =
|
bool padding =
|
||||||
(y == 0 || y == GLYPH_HEIGHT - 1 || x == 0 || x == GLYPH_WIDTH - 1);
|
(y == 0 || y == GLYPH_HEIGHT - 1 || x == 0 || x == GLYPH_WIDTH - 1);
|
||||||
fb_scr[off] = ((~glyph & 1) | padding) ? bg : fg;
|
fb_scr[off] = ((~glyph & 1) | padding) ? ((fb_scr[off] == fg) ? bg : fb_scr[off]) : fg;
|
||||||
glyph >>= !padding;
|
glyph >>= !padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,4 +132,4 @@ void unput(void) {
|
|||||||
for (size_t y = 0; y < GLYPH_HEIGHT; y++)
|
for (size_t y = 0; y < GLYPH_HEIGHT; y++)
|
||||||
for (size_t x = 0; x < GLYPH_WIDTH; x++)
|
for (size_t x = 0; x < GLYPH_WIDTH; x++)
|
||||||
fb_scr[(py + y) * fb_width + (px + x)] = bg;
|
fb_scr[(py + y) * fb_width + (px + x)] = bg;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user