diff --git a/.gitignore b/.gitignore index b1b15b8..74acc39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ compile_flags.txt bin +disk.img diff --git a/Makefile b/Makefile index 98f2190..543ba3c 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ A_OBJ=$(patsubst %.asm,bin/%_asm.o,$(A_SOURCE)) LIBK_SOURCE=$(shell find libk -type f -name "*.c") LIBK_OBJ=$(patsubst %.c,bin/%.o,$(LIBK_SOURCE)) -.PHONY: test all run clean +.PHONY: test all run clean mkdiskimg all: bin/os.iso @@ -42,8 +42,14 @@ bin/os.iso: bin/kernel.bin grub.cfg cp bin/kernel.bin bin/iso/boot grub-mkrescue -o bin/os.iso bin/iso -run: all - qemu-system-i386 -cdrom bin/os.iso +bin/disk.img: + @mkdir -p bin + cp disk.img bin/disk.img + +run: bin/os.iso bin/disk.img + qemu-system-i386 -cdrom bin/os.iso \ + -drive file=bin/disk.img,format=raw,if=ide \ + -boot order=d clean: rm -rf bin diff --git a/disk.img b/disk.img new file mode 100644 index 0000000..09ad9ae Binary files /dev/null and b/disk.img differ diff --git a/kernel/bootinfo.c b/kernel/bootinfo.c index 7b8fb04..ae8d0b2 100644 --- a/kernel/bootinfo.c +++ b/kernel/bootinfo.c @@ -3,7 +3,6 @@ #include #include "panic.h" -#include "term.h" #include "bootinfo.h" #define CMDLINE_MAX 128 diff --git a/kernel/drivers/ata.c b/kernel/drivers/ata.c new file mode 100644 index 0000000..8b9e921 --- /dev/null +++ b/kernel/drivers/ata.c @@ -0,0 +1,127 @@ +#include + +#include "ata.h" +#include "pci.h" +#include "../panic.h" + +#define REG_DATA 0 +#define REG_ERR 1 +#define REG_FEATURES 1 +#define REG_SECTOR_CNT 2 +#define REG_SECTOR_NUM 3 +#define REG_LBA_LO 3 +#define REG_CYLINDER_LO 4 +#define REG_LBA_MID 4 +#define REG_CYLINDER_HI 5 +#define REG_LBA_HI 5 +#define REG_DRIVE_HEAD 6 +#define REG_STATUS 7 +#define REG_COMMAND 7 + +#define STAT_ERR 0x01 +#define STAT_IDX 0x02 +#define STAT_CORR 0x04 +#define STAT_DRQ 0x08 +#define STAT_SRV 0x10 +#define STAT_DF 0x20 +#define STAT_RDY 0x40 +#define STAT_BSY 0x80 + +static bool ata_init_impl(uint16_t base, uint16_t ctrl, struct AtaDevice *dev) { + uint8_t status = inb(base + REG_STATUS); + outb(base + REG_DRIVE_HEAD, 0xA0); + outb(base + REG_SECTOR_CNT, 0x00); + outb(base + REG_LBA_LO, 0x00); + outb(base + REG_LBA_MID, 0x00); + outb(base + REG_LBA_HI, 0x00); + outb(base + REG_COMMAND, 0xEC); + status = STAT_BSY; + while(status & STAT_BSY) { + status = inb(base + REG_STATUS); + } + if(inb(base + REG_LBA_MID) != 0 || inb(base + REG_LBA_HI) != 0) { + panic("Device is not an ATA device"); + } + while(!(status & (STAT_DRQ | STAT_ERR))) { + status = inb(base + REG_STATUS); + } + if(status & STAT_ERR) { + uint8_t err = inb(base + REG_ERR); + panic("Error initializing ATA device: %X", err); + } + uint16_t data[256]; + for(int i = 0; i < 256; i++) { + data[i] = inw(base + REG_DATA); + } + uint32_t sector_count = data[60] | (data[61] << 16); + if(sector_count == 0) { + panic("ATA device does not support LBA28"); + } + dev->base = base; + dev->ctrl = ctrl; + dev->sector_count = sector_count; + return true; +} + +bool ata_init(struct AtaDevice *atadev, struct PciDevice pcidev) { + uint8_t prog_if = pci_rcfg_b(pcidev, PCI_PROG_IF_B); + + if((prog_if & 0x7F) != 0) { + panic("Could not initialize ATA device: unsupported prog_if %X", prog_if); + } + + atadev->pcidev = pcidev; + + if(!ata_init_impl(0x1F0, 0x3F6, atadev)) { + return false; + } + + return true; +} + +bool ata_read(struct AtaDevice atadev, uint32_t lba, uint8_t sector_count, uint16_t buf[sector_count*256]) { + outb(atadev.base + REG_DRIVE_HEAD, 0xE0 | ((lba >> 24) & 0x0F)); + outb(atadev.base + REG_FEATURES, 0x00); + outb(atadev.base + REG_SECTOR_CNT, sector_count); + outb(atadev.base + REG_LBA_LO, lba & 0xFF); + outb(atadev.base + REG_LBA_MID, (lba >> 8) & 0xFF); + outb(atadev.base + REG_LBA_HI, (lba >> 16) & 0xFF); + outb(atadev.base + REG_COMMAND, 0x20); + for(int i = 0; i < sector_count; i++) { + while(true) { + uint8_t status = inb(atadev.ctrl); + if(status & STAT_DRQ) break; + if(status & STAT_DF) panic("Drive failure"); + if(status & STAT_ERR) panic("Read disk error"); + } + for(int j = 0; j < 256; j++) { + buf[i*256 + j] = inw(atadev.base + REG_DATA); + } + } + return true; +} + +bool ata_write(struct AtaDevice atadev, uint32_t lba, uint8_t sector_count, uint16_t buf[sector_count*256]) { + outb(atadev.base + REG_DRIVE_HEAD, 0xE0 | ((lba >> 24) & 0x0F)); + outb(atadev.base + REG_FEATURES, 0x00); + outb(atadev.base + REG_SECTOR_CNT, sector_count); + outb(atadev.base + REG_LBA_LO, lba & 0xFF); + outb(atadev.base + REG_LBA_MID, (lba >> 8) & 0xFF); + outb(atadev.base + REG_LBA_HI, (lba >> 16) & 0xFF); + outb(atadev.base + REG_COMMAND, 0x30); + for(int i = 0; i < sector_count; i++) { + while(true) { + uint8_t status = inb(atadev.ctrl); + if(status & STAT_DRQ) break; + if(status & STAT_DF) panic("Drive failure"); + if(status & STAT_ERR) panic("Write disk error"); + } + for(int j = 0; j < 256; j++) { + outw(atadev.base + REG_DATA, buf[i*256 + j]); + } + } + io_wait(); + outb(atadev.base + REG_COMMAND, 0xE7); + while(inb(atadev.ctrl & STAT_BSY)) {} + return true; +} diff --git a/kernel/drivers/ata.h b/kernel/drivers/ata.h new file mode 100644 index 0000000..da70e93 --- /dev/null +++ b/kernel/drivers/ata.h @@ -0,0 +1,14 @@ +#pragma once + +#include "pci.h" + +struct AtaDevice { + struct PciDevice pcidev; + uint16_t base; + uint16_t ctrl; + uint32_t sector_count; +}; + +bool ata_init(struct AtaDevice *atadev, struct PciDevice pcidev); +bool ata_read(struct AtaDevice atadev, uint32_t lba, uint8_t sector_count, uint16_t buf[sector_count*256]); +bool ata_write(struct AtaDevice atadev, uint32_t lba, uint8_t sector_count, uint16_t buf[sector_count*256]); diff --git a/kernel/drivers/keycodes.h b/kernel/drivers/keycodes.h index 4855007..d55f586 100644 --- a/kernel/drivers/keycodes.h +++ b/kernel/drivers/keycodes.h @@ -9,7 +9,7 @@ struct Keycode { #define KC_FLAG_KEY_DOWN 0x01 #define KC_FLAG_KEY_UP 0x02 -#define KC_FLAG_ERROR 0x04 +#define KC_FLAG_ERROR 0x04 #define KEY_NONE 0x00 #define KEY_UNKNOWN 0x01 diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci.c new file mode 100644 index 0000000..cb3ae2f --- /dev/null +++ b/kernel/drivers/pci.c @@ -0,0 +1,157 @@ +#include +#include + +#include "../panic.h" +#include "pci.h" + +#define CONF_ADDR 0xCF8 +#define CONF_DATA 0xCFC + +#define TABLE_LEN 16 + +struct PciTableEntry { + struct PciDevice device; + uint16_t device_id; + uint16_t vendor_id; + uint8_t class; + uint8_t subclass; + uint8_t prog_if; + uint8_t revision; +}; + +static struct PciTableEntry pci_table[TABLE_LEN]; +static size_t pci_table_next = 0; + +uint32_t pci_rcfg_d(struct PciDevice dev, uint8_t offset) { + uint32_t addr = 0x80000000; + addr |= ((uint32_t)dev.bus) << 16; + addr |= ((uint32_t)dev.device) << 11; + addr |= ((uint32_t)dev.function) << 8; + addr |= offset & 0xFC; + + outl(CONF_ADDR, addr); + uint32_t in = inl(CONF_DATA); + return in; +} + +uint16_t pci_rcfg_w(struct PciDevice dev, uint8_t offset) { + uint32_t dword = pci_rcfg_d(dev, offset); + return (uint16_t)((dword >> ((offset & 2) * 8)) & 0xFFFF); +} + +uint8_t pci_rcfg_b(struct PciDevice dev, uint8_t offset) { + uint32_t dword = pci_rcfg_d(dev, offset); + return (uint8_t)((dword >> ((offset & 3) * 8)) & 0xFF); +} + +void pci_wcfg_d(struct PciDevice dev, uint8_t offset, uint32_t dword) { + uint32_t addr = 0x80000000; + addr |= ((uint32_t)dev.bus) << 16; + addr |= ((uint32_t)dev.device) << 11; + addr |= ((uint32_t)dev.function) << 8; + addr |= offset & 0xFC; + + outl(CONF_ADDR, addr); + outl(CONF_DATA, dword); +} + +void pci_wcfg_w(struct PciDevice dev, uint8_t offset, uint16_t word) { + size_t shift = (offset & 2) * 8; + uint32_t dword = pci_rcfg_d(dev, offset); + dword &= ~(0xFFFF << shift); + dword |= word << shift; + pci_wcfg_d(dev, offset, dword); +} + +void pci_wcfg_b(struct PciDevice dev, uint8_t offset, uint8_t byte) { + size_t shift = (offset & 3) * 8; + uint32_t dword = pci_rcfg_d(dev, offset); + dword &= ~(0xFF << shift); + dword |= byte << shift; + pci_wcfg_d(dev, offset, dword); +} + +//static void print_device(struct PciTableEntry *entry) { +// printf("pci bus @0e%X@0f dev @0e%X@0f func @0e%X@0f", +// entry->device.bus, entry->device.device, entry->device.function); +// +// printf("\tid @0c%X:%X@0f", entry->vendor_id, entry->device_id); +// +// printf("\tclass @0c%X:%X:%X@0f", entry->class, entry->subclass, entry->prog_if); +// printf("\trev @0c%X@0f\n", entry->revision); +//} + + +static struct PciTableEntry *load_device(struct PciDevice dev) { + if(pci_table_next >= TABLE_LEN) panic("Too many PCI devices: limit is %d", TABLE_LEN); + struct PciTableEntry *entry = &pci_table[pci_table_next++]; + entry->device = dev; + uint32_t dword0 = pci_rcfg_d(dev, 0); + uint32_t dword2 = pci_rcfg_d(dev, 8); + + entry->device_id = (dword0 >> 16) & 0xFFFF; + entry->vendor_id = dword0 & 0xFFFF; + + entry->class = (dword2 >> 24) & 0xFF; + entry->subclass = (dword2 >> 16) & 0xFF; + entry->prog_if = (dword2 >> 8) & 0xFF; + entry->revision = dword2 & 0xFF; + + //print_device(entry); + return entry; +} + +void pci_init(void) { + pci_table_next = 0; + struct PciDevice pcidev; + for(int bus = 0; bus < 256; bus++) { + pcidev.bus = bus; + for(int dev = 0; dev < 32; dev++) { + pcidev.device = dev; + pcidev.function = 0; + + uint16_t vendor = pci_rcfg_w(pcidev, 0); + if(vendor == 0xFFFF) continue; + + load_device(pcidev); + + uint8_t header_type = pci_rcfg_b(pcidev, 14); + + if(!(header_type & 0x80)) continue; + for(int func = 1; func < 8; func++) { + pcidev.function = func; + + uint16_t vendor = pci_rcfg_w(pcidev, 0); + if(vendor == 0xFFFF) continue; + + load_device(pcidev); + } + } + } +} + +bool pci_findby_class(struct PciDevice *dest, uint8_t class, uint8_t subclass, size_t *offset) { + size_t o = 0; + if(offset == NULL) offset = &o; + for(; *offset < pci_table_next; (*offset)++) { + struct PciTableEntry *entry = &pci_table[*offset]; + if(entry->class == class && entry->subclass == subclass) { + *dest = entry->device; + return true; + } + } + return false; +} + +bool pci_findby_id(struct PciDevice *dest, uint16_t device, uint16_t vendor, size_t *offset) { + size_t o = 0; + if(offset == NULL) offset = &o; + for(; *offset < pci_table_next; (*offset)++) { + struct PciTableEntry *entry = &pci_table[*offset]; + if(entry->device_id == device && entry->vendor_id == vendor) { + *dest = entry->device; + return true; + } + } + return false; +} diff --git a/kernel/drivers/pci.h b/kernel/drivers/pci.h new file mode 100644 index 0000000..b09acaf --- /dev/null +++ b/kernel/drivers/pci.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include + +// common +#define PCI_VENDOR_W 0x00 +#define PCI_DEVICE_W 0x02 +#define PCI_COMMAND_W 0x04 +#define PCI_STATUS_W 0x06 +#define PCI_REVISION_B 0x08 +#define PCI_PROG_IF_B 0x09 +#define PCI_SUBCLASS_B 0x0A +#define PCI_CLASS_B 0x0B +#define PCI_CACHE_SIZE_B 0x0C +#define PCI_LATENCY_TIMER_B 0x0D +#define PCI_HEADER_TYPE_B 0x0E +#define PCI_BIST_B 0x0F + +// header type 0 +#define PCI_BAR0_D 0x10 +#define PCI_BAR1_D 0x14 +#define PCI_BAR2_D 0x18 +#define PCI_BAR3_D 0x1C +#define PCI_BAR4_D 0x20 +#define PCI_BAR5_D 0x24 +#define PCI_CARDBUS_CIS_D 0x28 +#define PCI_SUBSYSTEM_VENDOR_W 0x2C +#define PCI_SUBSYSTEM_W 0x2E +#define PCI_EXPANSION_ROM_D 0x30 +#define PCI_CAP_PTR_B 0x34 +#define PCI_INT_LINE_B 0x3C +#define PCI_INT_PIN_B 0x3D +#define PCI_MIN_GRANT_B 0x3E +#define PCI_MAX_LATENCY_B 0x3F + +struct PciDevice { + uint8_t bus: 8; + uint8_t device: 5; + uint8_t function: 3; +}; + +void pci_init(void); + +bool pci_findby_class(struct PciDevice *dest, uint8_t class, uint8_t subclass, size_t *offset); +bool pci_findby_id(struct PciDevice *dest, uint16_t device, uint16_t vendor, size_t *offset); + +uint32_t pci_rcfg_d(struct PciDevice dev, uint8_t offset); +uint16_t pci_rcfg_w(struct PciDevice dev, uint8_t offset); +uint8_t pci_rcfg_b(struct PciDevice dev, uint8_t offset); + +void pci_wcfg_d(struct PciDevice dev, uint8_t offset, uint32_t dword); +void pci_wcfg_w(struct PciDevice dev, uint8_t offset, uint16_t word); +void pci_wcfg_b(struct PciDevice dev, uint8_t offset, uint8_t byte); diff --git a/kernel/drivers/ps2kb.c b/kernel/drivers/ps2kb.c index 475f33b..be5993b 100644 --- a/kernel/drivers/ps2kb.c +++ b/kernel/drivers/ps2kb.c @@ -1,7 +1,6 @@ #include #include #include -#include "../term.h" #include "../panic.h" #include "../interrupt/pic.h" #include diff --git a/kernel/drivers/serial.c b/kernel/drivers/serial.c deleted file mode 100644 index fbaa49e..0000000 --- a/kernel/drivers/serial.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include "serial.h" -#include "../panic.h" - -#define PORT 0x3f8 // COM1 - -void serial_init(void) { - outb(PORT + 1, 0x00); // Disable all interrupts - outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) - outb(PORT + 0, 0x01); // Set divisor to 1 (lo byte) 38400 baud - outb(PORT + 1, 0x00); // (hi byte) - outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit - outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold - outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set - outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip - outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) - - // Check if serial is faulty (i.e: not same byte as sent) - uint8_t response = inb(PORT + 0); - if(response != 0xAE) { - panic("Serial is faulty: %X\n", response); - } - - // If serial is not faulty set it in normal operation mode - // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) - outb(PORT + 4, 0x0F); -} - -void serial_write(uint8_t a) { - while((inb(PORT + 5) & 0x20) != 0); - outb(PORT, a); -} - -void serial_write_s(const char* str) { - while(*str != '\0') { - serial_write(*str++); - } -} diff --git a/kernel/drivers/serial.h b/kernel/drivers/serial.h deleted file mode 100644 index 7bc1d77..0000000 --- a/kernel/drivers/serial.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -void serial_init(void); -void serial_write(uint8_t a); -void serial_write_s(const char* str); diff --git a/kernel/fs/fat.c b/kernel/fs/fat.c new file mode 100644 index 0000000..21a264e --- /dev/null +++ b/kernel/fs/fat.c @@ -0,0 +1,59 @@ +#include +#include "../term.h" +#include "../panic.h" +#include "fat.h" + +bool fat_init(struct FatInfo *fatinfo, struct AtaDevice dev, struct MbrPartition partition) { + uint8_t boot_sector[512] __attribute__((aligned(2))); + if(!ata_read(dev, partition.start_sector, 1, (void*)boot_sector)) return false; + memcpy(&fatinfo->bpb, boot_sector, sizeof(struct FatBpb)); + memcpy(&fatinfo->ebpb.f16, boot_sector + sizeof(struct FatBpb), sizeof(struct Fat16Ebpb)); + fatinfo->type = FAT16; + fatinfo->dev = dev; + fatinfo->partition = partition; + return true; +} + +static int read_dir_entry_sector(struct FatFile *file, struct FatInfo *fatinfo, size_t sector, char* name) { + uint8_t buf[512] __attribute__((aligned(2))); + if(!ata_read(fatinfo->dev, fatinfo->partition.start_sector + sector, 1, (uint16_t*)buf)) panic("read fail"); + for(int i = 0; i < 512; i += 32) { + if(buf[i] == 0) return 1; // reached end + if(buf[i] == 0xE5) continue; + if(buf[i+11] == 0x0F) continue; + int j; + for(j = 0; j < 11; j++) { + if(buf[i + j] != name[j]) break; + } + if(j != 11) continue; + memcpy(file->name, &buf[i], 11); + file->start_cluster = buf[i+26] | (buf[i+27] << 8) | (buf[i+20] << 16) | (buf[i+21] << 24); + file->size = buf[i+28] | (buf[i+29] << 8) | (buf[i+30] << 16) | (buf[i+31] << 24); + file->attributes = buf[i+11]; + return 0; // found file + } + return 2; // next sector +} + +static bool read_dir_entry(struct FatFile *file, struct FatInfo *fatinfo, size_t start_sector, size_t sector_count, char* name) { + for(size_t i = 0; i < sector_count; i++) { + int result = read_dir_entry_sector(file, fatinfo, start_sector + i, name); + if(result == 0) return true; + if(result == 1) break; + // continue if result == 2 + } + return false; +} + +bool fat_test(struct FatInfo *fatinfo) { + size_t root_start = fatinfo->bpb.reserved_sectors + fatinfo->bpb.fat_count * fatinfo->bpb.sectors_per_fat; + size_t root_sectors = (fatinfo->bpb.root_entries * 32 + 511) / 512; + printf("root start %d sectors %d\n", root_start, root_sectors); + printf("%X\n", root_start * 512); + struct FatFile file; + read_dir_entry(&file, fatinfo, root_start, root_sectors, "FILE3 "); + printf("start: 0x%X\n", file.start_cluster); + printf("size: 0x%X\n", file.size); + printf("attr: 0x%X\n", file.attributes); + return true; +} diff --git a/kernel/fs/fat.h b/kernel/fs/fat.h new file mode 100644 index 0000000..d02b84e --- /dev/null +++ b/kernel/fs/fat.h @@ -0,0 +1,72 @@ +#pragma once + +#include "mbr.h" + +enum FatType { + FAT12, + FAT16, + FAT32, +}; + +struct FatBpb { + uint8_t _instrs[3]; + uint8_t oem_ident[8]; + uint16_t bytes_per_sector; + uint8_t sectors_per_cluster; + uint16_t reserved_sectors; + uint8_t fat_count; + uint16_t root_entries; + uint16_t total_sectors_16; + uint8_t media_descriptor; + uint16_t sectors_per_fat; + uint16_t sectors_per_track; + uint16_t heads; + uint32_t hidden_sectors; + uint32_t total_sectors_32; +} __attribute__((packed)); + +struct Fat16Ebpb { + uint8_t drive_number; + uint8_t _reserved; + uint8_t signature; + uint32_t volume_id; + uint8_t volume_label[11]; + uint8_t sys_ident[8]; +} __attribute__((packed)); + +struct Fat32Ebpb { + uint32_t sectors_per_fat; + uint16_t flags; + uint16_t version; + uint32_t root_cluster; + uint16_t fsinfo_sector; + uint16_t backup_boot_sector; + uint8_t _reserved0[12]; + uint8_t drive_number; + uint8_t _reserved1; + uint8_t signature; + uint32_t serial_number; + uint8_t volume_label[11]; + uint8_t system_ident[8]; +} __attribute__((packed)); + +struct FatInfo { + struct MbrPartition partition; + struct AtaDevice dev; + enum FatType type; + struct FatBpb bpb; + union { + struct Fat16Ebpb f16; + struct Fat32Ebpb f32; + } ebpb; +}; + +struct FatFile { + uint8_t name[11]; + uint8_t attributes; + uint32_t start_cluster; + uint32_t size; +}; + +bool fat_init(struct FatInfo *fatinfo, struct AtaDevice dev, struct MbrPartition partition); +bool fat_test(struct FatInfo *fatinfo); diff --git a/kernel/fs/mbr.c b/kernel/fs/mbr.c new file mode 100644 index 0000000..4f9279f --- /dev/null +++ b/kernel/fs/mbr.c @@ -0,0 +1,19 @@ +#include "mbr.h" + +bool mbr_get_partition(struct MbrPartition *dest, struct AtaDevice dev, int n) { + if(n < 0 || n > 3) return false; + uint8_t data[512] __attribute__(( aligned(2) )); + if(!ata_read(dev, 0, 1, (void*)data)) return false; + size_t offset = 0x1BE + n * 0x10; + + uint8_t status = data[offset]; + if((status & 0x7F) != 0) return false; + + dest->n = n; + dest->bootable = status & 0x80 ? true : false; + dest->type = data[offset + 4]; + dest->start_sector = data[offset+8] | (data[offset+9] << 8) | (data[offset+10] << 16) | (data[offset+11] << 24); + dest->sector_count = data[offset+12] | (data[offset+13] << 8) | (data[offset+14] << 16) | (data[offset+15] << 24); + + return true; +} diff --git a/kernel/fs/mbr.h b/kernel/fs/mbr.h new file mode 100644 index 0000000..eb5806b --- /dev/null +++ b/kernel/fs/mbr.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include + +#include "../drivers/ata.h" + +struct MbrPartition { + uint8_t n; + uint8_t type; + bool bootable; + size_t start_sector; + size_t sector_count; +}; + +bool mbr_get_partition(struct MbrPartition *dest, struct AtaDevice device, int n); diff --git a/kernel/interrupt/idt.asm b/kernel/interrupt/idt.asm index b56c3f8..87b6016 100644 --- a/kernel/interrupt/idt.asm +++ b/kernel/interrupt/idt.asm @@ -1,7 +1,7 @@ extern idt_exception_handler extern idt_pic_timer extern idt_pic_keyboard -extern idt_pic_generic +extern idt_pic_eoi global isr_stub_table %macro ISRErrorStub 1 @@ -15,25 +15,25 @@ isr_stub_%+%1: %macro PICGeneric 1 isr_stub_%+%1: push dword %1 - call idt_pic_generic + call idt_pic_eoi pop eax iret %endmacro %macro PICTimer 1 isr_stub_%+%1: - push dword %1 - call idt_pic_generic call idt_pic_timer + push dword %1 + call idt_pic_eoi pop eax iret %endmacro %macro PICKeyboard 1 isr_stub_%+%1: - push dword %1 - call idt_pic_generic call idt_pic_keyboard + push dword %1 + call idt_pic_eoi pop eax iret %endmacro diff --git a/kernel/interrupt/idt.c b/kernel/interrupt/idt.c index 01e0069..4481316 100644 --- a/kernel/interrupt/idt.c +++ b/kernel/interrupt/idt.c @@ -13,7 +13,7 @@ static int timer = 0; -void idt_pic_generic(uint8_t exception) { +void idt_pic_eoi(uint8_t exception) { pic_eoi(exception - PIC_REMAP_OFFSET); } diff --git a/kernel/interrupt/pic.c b/kernel/interrupt/pic.c index dd5e2f6..359b3e5 100644 --- a/kernel/interrupt/pic.c +++ b/kernel/interrupt/pic.c @@ -1,5 +1,4 @@ #include "pic.h" -#include "../term.h" #include #define PIC1_COMMAND_PORT 0x20 diff --git a/kernel/main.c b/kernel/main.c index 0f3fbca..0a9322c 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,10 +1,13 @@ #include #include #include "bootinfo.h" +#include "drivers/ata.h" #include "drivers/keycodes.h" #include "drivers/ps2ctrl.h" #include "drivers/ps2kb.h" -#include "drivers/serial.h" +#include "drivers/pci.h" +#include "fs/fat.h" +#include "fs/mbr.h" #include "panic.h" #include "term.h" #include "interrupt/pic.h" @@ -13,20 +16,27 @@ extern void kmain(void* boot_info) { term_clear(); term_setcol(0x0f); - puts("loading kernel\n"); bootinfo_load(boot_info); - puts("loaded boot info\n"); printf("cmdline: %s\n", bootinfo_get_cmdline()); idt_init(); - puts("initialized idt\n"); pic_remap(PIC_REMAP_OFFSET); - puts("remapped pic\n"); - serial_init(); - puts("initialized serial\n"); ps2ctrl_init(); - puts("enabled ps/2 controller\n"); ps2kb_init(); - puts("enabled keyboard\n"); + pci_init(); + + struct PciDevice pcidev; + if(!pci_findby_class(&pcidev, 0x01, 0x01, NULL)) { + panic("Could not find IDE device"); + } + + struct AtaDevice atadev; + ata_init(&atadev, pcidev); + struct MbrPartition part0; + mbr_get_partition(&part0, atadev, 0); + struct FatInfo fat; + fat_init(&fat, atadev, part0); + fat_test(&fat); + while(1) { int_wait(); diff --git a/kernel/term.c b/kernel/term.c index 0dc65a4..7f61bf8 100644 --- a/kernel/term.c +++ b/kernel/term.c @@ -24,8 +24,7 @@ void putc(char c) { term_x = TERM_W; break; case '\t': - if(term_x % 8 == 0) term_x += 8; - term_x += 7 - (term_x % 8); + term_x += 8 - (term_x % 8); break; default: screen_buf[term_x + term_y * TERM_W] = screen_entry(c, color); @@ -115,14 +114,19 @@ void vprintf(const char *fstr, va_list args) { char buf[80]; for(; *fstr != '\0'; fstr++) { if(*fstr == '%') { - fstr++; - switch(*fstr) { + switch(*++fstr) { case '%': putc('%'); break; + case '@': + putc('@'); + break; case 's': puts(va_arg(args, char*)); break; + case 'c': + putc(va_arg(args, int)); + break; case 'd': itoa(va_arg(args, int), buf, 10, false); puts(buf); @@ -139,15 +143,13 @@ void vprintf(const char *fstr, va_list args) { utoa(va_arg(args, unsigned int), buf, 16, true); puts(buf); break; - case '@': { - uint8_t hi = hex2i(*++fstr); - uint8_t lo = hex2i(*++fstr); - term_setcol((hi << 4) | lo); - break; - } default: break; } + } else if(*fstr == '@') { + uint8_t hi = hex2i(*++fstr); + uint8_t lo = hex2i(*++fstr); + term_setcol((hi << 4) | lo); } else { putc(*fstr); } diff --git a/libk/include/errno.h b/libk/include/errno.h new file mode 100644 index 0000000..b3708e7 --- /dev/null +++ b/libk/include/errno.h @@ -0,0 +1,7 @@ +#pragma once + +enum { + ESUCCESS, + ENOENTRY, + EDISKFAIL, +}; diff --git a/libk/include/sys.h b/libk/include/sys.h index 28eee70..75618e8 100644 --- a/libk/include/sys.h +++ b/libk/include/sys.h @@ -1,12 +1,51 @@ #include -#include -uint8_t inb(uint16_t port); -void outb(uint16_t port, uint8_t val); -void io_wait(void); +static inline uint8_t inb(uint16_t port) { + uint8_t ret; + __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} -void int_enable(void); -void int_disable(void); -void int_wait(void); +static inline void outb(uint16_t port, uint8_t val) { + __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); +} -void halt(void); +static inline uint16_t inw(uint16_t port) { + uint16_t ret; + __asm__ volatile ("inw %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void outw(uint16_t port, uint16_t val) { + __asm__ volatile ("outw %0, %1" : : "a"(val), "Nd"(port)); +} + +static inline uint32_t inl(uint16_t port) { + uint32_t ret; + __asm__ volatile ("inl %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void outl(uint16_t port, uint32_t val) { + __asm__ volatile ("outl %0, %1" : : "a"(val), "Nd"(port)); +} + +static inline void io_wait(void) { + outb(0x80, 0); +} + +static inline void int_enable(void) { + __asm__ volatile ("sti"); +} + +static inline void int_disable(void) { + __asm__ volatile ("cli"); +} + +static inline void int_wait(void) { + __asm__ volatile ("sti; hlt"); +} + +static inline void halt(void) { + __asm__ volatile ("cli; hlt"); +} diff --git a/libk/sys.c b/libk/sys.c deleted file mode 100644 index be448b9..0000000 --- a/libk/sys.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - -uint8_t inb(uint16_t port) { - uint8_t ret; - __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); - return ret; -} - -void outb(uint16_t port, uint8_t val) { - __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); -} - -void io_wait(void) { - outb(0x80, 0); -} - -void int_enable(void) { - __asm__ volatile ("sti"); -} - -void int_disable(void) { - __asm__ volatile ("cli"); -} - -void int_wait(void) { - __asm__ volatile ("sti; hlt"); -} - -void halt(void) { - __asm__ volatile ("cli; hlt"); -} diff --git a/scripts/mkdisk.sh b/scripts/mkdisk.sh new file mode 100755 index 0000000..d1157fb --- /dev/null +++ b/scripts/mkdisk.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +DISKSIZE_MB=16 +DISK=disk.img +OFFSET=1048576 + +dd if=/dev/zero of="$DISK" bs=1M count="$DISKSIZE_MB" + +sfdisk "$DISK" </dev/null; then + echo "unmounting" + umount "$MOUNTPOINT" + losetup -D "$DISK" +else + echo "mounting" + LOOPDEV="$(losetup -f)" + losetup "$LOOPDEV" "$DISK" -o "$OFFSET" + mount "$LOOPDEV" "$MOUNTPOINT" +fi