lots of progress, including readonly PATA driver and part of FAT16 driver

This commit is contained in:
Benji Dial 2020-08-13 17:58:50 -04:00
parent 63167f223e
commit 2ddbeb9f72
27 changed files with 287 additions and 276 deletions

View file

@ -21,7 +21,7 @@ skel:
mkdir -p out/fs
cp -r fs-skel/* out/fs/
kgccargs = -Wall -m32 -Og -ffreestanding -fno-asynchronous-unwind-tables
kgccargs = -Wall -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wsuggest-attribute=malloc -m32 -Og -ffreestanding -fno-asynchronous-unwind-tables
ugccargs = ${kgccargs} -Isrc/libc/inc
nasmargs = -f elf32

View file

@ -38,23 +38,16 @@ enum {
};
enum {
ATA_REG_DATA = 0x0,
ATA_REG_ERROR = 0x1,
ATA_REG_FEAT = 0x1,
ATA_REG_COUNT_LOW = 0x2,
ATA_REG_LBA0 = 0x3,
ATA_REG_LBA1 = 0x4,
ATA_REG_LBA2 = 0x5,
ATA_REG_SELECT = 0x6,
ATA_REG_CMD = 0x7,
ATA_REG_STATUS = 0x7,
ATA_REG_COUNT_HIGH = 0x8,
ATA_REG_LBA3 = 0x9,
ATA_REG_LBA4 = 0xa,
ATA_REG_LBA5 = 0xb,
ATA_REG_CONTROL = 0xc,
ATA_REG_ALT_STATUS = 0xc,
ATA_REG_ADDR = 0xd
ATA_REG_DATA = 0x0,
ATA_REG_ERROR = 0x1,
ATA_REG_FEAT = 0x1,
ATA_REG_COUNT = 0x2,
ATA_REG_LBA0 = 0x3,
ATA_REG_LBA1 = 0x4,
ATA_REG_LBA2 = 0x5,
ATA_REG_SELECT = 0x6,
ATA_REG_CMD = 0x7,
ATA_REG_STATUS = 0x7,
};
enum {
@ -71,5 +64,12 @@ enum {
};
enum {
ATA_CONTROL_NO_IRQS = 0x02
ATA_CONTROL_NO_IRQS = 0x02,
};
enum {
PATA_TYPE_ID = 0x0000,
SATA_TYPE_ID = 0xc33c,
PATAPI_TYPE_ID = 0xeb14,
SATAPI_TYPE_ID = 0x9669
};

View file

@ -1,24 +1,24 @@
#include "drive.h"
#include "fat.h"
#include "panic.h"
#include "fat.h"
uint8_t n_drives = 0;
struct drive drives[256];
drive_file_id_t unknown_get_file(struct drive *d, char *path) {
__attribute__ ((const)) drive_file_id_t unknown_get_file(const struct drive *d, const char *path) {
return 0;
}
void unknown_free_file(struct drive *d, drive_file_id_t fid) {
void unknown_free_file(const struct drive *d, drive_file_id_t fid) {
panic("Free file called on unknown file system");
}
void unknown_load_sector(struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) {
void unknown_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) {
panic("Load sector called on unknown file system");
}
uint32_t unknown_get_free_sectors(struct drive *d) {
return d->n_sectors;
__attribute__ ((const)) uint32_t unknown_get_free_sectors(const struct drive *d) {
return -1;
}
void determine_fs(struct drive *d) {

View file

@ -14,15 +14,15 @@ struct drive {
char *drive_type;
char *fs_type;
uint8_t (*read_sectors)(struct drive *d, uint32_t start, uint32_t count, void *buffer);
uint8_t (*write_sectors)(struct drive *d, uint32_t start, uint32_t count, void *buffer);
uint8_t (*read_sectors)(const struct drive *d, uint32_t start, uint32_t count, void *buffer);
uint8_t (*write_sectors)(const struct drive *d, uint32_t start, uint32_t count, const void *buffer);
uint32_t n_sectors;
drive_id_t drive_id;
drive_file_id_t (*get_file)(struct drive *d, char *path);
void (*free_file)(struct drive *d, drive_file_id_t fid);
void (*load_sector)(struct drive *d, drive_file_id_t fid, uint32_t sector, void *at);
uint32_t (*get_free_sectors)(struct drive *d);
drive_file_id_t (*get_file)(const struct drive *d, const char *path);
void (*free_file)(const struct drive *d, drive_file_id_t fid);
void (*load_sector)(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at);
uint32_t (*get_free_sectors)(const struct drive *d);
fs_id_t fs_id;
};

View file

@ -1,9 +1,9 @@
#include "fat.h"
#include "ata.h"
#include "panic.h"
#include "drive.h"
#include "mem.h"
#include "panic.h"
#include "util.h"
#include "ata.h"
#include "fat.h"
#include "mem.h"
#define MAX_FAT_DRIVES 16
#define MAX_OPEN_FILES_PER_DRIVE 32
@ -57,20 +57,19 @@ struct fat_info {
uint8_t fs_type[8];
} __attribute__ ((packed));
#define CTOS(c, fi) ((fi)->reserved_sectors + (fi)->sectors_per_fat * (fi)->fats + ((fi)->root_entries >> 4) + (c) - 2)
#define CTOS(c, fdi) ((fdi)->data_start + (c) - 2)
struct fat_drive_info {
struct fat_info *fi;
const struct fat_info *fi;
uint16_t *fat;
uint16_t root_start;
uint16_t data_start;
struct directory_entry open_files[MAX_OPEN_FILES_PER_DRIVE];
};
struct fat_drive_info infos[MAX_FAT_DRIVES];
uint8_t next_id = 0;
#define FI(n) ((struct fat_info *)(infos[n].fi + 3))
#define FN(n, f) (infos[n].open_files[f - 1])
uint8_t fat_driver_buffer[512];
struct fat_info *next_fi;
@ -80,8 +79,9 @@ void alloc_next_fi() {
panic("Out of memory in FAT driver.");
}
struct drive *cur_drive;
const struct drive *cur_drive;
fs_id_t cur_id;
const struct fat_drive_info *cur_fdi;
struct directory_entry *cur_dir;
//loads cluster `c`
@ -91,7 +91,7 @@ void load_cluster(uint16_t c, void *to) {
return;
}
uint32_t s = CTOS(c, FI(cur_id));
uint32_t s = CTOS(c, cur_fdi);
cur_drive->read_sectors(cur_drive, s, 1, to);
}
@ -99,7 +99,7 @@ uint16_t next_cluster(uint16_t c) {
panic("TODO: compute next sector (or 0 for none)");
}
static inline bool check_fat_names(uint8_t *a, uint8_t *b) {
static inline bool check_fat_names(const uint8_t *a, const uint8_t *b) {
return (((uint32_t *)a)[0] == ((uint32_t *)b)[0]) &&
(((uint32_t *)a)[1] == ((uint32_t *)b)[1]) &&
(((uint16_t *)a)[8] == ((uint16_t *)b)[8]) &&
@ -107,8 +107,8 @@ static inline bool check_fat_names(uint8_t *a, uint8_t *b) {
}
//after: cur_dir -> specified entry in root
bool try_locate_root_entry(uint8_t *fat_name) {
uint32_t cur_dir_sect = FI(cur_id)->reserved_sectors + FI(cur_id)->sectors_per_fat * FI(cur_id)->fats - 1;
bool try_locate_root_entry(const uint8_t *fat_name) {
uint32_t cur_dir_sect = cur_fdi->root_start - 1;
cur_dir = (struct directory_entry *)(fat_driver_buffer + 512);
while (true) {
if (cur_dir == (struct directory_entry *)(fat_driver_buffer + 512)) {
@ -127,7 +127,7 @@ bool try_locate_root_entry(uint8_t *fat_name) {
//before: cur_dir -> entry of dir to search
//after: cur_dir -> specified entry in dir
bool try_locate_entry(uint8_t *fat_name) {
bool try_locate_entry(const uint8_t *fat_name) {
uint16_t cur_dir_cluster = cur_dir->first_cluster;
load_cluster(cur_dir_cluster, fat_driver_buffer);
cur_dir = (struct directory_entry *)fat_driver_buffer;
@ -146,32 +146,41 @@ bool try_locate_entry(uint8_t *fat_name) {
}
}
drive_file_id_t fat_get_file(struct drive *d, char *path) {
drive_file_id_t fat_get_file(const struct drive *d, const char *path) {
cur_drive = d;
cur_id = d->drive_id;
cur_fdi = &infos[cur_id];
const struct directory_entry *open_files = cur_fdi->open_files - 1;
for (drive_file_id_t n = 1; n != MAX_OPEN_FILES_PER_DRIVE + 1; ++n)
if (!*(uint8_t *)(&FN(d->drive_id, n))) {
panic("TODO: open path at FN(id, n)");
if (!*(uint8_t *)(&open_files[n])) {
panic("TODO: open path into open_files[n]");
return n;
}
panic("Maximum number of files open reached for FAT drive.");
}
void fat_free_file(struct drive *d, drive_file_id_t fid) {
*(uint8_t *)(&FN(d->drive_id, fid)) = 0;
void fat_free_file(const struct drive *d, drive_file_id_t fid) {
*(uint8_t *)(&infos[d->drive_id].open_files[fid - 1]) = 0;
}
void fat_load_sector(struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) {
void fat_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) {
cur_drive = d;
cur_id = d->drive_id;
uint16_t c = FN(d->drive_id, fid).first_cluster;
cur_fdi = &infos[cur_id];
uint16_t c = cur_fdi->open_files[fid - 1].first_cluster;
for (uint32_t i = 0; i < sector; ++i)
c = next_cluster(c);
load_cluster(c, at);
}
uint32_t fat_get_free_sectors(struct drive *d) {
panic("TODO: get free sectors of drive");
__attribute__ ((pure)) uint32_t fat_get_free_sectors(const struct drive *d) {
uint16_t *start = infos[d->fs_id].fat + 2;
uint16_t *end = start + d->n_sectors - infos[d->fs_id].data_start;
uint32_t count = 0;
for (uint16_t *i = start; i < end; ++i)
if (!*i)
++count;
return count;
}
void init_fat() {
@ -186,8 +195,8 @@ bool try_fat_init_drive(struct drive *d) {
return false;
memcpy(next_fi, fat_driver_buffer + 3, sizeof(struct fat_info));
uint32_t *fs_type_32 = (uint32_t *)next_fi->fs_type;
if ((fs_type_32[0] != ('F' + 'A' * 256 + 'T' + 65536 + '1' * 16777216)) ||
(fs_type_32[1] != ('6' + ' ' * 256 + ' ' + 65536 + ' ' * 16777216)))
if ((fs_type_32[0] != ('F' + 'A' * 256 + 'T' * 65536 + '1' * 16777216)) ||
(fs_type_32[1] != ('6' + ' ' * 256 + ' ' * 65536 + ' ' * 16777216)))
return false;
d->fs_type = "FAT16";
@ -199,10 +208,15 @@ bool try_fat_init_drive(struct drive *d) {
d->fs_id = next_id;
infos[next_id].fi = next_fi;
infos[next_id].fat = allocate_pages(((next_fi->sectors_per_fat - 1) >> 3) + 1);
for (drive_file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i)
*(uint8_t *)&FN(next_id, i) = 0;
infos[next_id].root_start = next_fi->reserved_sectors +
next_fi->sectors_per_fat * next_fi->fats;
infos[next_id].data_start = infos[next_id].root_start +
((next_fi->root_entries - 1) >> 4) + 1;
d->read_sectors(d, next_fi->reserved_sectors, next_fi->sectors_per_fat, infos[next_id].fat);
struct directory_entry *open_files = infos[next_id].open_files - 1;
for (drive_file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i)
*(uint8_t *)&open_files[i] = 0;
alloc_next_fi();
++next_id;

View file

@ -1,8 +1,8 @@
#ifndef FAT_H
#define FAT_H
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
#include "drive.h"
void init_fat();

View file

@ -1,171 +1,192 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
#include "drive.h"
#include "panic.h"
#include "util.h"
#include "drive.h"
#include "pci.h"
#include "ata.h"
#include "pci.h"
#define MAX_IDE_DRIVES 8
struct ide_drive_info {
uint16_t base_port;
uint16_t control_port;
uint16_t alt_port;
bool slave;
};
struct ide_drive_info ide_drives[MAX_IDE_DRIVES];
drive_id_t n_ide_drives = 0;
void spin_delay() {
for (uint32_t i = -1; i; --i)
;
typedef uint16_t spinner_t;
//returns the status after waiting
uint8_t wait_after_cmd(uint16_t base_port) {
for (spinner_t n = -1; n; --n) {
uint8_t s = inb(base_port | ATA_REG_STATUS);
if (s & ATA_STATUS_ERROR)
panic("Error status in IDE driver.");
if (!(s & ATA_STATUS_BUSY))
return s;
}
panic("Spun out in IDE driver.");
}
//return true on error condition
bool poll(struct ide_drive_info *info) {
spin_delay();
uint8_t status;
while ((status = inb(info->base_port | ATA_REG_STATUS)) & ATA_STATUS_BUSY)
;
return (status & (ATA_STATUS_ERROR | ATA_STATUS_DRIVE_FAULT)) || !(status & ATA_STATUS_DRIVE_READY);
//returns the status after waiting
uint8_t wait_for_ready(uint16_t base_port) {
for (spinner_t n = -1; n; --n) {
uint8_t s = inb(base_port | ATA_REG_STATUS);
if (s & ATA_STATUS_ERROR)
panic("Error status in IDE driver.");
if (s & ATA_STATUS_DRIVE_READY)
return s;
}
panic("Spun out in IDE driver.");
}
uint8_t ide_ata_rs(struct drive *d, uint32_t start, uint32_t count, void *buffer) {
if (start & 0xf0000000)
panic("IDE ATA driver only supports LBA28 addressing currently.");
//returns the status after waiting
uint8_t wait_for_error_or_ready(uint16_t base_port) {
for (spinner_t n = -1; n; --n) {
uint8_t s = inb(base_port | ATA_REG_STATUS);
if (s & (ATA_STATUS_DRIVE_READY | ATA_STATUS_ERROR))
return s;
}
panic("Spun out in IDE driver.");
}
struct ide_drive_info *info = ide_drives + d->drive_id;
//returns the status after waiting
uint8_t wait_for_data_ready_not_busy(uint16_t base_port) {
for (spinner_t n = -1; n; --n) {
uint8_t s = inb(base_port | ATA_REG_STATUS);
if (!(s & ATA_STATUS_BUSY) && (s & ATA_STATUS_DATA_READY))
return s;
if (s & ATA_STATUS_ERROR)
panic("Error status in IDE driver.");
}
panic("Spun out in IDE driver.");
}
uint8_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) {
if (start >= d->n_sectors)
return 0;
if (start + count > d->n_sectors)
count = d->n_sectors - start;
if (!count)
return 0;
if (start & 0xf0000000)
panic("IDE ATA driver does not support reads starting past 256MiB currently.");
if (count & 0xffffff00)
panic("IDE ATA driver only supports reading up to 128k at a time currently.");
panic("IDE ATA driver does not support reads over 128kiB in length currently.");
uint32_t lba = start & 0x00ffffff;
uint32_t spin = -1;
while (inb(info->base_port | ATA_REG_STATUS) & ATA_STATUS_BUSY)
if (!spin--)
panic("Spun out in IDE ATA reading");
struct ide_drive_info *info = ide_drives + d->drive_id;
outb(info->base_port | ATA_REG_SELECT, (info->slave ? 0xf0 : 0xe0) | (start >> 24));
outb(info->base_port | ATA_REG_COUNT_LOW, count);
//spin?
outb(info->base_port | ATA_REG_COUNT, count);
outb(info->base_port | ATA_REG_LBA0, lba);
outb(info->base_port | ATA_REG_LBA1, lba >> 8);
outb(info->base_port | ATA_REG_LBA2, lba >> 16);
uint16_t *buffer_16 = buffer;
outb(info->base_port | ATA_REG_CMD, ATA_CMD_READ);
uint16_t *buf16 = (uint16_t *)buffer;
for (uint16_t i = 0; i < count; ++i) {
if (poll(info))
return i;
wait_for_data_ready_not_busy(info->base_port);
for (uint16_t j = 0; j < 256; ++j)
*buffer_16++ = inw(info->base_port + ATA_REG_DATA);
*buf16++ = inw(info->base_port | ATA_REG_DATA);
}
return count;
}
uint8_t ide_ata_ws(struct drive *d, uint32_t start, uint32_t count, void *buffer) {
uint8_t ide_ata_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) {
panic("IDE ATA writing not implemented yet");
return 0;
}
uint8_t ide_atapi_rs(struct drive *d, uint32_t start, uint32_t count, void *buffer) {
uint8_t ide_atapi_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) {
//panic("IDE ATAPI reading not implemented yet");
return 0;
}
uint8_t ide_atapi_ws(struct drive *d, uint32_t start, uint32_t count, void *buffer) {
uint8_t ide_atapi_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) {
panic("IDE ATAPI writing not implemented yet");
return 0;
}
struct id_space {
uint16_t device_type;//0
uint8_t skip1[98 - 2];
uint16_t capabilities;//98
uint8_t skip2[120 - (98 + 2)];
uint8_t skip1[120];
uint32_t max_lba;//120
uint8_t skip3[164 - (120 + 4)];
uint32_t command_sets;//164
uint8_t skip4[200 - (164 + 4)];
uint32_t max_lba_ext;//200
uint8_t skip5[512 - (200 + 4)];
} __attribute__ ((__packed__));
uint8_t skip2[512 - (120 + 4)];
} __attribute__ ((__packed__ ));
void read_id_space(uint16_t base_port, struct id_space *to) {
uint32_t *to_32 = (uint32_t *)to;
for (uint8_t i = 0; i < 128; ++i)
*(to_32++) = ind(base_port | ATA_REG_DATA);
}
void vga_printsz(char *s);
void test_drive(uint16_t base_port, uint16_t control_port, bool slave) {
outb(base_port | ATA_REG_SELECT, slave ? ATA_SLAVE_SELECT : ATA_MASTER_SELECT);
spin_delay();
void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) {
if (n_ide_drives == MAX_IDE_DRIVES)
panic("Maximum number of IDE drives reached.");
struct ide_drive_info *next = ide_drives + n_ide_drives;
struct drive next_d;
next_d.drive_id = n_ide_drives;
next->base_port = base_port;
next->alt_port = alt_port;
next->slave = slave;
outb(base_port | ATA_REG_SELECT, slave ? 0xb0 : 0xa0);
outb(base_port | ATA_REG_COUNT, 0);
outb(base_port | ATA_REG_LBA0, 0);
outb(base_port | ATA_REG_LBA1, 0);
outb(base_port | ATA_REG_LBA2, 0);
outb(base_port | ATA_REG_CMD, ATA_CMD_ID);
spin_delay();
if (!inb(base_port | ATA_REG_STATUS))
return;
if (n_ide_drives == MAX_IDE_DRIVES)
panic("Maximum IDE drives reached");
struct id_space ids;
outb(base_port | ATA_REG_CONTROL, ATA_CONTROL_NO_IRQS);
if (!(wait_for_error_or_ready(base_port) & ATA_STATUS_ERROR)) {
wait_for_ready(base_port);
for (uint16_t *ids_16 = (uint16_t *)&ids; ids_16 < (uint16_t *)&ids + 256; ++ids_16)
*ids_16 = inw(base_port | ATA_REG_DATA);
struct ide_drive_info *this_drive = ide_drives + n_ide_drives;
this_drive->base_port = base_port;
this_drive->control_port = control_port;
this_drive->slave = slave;
struct drive data;
data.drive_id = n_ide_drives;
uint32_t spin_out = -1;
while (1) {//wait for identify to complete
uint8_t status = inb(base_port | ATA_REG_STATUS);
if (status & ATA_STATUS_ERROR) {
uint16_t type = inb(base_port | ATA_REG_LBA1) +
(inb(base_port | ATA_REG_LBA2) << 8);
//These two are listed on OSDev Wiki
// as being ATAPI device types.
if ((type != 0xeb14) && (type != 0x9669))
return;
outb(base_port | ATA_REG_CMD, ATAPI_CMD_ID);
data.read_sectors = &ide_atapi_rs;
data.write_sectors = &ide_atapi_ws;
data.drive_type = "IDE ATAPI";
break;
next_d.drive_type = "IDE PATA";
next_d.read_sectors = &ide_ata_rs;
next_d.write_sectors = &ide_ata_ws;
}
else {
uint16_t code = inb(base_port | 0x4) + (inb(base_port | 0x5) << 8);
if (!code) {
panic("PATA identification aborted.");
}
if (!(status & ATA_STATUS_BUSY) && (status & ATA_STATUS_DATA_READY)) {
data.read_sectors = &ide_ata_rs;
data.write_sectors = &ide_ata_ws;
data.drive_type = "IDE ATA";
break;
if (code == 0xeb14) {
next_d.drive_type = "IDE PATAPI";
next_d.read_sectors = &ide_atapi_rs;
next_d.write_sectors = &ide_atapi_ws;
//TODO: issue proper identify command
ids.max_lba = -1;
}
else if (code == 0xc33c) {
next_d.drive_type = "IDE SATA";
//TODO: set up drive hooks, issue proper identify command
return;
}
if (!spin_out--)
panic("IDE ATA identify won't complete");
}
struct id_space id;
read_id_space(base_port, &id);
//in the future, maybe add support for 48-bit LBA, and/or CHS addressing
if (!ids.max_lba)
panic("Encountered ATA drive that doesn't support 28-bit LBA");
next_d.n_sectors = ids.max_lba;
if (!(id.capabilities & ATA_CAP_LBA))
//TODO: CHS compability driver?
return;
data.n_sectors = (id.command_sets & ATA_SET_EXT) ? id.max_lba_ext : id.max_lba;
commit_drive(data);
commit_drive(next_d);
++n_ide_drives;
}
@ -176,14 +197,9 @@ void init_ide() {
while ((device = find_pci_device_from_class_and_subclass(PCI_MASS_STORAGE, PCI_IDE, check_from, &check_from))) {
++check_from;
uint16_t primary_base_port = device->bar0 <= 1 ? 0x01f0 : device->bar0;
uint16_t primary_control_port = device->bar1 <= 1 ? 0x03f6 : device->bar1;
uint16_t secondary_base_port = device->bar2 <= 1 ? 0x0170 : device->bar2;
uint16_t secondary_control_port = device->bar3 <= 1 ? 0x0376 : device->bar3;
test_drive(primary_base_port, primary_control_port, false);
test_drive(primary_base_port, primary_control_port, true);
test_drive(secondary_base_port, secondary_control_port, false);
test_drive(secondary_base_port, secondary_control_port, true);
test_drive(0x01f0, 0x03f6, false);
test_drive(0x01f0, 0x03f6, true);
test_drive(0x0170, 0x0376, false);
test_drive(0x0170, 0x0376, true);
}
}

View file

@ -1,12 +1,6 @@
#ifndef IDE_H
#define IDE_H
#include <stdint.h>
#include "drive.h"
void init_ide();
uint8_t ide_read_sectors(drive_id_t id, uint32_t start, uint32_t count, void *buffer);
uint8_t ide_write_sectors(drive_id_t id, uint32_t start, uint32_t count, void *buffer);
#endif

View file

@ -1,30 +1,20 @@
#include <stdint.h>
#include "vga.h"
#include "serial.h"
#include "panic.h"
#include "boot.h"
#include "util.h"
#include "vesa.h"
#include "fat.h"
#include "ide.h"
#include "panic.h"
#include "serial.h"
#include "util.h"
#include "mem.h"
#include "pci.h"
#include "boot.h"
#include "vesa.h"
char nbuf[11];
#define SOTL(field) field = (void *)((*((uint16_t *)(&field) + 1) << 16) + *(uint16_t *)(&field));
#include "vga.h"
__attribute__ ((noreturn)) void main() {
SOTL(VESA_INFO->oem)
SOTL(VESA_INFO->modes)
SOTL(VESA_INFO->vendor)
SOTL(VESA_INFO->pname)
SOTL(VESA_INFO->prev)
char nbuf[11];
init_mmap();
init_vesa();
init_serial();
vga_blank();
@ -64,8 +54,10 @@ __attribute__ ((noreturn)) void main() {
vga_printch('\n');
init_fat();
//other fs drivers
init_ide();
//other drive drivers
u8_dec(n_drives, nbuf);
vga_printsz(nbuf);
@ -79,24 +71,27 @@ __attribute__ ((noreturn)) void main() {
vga_printsz(nbuf);
vga_printsz(" (");
vga_printsz(d->drive_type);
vga_printsz("): ");
vga_printsz(d->fs_type);
vga_printsz(", ");
u32_dec(d->n_sectors / 2, nbuf);
vga_printsz(nbuf);
if (d->n_sectors % 2)
vga_printsz(".5");
vga_printsz("k, ");
vga_printsz("k): ");
vga_printsz(d->fs_type);
uint32_t free_sectors = d->get_free_sectors(d);
if (free_sectors != -1) {
u32_dec(free_sectors / 2, nbuf);
vga_printsz(", ");
vga_printsz(nbuf);
if (free_sectors % 2)
vga_printsz(".5");
vga_printsz("k free");
}
u32_dec(free_sectors / 2, nbuf);
vga_printsz(nbuf);
if (d->n_sectors % 2)
vga_printsz(".5");
vga_printsz("k free.\n");
vga_printsz(".\n");
}
vga_printch('\n');

View file

@ -1,6 +1,6 @@
#include <stdint.h>
#include <stdbool.h>
#include "panic.h"
#include "mem.h"
#define DYNAMIC_START (0x10000000)
#define DYNAMIC_END (DYNAMIC_START + 65536 * 4096)
@ -55,7 +55,7 @@ void *allocate_pages(uint16_t n) {
}
//in the future, change this to go by bytes or dwords instead of bits.
void free_pages(void *ptr, uint16_t n) {
void free_pages(const void *ptr, uint16_t n) {
uint16_t page = ADDR_TO_PAGE(ptr);
for (uint32_t i = page; i < page + n; ++i)
CLEAR_PAGE(i);

View file

@ -7,7 +7,7 @@ extern uint16_t pages_left;
void init_mmap();
void *allocate_pages(uint16_t n);
void free_pages(void *ptr, uint16_t n);
void *allocate_pages(uint16_t n) __attribute__ ((malloc));
void free_pages(const void *ptr, uint16_t n);
#endif

View file

@ -1,10 +1,7 @@
#include <stdint.h>
#include "vga.h"
#include "serial.h"
#include "util.h"
#include "panic.h"
#include "vga.h"
void panic(char *message) {
void panic(const char *message) {
vga_set_color(0x4f);
vga_blank();
vga_printsz("Kernel panic: ");

View file

@ -1,8 +1,6 @@
#ifndef PANIC_H
#define PANIC_H
#include <stdint.h>
void panic(char *message) __attribute__ ((noreturn));
void panic(const char *message) __attribute__ ((noreturn));
#endif

View file

@ -1,8 +1,8 @@
#include "boot.h"
#include "mem.h"
#include "util.h"
#include "pci.h"
#include "panic.h"
#include "boot.h"
#include "util.h"
#include "mem.h"
#include "pci.h"
enum {
PCP_SELECT = 0x0cf8,
@ -59,11 +59,6 @@ void pci_device_check(uint16_t number) {
next_device->class = class >> 24;
next_device->subclass = class >> 16;
next_device->iface = class >> 8;
next_device->bar0 = pci_read_config(number, 4);
next_device->bar1 = pci_read_config(number, 5);
next_device->bar2 = pci_read_config(number, 6);
next_device->bar3 = pci_read_config(number, 7);
}
void pci_init() {

View file

@ -20,16 +20,10 @@ struct pci_device {
uint8_t class;
uint8_t subclass;
uint8_t iface;
uint32_t bar0;
uint32_t bar1;
uint32_t bar2;
uint32_t bar3;
//etc
};
extern uint16_t n_pci_devices;
struct pci_device *nth_pci_device(uint16_t n);
struct pci_device *nth_pci_device(uint16_t n) __attribute__ ((pure));
struct pci_device *find_pci_device_from_class_and_subclass(uint8_t class, uint8_t subclass, uint16_t start, uint16_t *index);

View file

@ -1,13 +1,12 @@
#include <stdint.h>
#include <stdbool.h>
#include "plef.h"
#include "drive.h"
#include "util.h"
#include "plef.h"
#include "task.h"
#include "util.h"
#define PLEF_MAGIC 0xb9ba4c50
task_handle plef_run(struct drive *d, char *path) {
task_handle plef_run(const struct drive *d, const char *path) {
drive_file_id_t h = d->get_file(d, path);
if (!h)
return 0;

View file

@ -2,7 +2,6 @@
#define PLEF_H
#include <stdint.h>
#include <stdbool.h>
#include "drive.h"
typedef uint8_t task_handle;
@ -17,6 +16,6 @@ struct plef_header {
uint32_t entry_point;
} __attribute__ ((packed));
task_handle plef_run(struct drive *d, char *path);
task_handle plef_run(const struct drive *d, const char *path);
#endif

View file

@ -1,5 +1,6 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
#include "serial.h"
#include "util.h"
enum {
@ -76,12 +77,12 @@ void sout(char b) {
outb(CP_1 | CP_DATA, (uint8_t)b);
}
void soutsz(char *s) {
void soutsz(const char *s) {
while (*s)
sout(*(s++));
}
void soutsn(char *s, uint8_t n) {
void soutsn(const char *s, uint8_t n) {
while (n--)
sout(*(s++));
}

View file

@ -1,14 +1,14 @@
#ifndef SERIAL_H
#define SERIAL_H
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
bool serr();
bool serr() __attribute__ ((pure));
void init_serial();
void sout(char b);
void soutsz(char *s);
void soutsn(char *s, uint8_t n);
void soutsz(const char *s);
void soutsn(const char *s, uint8_t n);
char sin();
void sinsn(char *s, uint8_t n);

View file

@ -1,5 +1,5 @@
#include "task.h"
#include "panic.h"
#include "task.h"
segment_id new_segment(bool is_code, uint32_t length, uint32_t *location_out) {
panic("TODO: make new segment");

View file

@ -1,8 +1,8 @@
#ifndef TASK_H
#define TASK_H
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
typedef uint8_t segment_id;
typedef uint8_t task_handle;

View file

@ -1,10 +1,10 @@
#include <stdint.h>
#include "panic.h"
#include <stdbool.h>
#include <stdint.h>
#include "drive.h"
void memcpy(void *to, void *from, uint32_t n) {
uint32_t *tp = to, *fp = from;
void memcpy(void *to, const void *from, uint32_t n) {
uint32_t *tp = to;
const uint32_t *fp = from;
while (n >= 4) {
*(tp++) = *(fp++);
n -= 4;
@ -14,7 +14,7 @@ void memcpy(void *to, void *from, uint32_t n) {
*(tpp++) = *(fpp++);
}
void fmcpy(void *to, struct drive *d, drive_file_id_t f, uint32_t from, uint32_t n) {
void fmcpy(void *to, const struct drive *d, drive_file_id_t f, uint32_t from, uint32_t n) {
uint8_t buf[512];
d->load_sector(d, f, from >> 9, buf);
uint16_t from_low = from & 511;

View file

@ -10,8 +10,8 @@ static inline void outb(uint16_t port, uint8_t value) {
: : "a"(value), "Nd"(port));
}
static inline uint8_t inb(uint16_t port) {
uint8_t value;
asm volatile (
volatile uint8_t value;
asm (
"inb %1, %0"
: "=a"(value) : "Nd"(port));
return value;
@ -22,8 +22,8 @@ static inline void outw(uint16_t port, uint16_t value) {
: : "a"(value), "Nd"(port));
}
static inline uint16_t inw(uint16_t port) {
uint16_t value;
asm volatile (
volatile uint16_t value;
asm (
"inw %1, %0"
: "=a"(value) : "Nd"(port));
return value;
@ -34,15 +34,15 @@ static inline void outd(uint16_t port, uint32_t value) {
: : "a"(value), "Nd"(port));
}
static inline uint32_t ind(uint16_t port) {
uint32_t value;
asm volatile (
volatile uint32_t value;
asm (
"inl %1, %0"
: "=a"(value) : "Nd"(port));
return value;
}
void memcpy(void *to, void *from, uint32_t n);
void fmcpy(void *to, struct drive *d, drive_file_id_t f, uint32_t from, uint32_t n);
void memcpy(void *to, const void *from, uint32_t n);
void fmcpy(void *to, const struct drive *d, drive_file_id_t f, uint32_t from, uint32_t n);
void u32_dec(uint32_t n, char *b);
void u16_dec(uint16_t n, char *b);

View file

@ -1,5 +1,21 @@
#include "vesa.h"
uint16_t screen_width;
uint16_t screen_height;
uint8_t bpp;
void *frame_buffer;
void put_pixel(uint16_t x, uint16_t y, color c) {
}
void screen_fill(color c) {
}
void init_vesa() {
// for (void *v = 0; v < 0x65536; ++v) {
// if (*(uint32_t *)v == 'P' + 'M' * 256 + 'I' * 65536 + 'D' * 16777216)
// }
}

View file

@ -1,23 +1,16 @@
#ifndef VESA_H
#define VESA_H
struct video_mode {
//TODO
};
#include <stdint.h>
#define VESA_INFO \
((struct { \
uint32_t sig; \
uint16_t vbe_ver; \
char *oem; \
uint32_t capabilities; \
struct video_mode *modes; \
uint16_t vram_size_high; \
uint16_t soft_ver; \
char *vendor; \
char *pname; \
char *prev; \
} *)0x4200)
extern uint16_t screen_width;
extern uint16_t screen_height;
extern uint8_t bpp;
typedef uint32_t color;
void put_pixel(uint16_t x, uint16_t y, color c);
void screen_fill(color c);
void init_vesa();

View file

@ -1,5 +1,5 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
#define VGA_COM_MIRROR
@ -50,12 +50,12 @@ void vga_printch(char ch) {
vga_scroll();
}
void vga_printsz(char *sz) {
void vga_printsz(const char *sz) {
while (*sz)
vga_printch(*(sz++));
}
void vga_printsn(char *sn, uint8_t n) {
void vga_printsn(const char *sn, uint8_t n) {
while (n--)
vga_printch(*(sn++));
}

View file

@ -7,7 +7,7 @@ void vga_set_color(uint8_t color);
void vga_blank();
void vga_scroll();
void vga_printch(char ch);
void vga_printsz(char *sz);
void vga_printsn(char *sn, uint8_t n);
void vga_printsz(const char *sz);
void vga_printsn(const char *sn, uint8_t n);
#endif