summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/boot.asm28
-rw-r--r--src/kernel/drive.c23
-rw-r--r--src/kernel/drive.h20
-rw-r--r--src/kernel/fat.c221
-rw-r--r--src/kernel/ide.c34
-rw-r--r--src/kernel/log.c25
-rw-r--r--src/kernel/log.h9
-rw-r--r--src/kernel/main.c75
-rw-r--r--src/kernel/main2.c59
-rw-r--r--src/kernel/panic.c7
-rw-r--r--src/kernel/pci.c11
-rw-r--r--src/kernel/serial.c67
-rw-r--r--src/kernel/serial.h18
-rw-r--r--src/kernel/vesa.c21
-rw-r--r--src/kernel/vesa.h17
-rw-r--r--src/kernel/vga.c44
-rw-r--r--src/kernel/vga.h2
17 files changed, 431 insertions, 250 deletions
diff --git a/src/boot.asm b/src/boot.asm
index eb3b2c9..c74145c 100644
--- a/src/boot.asm
+++ b/src/boot.asm
@@ -5,13 +5,12 @@ kernel_sectors equ 64
kernel_segment equ 0x3000
support_flags equ 0x4000
-pci_hw_char equ 0x4001
-pci_ver equ 0x4002
+pci_hw_char equ 0x4001
+pci_ver equ 0x4002
+last_pci_bus equ 0x4004
pci_support equ 0x80
-vesa_segment equ 0x0420
-
in al, 0x92
or al, 0x02
out 0x92, al
@@ -44,19 +43,9 @@ vesa_segment equ 0x0420
mov byte [support_flags], pci_support
mov byte [pci_hw_char], al
mov word [pci_ver], bx
+ mov byte [last_pci_bus], cl
no_pci:
- mov dword [vesa_segment * 16], 'V' + 'B' * 256 + 'E' * 65535 + '2' * 16777216
-
- mov ax, vesa_segment
- mov es, ax
- xor di, di
- mov ax, 0x4f00
- int 0x10
-
- cmp ax, 0x004f
- jne no_vbe
-
cli
lgdt [gdt]
@@ -67,15 +56,6 @@ no_pci:
jmp 0x08:pmode
-no_vbe:
- ;TODO
-
- cli
-
-real_halt:
- hlt
- jmp real_halt
-
bits 32
pmode:
diff --git a/src/kernel/drive.c b/src/kernel/drive.c
index b001aca..38fef38 100644
--- a/src/kernel/drive.c
+++ b/src/kernel/drive.c
@@ -5,23 +5,34 @@
uint8_t n_drives = 0;
struct drive drives[256];
-__attribute__ ((const)) drive_file_id_t unknown_get_file(const struct drive *d, const char *path) {
+__attribute__ ((const))
+static drive_file_id_t unknown_get_file(const struct drive *d, const char *path) {
return 0;
}
-void unknown_free_file(const struct drive *d, drive_file_id_t fid) {
+static 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(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) {
+static 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");
}
-__attribute__ ((const)) uint32_t unknown_get_free_sectors(const struct drive *d) {
+static uint32_t unknown_get_file_length(const struct drive *d, drive_file_id_t fid) {
+ panic("Get file length called on unknown file system");
+}
+
+__attribute__ ((const))
+static uint32_t unknown_get_free_sectors(const struct drive *d) {
return -1;
}
-void determine_fs(struct drive *d) {
+__attribute__ ((const))
+static uint32_t unknown_enumerate_dir(const struct drive *d, const char *path, struct directory_content_info *info, uint32_t max) {
+ return 0;
+}
+
+static void determine_fs(struct drive *d) {
if (try_fat_init_drive(d))
return;
@@ -29,6 +40,8 @@ void determine_fs(struct drive *d) {
d->get_file = &unknown_get_file;
d->free_file = &unknown_free_file;
d->load_sector = &unknown_load_sector;
+ d->get_file_length = &unknown_get_file_length;
+ d->enumerate_dir = &unknown_enumerate_dir;
d->get_free_sectors = &unknown_get_free_sectors;
}
diff --git a/src/kernel/drive.h b/src/kernel/drive.h
index ca6d1ee..8eb6955 100644
--- a/src/kernel/drive.h
+++ b/src/kernel/drive.h
@@ -1,6 +1,7 @@
#ifndef DRIVE_H
#define DRIVE_H
+#include <stdbool.h>
#include <stdint.h>
typedef uint8_t drive_file_id_t;
@@ -9,20 +10,29 @@ typedef uint8_t fs_id_t;
typedef uint8_t drive_id_t;
#define MAX_DRIVES 256
+#define DCI_NAME_LEN 100
+
+struct directory_content_info {
+ bool is_dir;
+ char name[DCI_NAME_LEN];
+ uint32_t size;
+};
struct drive {
char *drive_type;
char *fs_type;
- uint8_t (*read_sectors)(const 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)(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);
+ 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_file_length) (const struct drive *d, drive_file_id_t fid);
+ uint32_t (*enumerate_dir) (const struct drive *d, const char *path, struct directory_content_info *info, uint32_t max);
+ uint32_t (*get_free_sectors)(const struct drive *d);
fs_id_t fs_id;
};
diff --git a/src/kernel/fat.c b/src/kernel/fat.c
index 807af00..ff01d7d 100644
--- a/src/kernel/fat.c
+++ b/src/kernel/fat.c
@@ -8,6 +8,9 @@
#define MAX_FAT_DRIVES 16
#define MAX_OPEN_FILES_PER_DRIVE 32
+#define PATH_SEP_CHAR '/'
+#define EXT_SEP_CHAR '.'
+
enum {
FA_READ_ONLY = 0x01,
FA_HIDDEN = 0x02,
@@ -59,33 +62,44 @@ struct fat_info {
#define CTOS(c, fdi) ((fdi)->data_start + (c) - 2)
+struct open_file_info {
+ //directory entry is the di_number'th entry in the di_sector'th sector
+ //di_sector of 0 indicates an unused handle
+ uint32_t di_sector;
+ uint8_t di_number;
+
+ uint16_t start_cluster;
+ uint32_t length;
+};
+
struct fat_drive_info {
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 open_file_info open_files[MAX_OPEN_FILES_PER_DRIVE];
};
-struct fat_drive_info infos[MAX_FAT_DRIVES];
-uint8_t next_id = 0;
+static struct fat_drive_info infos[MAX_FAT_DRIVES];
+static uint8_t next_id = 0;
-uint8_t fat_driver_buffer[512];
-struct fat_info *next_fi;
+static uint8_t fat_driver_buffer[512];
+static struct fat_info *next_fi;
-void alloc_next_fi() {
+static void alloc_next_fi() {
if (!((uint32_t)(next_fi = (struct fat_info *)((uint32_t)next_fi + 64)) & 0xfff))
if (!(next_fi = allocate_pages(1)))
panic("Out of memory in FAT driver.");
}
-const struct drive *cur_drive;
-fs_id_t cur_id;
-const struct fat_drive_info *cur_fdi;
-struct directory_entry *cur_dir;
+static const struct drive *cur_drive;
+static fs_id_t cur_id;
+static const struct fat_drive_info *cur_fdi;
+static struct directory_entry *cur_dir;
+static uint32_t cur_sect;
//loads cluster `c`
-void load_cluster(uint16_t c, void *to) {
+static void load_cluster(uint16_t c, void *to) {
if (c == 0) {
*(uint8_t *)to = 0;
return;
@@ -95,26 +109,29 @@ void load_cluster(uint16_t c, void *to) {
cur_drive->read_sectors(cur_drive, s, 1, to);
}
-uint16_t next_cluster(uint16_t c) {
+static uint16_t next_cluster(uint16_t c) {
panic("TODO: compute next sector (or 0 for none)");
}
+static const uint8_t this_dir[] = {'.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
+static const uint8_t parent_dir[] = {'.', '.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
+
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]) &&
+ (((uint16_t *)a)[4] == ((uint16_t *)b)[4]) &&
(((uint8_t *)a)[10] == ((uint8_t *)b)[10]);
}
//after: cur_dir -> specified entry in root
-bool try_locate_root_entry(const uint8_t *fat_name) {
- uint32_t cur_dir_sect = cur_fdi->root_start - 1;
+static bool try_locate_root_entry(const uint8_t *fat_name) {
+ cur_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)) {
cur_dir = (struct directory_entry *)fat_driver_buffer;
- ++cur_dir_sect;
- cur_drive->read_sectors(cur_drive, cur_dir_sect, 1, cur_dir);
+ ++cur_sect;
+ cur_drive->read_sectors(cur_drive, cur_sect, 1, cur_dir);
}
if (!*(uint8_t *)cur_dir)
return false;
@@ -127,53 +144,109 @@ bool try_locate_root_entry(const uint8_t *fat_name) {
//before: cur_dir -> entry of dir to search
//after: cur_dir -> specified entry in dir
-bool try_locate_entry(const uint8_t *fat_name) {
+static 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;
while (true) {
if (cur_dir == (struct directory_entry *)(fat_driver_buffer + 512)) {
cur_dir = (struct directory_entry *)fat_driver_buffer;
- ++cur_dir_cluster;
load_cluster(cur_dir_cluster = next_cluster(cur_dir_cluster), fat_driver_buffer);
}
if (!*(uint8_t *)cur_dir)
return false;
- if (check_fat_names(cur_dir -> name, fat_name))
+ if (check_fat_names(cur_dir->name, fat_name)) {
+ cur_sect = CTOS(cur_dir_cluster, cur_fdi);
return true;
+ }
else
++cur_dir;
}
}
-drive_file_id_t fat_get_file(const struct drive *d, const char *path) {
+//puts first path component's fat name into fat_name_buffer,
+//returns rest of path
+static const char *split_path(const char *path, uint8_t *fat_name_buffer) {
+ uint8_t pi = 0, fi = 0;
+ while (1) {
+ if ((path[pi] == PATH_SEP_CHAR) || !path[pi]) {
+ while (fi != 11)
+ fat_name_buffer[fi++] = (uint8_t)' ';
+ return path + (path[pi] ? pi + 1 : pi);
+ }
+ if (path[pi] == EXT_SEP_CHAR)
+ if (fi <= 8) {
+ while (fi != 8)
+ fat_name_buffer[fi++] = (uint8_t)' ';
+ ++pi;
+ }
+ else
+ panic("Bad path in FAT16 driver");
+ else if ((fi == 8) || (fi == 11))
+ panic("Bad path in FAT16 driver");
+ else {
+ fat_name_buffer[fi++] = (uint8_t)path[pi++];
+ }
+ }
+}
+
+//cur_dir -> specified entry
+static bool try_load_from_path(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;
+
+ uint8_t fat_name[11];
+ path = split_path(path, fat_name);
+ if (!try_locate_root_entry(fat_name))
+ return false;
+ while (*path) {
+ path = split_path(path, fat_name);
+ if (!try_locate_entry(fat_name))
+ return false;
+ }
+
+ return true;
+}
+
+static drive_file_id_t fat_get_file(const struct drive *d, const char *path) {
+ struct open_file_info *open_files = infos[d->drive_id].open_files - 1;
for (drive_file_id_t n = 1; n != MAX_OPEN_FILES_PER_DRIVE + 1; ++n)
- if (!*(uint8_t *)(&open_files[n])) {
- panic("TODO: open path into open_files[n]");
+ if (!open_files[n].di_sector) {
+ if (!try_load_from_path(d, path))
+ return 0;
+
+ open_files[n].di_sector = cur_sect;
+ open_files[n].di_number = cur_dir - (struct directory_entry *)fat_driver_buffer;
+ open_files[n].start_cluster = cur_dir->first_cluster;
+ open_files[n].length = cur_dir->length;
return n;
}
+
panic("Maximum number of files open reached for FAT drive.");
}
-void fat_free_file(const struct drive *d, drive_file_id_t fid) {
- *(uint8_t *)(&infos[d->drive_id].open_files[fid - 1]) = 0;
+static void fat_free_file(const struct drive *d, drive_file_id_t fid) {
+ infos[d->drive_id].open_files[fid - 1].di_sector = 0;
}
-void fat_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) {
+static 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;
cur_fdi = &infos[cur_id];
- uint16_t c = cur_fdi->open_files[fid - 1].first_cluster;
+ uint16_t c = cur_fdi->open_files[fid - 1].start_cluster;
for (uint32_t i = 0; i < sector; ++i)
c = next_cluster(c);
load_cluster(c, at);
}
-__attribute__ ((pure)) uint32_t fat_get_free_sectors(const struct drive *d) {
+__attribute__ ((pure))
+static uint32_t fat_get_file_length(const struct drive *d, drive_file_id_t fid) {
+ return infos[d->drive_id].open_files[fid - 1].length;
+}
+
+__attribute__ ((pure))
+static 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;
@@ -183,6 +256,90 @@ __attribute__ ((pure)) uint32_t fat_get_free_sectors(const struct drive *d) {
return count;
}
+static void fat_name_to_path(const uint8_t *fat_name, char *path) {
+ uint8_t last_visible = -1;
+ for (uint8_t i = 0; i < 8; ++i) {
+ if (fat_name[i] != (uint8_t)' ')
+ last_visible = i;
+ path[i] = (char)fat_name[i];
+ }
+
+ if (fat_name[8] || fat_name[9] || fat_name[10]) {
+ path[last_visible + 1] = EXT_SEP_CHAR;
+ for (uint8_t fi = 8, ti = last_visible + 2; fi < 11; ++fi, ++ti) {
+ if (fat_name[fi] != (uint8_t)' ')
+ last_visible = ti;
+ path[ti] = (char)fat_name[fi];
+ }
+ }
+
+ path[last_visible + 1] = '\0';
+}
+
+static uint32_t enumerate_root(const struct drive *d, struct directory_content_info *info, uint32_t max) {
+ uint32_t sect = infos[d->drive_id].root_start - 1;
+ struct directory_entry *entry = (struct directory_entry *)(fat_driver_buffer + 512);
+ struct directory_content_info *fill = info;
+
+ while (true) {
+ if (entry == (struct directory_entry *)(fat_driver_buffer + 512)) {
+ entry = (struct directory_entry *)fat_driver_buffer;
+ ++sect;
+ d->read_sectors(d, sect, 1, entry);
+ }
+
+ if (!*(uint8_t *)entry || (info == fill + max))
+ return fill - info;
+
+ if (entry-> attrib & FA_LABEL) {
+ ++entry;
+ continue;
+ }
+
+ fill->is_dir = entry->attrib & FA_DIRECTORY;
+ fill->size = entry->length;
+ fat_name_to_path(entry->name, fill->name);
+
+ ++entry;
+ ++fill;
+ }
+}
+
+static uint32_t fat_enumerate_dir(const struct drive *d, const char *path, struct directory_content_info *info, uint32_t max) {
+ if (!*path)
+ return enumerate_root(d, info, max);
+
+ if (!try_load_from_path(d, path))
+ return 0;
+
+ uint16_t cluster = cur_dir->first_cluster;
+ load_cluster(cluster, fat_driver_buffer);
+ struct directory_entry *entry = (struct directory_entry *)fat_driver_buffer;
+ struct directory_content_info *fill = info;
+
+ while (true) {
+ if (entry == (struct directory_entry *)(fat_driver_buffer + 512)) {
+ entry = (struct directory_entry *)fat_driver_buffer;
+ load_cluster(cluster = next_cluster(cluster), fat_driver_buffer);
+ }
+
+ if (!*(uint8_t *)entry || (fill == info + max))
+ return fill - info;
+
+ if (check_fat_names(entry->name, this_dir) || check_fat_names(entry->name, parent_dir)) {
+ ++entry;
+ continue;
+ }
+
+ fill->is_dir = entry->attrib & FA_DIRECTORY;
+ fill->size = entry->length;
+ fat_name_to_path(entry->name, fill->name);
+
+ ++entry;
+ ++fill;
+ }
+}
+
void init_fat() {
next_fi = allocate_pages(1);
}
@@ -203,6 +360,8 @@ bool try_fat_init_drive(struct drive *d) {
d->get_file = &fat_get_file;
d->free_file = &fat_free_file;
d->load_sector = &fat_load_sector;
+ d->get_file_length = &fat_get_file_length;
+ d->enumerate_dir = &fat_enumerate_dir;
d->get_free_sectors = &fat_get_free_sectors;
d->fs_id = next_id;
@@ -214,9 +373,9 @@ bool try_fat_init_drive(struct drive *d) {
((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;
+ struct open_file_info *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;
+ open_files[i].di_sector = 0;
alloc_next_fi();
++next_id;
diff --git a/src/kernel/ide.c b/src/kernel/ide.c
index a32f149..a4ba34c 100644
--- a/src/kernel/ide.c
+++ b/src/kernel/ide.c
@@ -14,25 +14,13 @@ struct ide_drive_info {
bool slave;
};
-struct ide_drive_info ide_drives[MAX_IDE_DRIVES];
-drive_id_t n_ide_drives = 0;
+static struct ide_drive_info ide_drives[MAX_IDE_DRIVES];
+static drive_id_t n_ide_drives = 0;
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.");
-}
-
-//returns the status after waiting
-uint8_t wait_for_ready(uint16_t base_port) {
+static 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)
@@ -44,7 +32,7 @@ uint8_t wait_for_ready(uint16_t base_port) {
}
//returns the status after waiting
-uint8_t wait_for_error_or_ready(uint16_t base_port) {
+static 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))
@@ -54,7 +42,7 @@ uint8_t wait_for_error_or_ready(uint16_t base_port) {
}
//returns the status after waiting
-uint8_t wait_for_data_ready_not_busy(uint16_t base_port) {
+static 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))
@@ -65,7 +53,7 @@ uint8_t wait_for_data_ready_not_busy(uint16_t base_port) {
panic("Spun out in IDE driver.");
}
-uint8_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) {
+static 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)
@@ -103,17 +91,17 @@ uint8_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void *
return count;
}
-uint8_t ide_ata_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) {
+static 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(const struct drive *d, uint32_t start, uint32_t count, void *buffer) {
+static 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(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) {
+static 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;
}
@@ -124,9 +112,7 @@ struct id_space {
uint8_t skip2[512 - (120 + 4)];
} __attribute__ ((__packed__ ));
-void vga_printsz(char *s);
-
-void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) {
+static 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.");
diff --git a/src/kernel/log.c b/src/kernel/log.c
new file mode 100644
index 0000000..e8695cc
--- /dev/null
+++ b/src/kernel/log.c
@@ -0,0 +1,25 @@
+#include "vga.h"
+#include "serial.h"
+
+#define INFO_COM COM1
+
+void init_log() {
+ vga_set_color(0x2f);
+ vga_blank();
+}
+
+void logch(char ch) {
+ if (ch == '\n') {
+ sout(INFO_COM, (uint8_t)'\r');
+ sout(INFO_COM, (uint8_t)'\n');
+ }
+ else
+ sout(INFO_COM, (uint8_t)ch);
+
+ vga_printch(ch);
+}
+
+void logsz(const char *sz) {
+ while (*sz)
+ logch(*sz++);
+} \ No newline at end of file
diff --git a/src/kernel/log.h b/src/kernel/log.h
new file mode 100644
index 0000000..ff2a7a2
--- /dev/null
+++ b/src/kernel/log.h
@@ -0,0 +1,9 @@
+#ifndef LOG_H
+#define LOG_H
+
+void init_log();
+
+void logch(char ch);
+void logsz(const char *sz);
+
+#endif \ No newline at end of file
diff --git a/src/kernel/main.c b/src/kernel/main.c
index cbdebfa..0c57ef3 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -3,55 +3,56 @@
#include "panic.h"
#include "boot.h"
#include "util.h"
-#include "vesa.h"
#include "fat.h"
#include "ide.h"
#include "mem.h"
#include "pci.h"
-#include "vga.h"
+#include "log.h"
-__attribute__ ((noreturn)) void main() {
+void tree(struct drive *d);
+
+__attribute__ ((noreturn))
+void main() {
char nbuf[11];
init_mmap();
- init_vesa();
init_serial();
+ init_log();
- vga_blank();
- vga_printsz("Portland v0.0.11\n\n");
+ logsz("Portland v0.0.11\n\n");
//list vesa modes?
pci_init();
u16_dec(n_pci_devices, nbuf);
- vga_printsz(nbuf);
- vga_printsz(" PCI device(s) found:\n");
+ logsz(nbuf);
+ logsz(" PCI device(s) found:\n");
for (uint16_t n = 0; n < n_pci_devices; ++n) {
struct pci_device *pd = nth_pci_device(n);
u16_hex(pd->number, nbuf);
- vga_printsz(" ");
- vga_printsz(nbuf);
- vga_printsz(": ");
+ logsz(" ");
+ logsz(nbuf);
+ logsz(": ");
u16_hex(pd->id_vendor, nbuf);
nbuf[4] = '.';
u16_hex(pd->id_device, nbuf + 5);
- vga_printsz(nbuf);
+ logsz(nbuf);
u8_hex(pd->class, nbuf);
nbuf[2] = '.';
u8_hex(pd->subclass, nbuf + 3);
nbuf[5] = '.';
u8_hex(pd->iface, nbuf + 6);
- vga_printsz(" (");
- vga_printsz(nbuf);
- vga_printsz(")\n");
+ logsz(" (");
+ logsz(nbuf);
+ logsz(")\n");
}
- vga_printch('\n');
+ logch('\n');
init_fat();
//other fs drivers
@@ -60,49 +61,49 @@ __attribute__ ((noreturn)) void main() {
//other drive drivers
u8_dec(n_drives, nbuf);
- vga_printsz(nbuf);
- vga_printsz(" drive(s) found:\n");
+ logsz(nbuf);
+ logsz(" drive(s) found:\n");
for (uint8_t n = 0; n < n_drives; ++n) {
struct drive *d = drives + n;
u8_dec(n, nbuf);
- vga_printsz(" sd");
- vga_printsz(nbuf);
- vga_printsz(" (");
- vga_printsz(d->drive_type);
- vga_printsz(", ");
+ logsz(" sd");
+ logsz(nbuf);
+ logsz(" (");
+ logsz(d->drive_type);
+ logsz(", ");
u32_dec(d->n_sectors / 2, nbuf);
- vga_printsz(nbuf);
+ logsz(nbuf);
if (d->n_sectors % 2)
- vga_printsz(".5");
- vga_printsz("k): ");
+ logsz(".5");
+ logsz("k): ");
- vga_printsz(d->fs_type);
+ logsz(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);
+ logsz(", ");
+ logsz(nbuf);
if (free_sectors % 2)
- vga_printsz(".5");
- vga_printsz("k free");
+ logsz(".5");
+ logsz("k free");
}
- vga_printsz(".\n");
+ logsz(".\n");
}
- vga_printch('\n');
+ logch('\n');
u32_dec(pages_left * 4, nbuf);
- vga_printsz(nbuf);
- vga_printsz("k dynamic memory free.\n\n");
+ logsz(nbuf);
+ logsz("k dynamic memory free.\n\n");
- vga_printsz("Loading init process.");
+ logsz("sd0 root:\n");
+ tree(&drives[0]);
- vga_printsz("\n\nTODO: load and switch to init process");
while (1)
asm ("hlt");
} \ No newline at end of file
diff --git a/src/kernel/main2.c b/src/kernel/main2.c
new file mode 100644
index 0000000..2b85592
--- /dev/null
+++ b/src/kernel/main2.c
@@ -0,0 +1,59 @@
+#include <stdint.h>
+#include "drive.h"
+#include "util.h"
+#include "log.h"
+
+static char nbuf2[11];
+
+static char path_builder[200] = "";
+static uint8_t path_builder_len = 0;
+
+static char indent_builder[20] = " ";
+static uint8_t indent_builder_len = 2;
+
+void tree(struct drive *d) {
+ struct directory_content_info infos[100];
+ uint8_t n_infos = d->enumerate_dir(d, path_builder, infos, 100);
+
+ if (!n_infos) {
+ logsz(indent_builder);
+ logsz("(empty)\n");
+ return;
+ }
+
+ for (uint8_t i = 0; i < n_infos; ++i) {
+ logsz(indent_builder);
+ logsz(infos[i].name);
+
+ if (infos[i].is_dir) {
+ logsz(":\n");
+
+ indent_builder[indent_builder_len] = ' ';
+ indent_builder[indent_builder_len + 1] = ' ';
+ indent_builder[indent_builder_len + 2] = '\0';
+ indent_builder_len += 2;
+
+ uint8_t name_length = 0;
+ while (infos[i].name[name_length])
+ ++name_length;
+
+ memcpy(path_builder + path_builder_len, infos[i].name, name_length + 1);
+ path_builder_len += name_length;
+
+ tree(d);
+
+ path_builder_len -= name_length;
+ path_builder[path_builder_len] = '\0';
+
+ indent_builder_len -= 2;
+ indent_builder[indent_builder_len] = '\0';
+ }
+
+ else {
+ u32_dec(infos[i].size, nbuf2);
+ logsz(" (");
+ logsz(nbuf2);
+ logsz(" bytes)\n");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/kernel/panic.c b/src/kernel/panic.c
index e04ae38..7793065 100644
--- a/src/kernel/panic.c
+++ b/src/kernel/panic.c
@@ -1,12 +1,13 @@
#include "panic.h"
+#include "log.h"
#include "vga.h"
void panic(const char *message) {
vga_set_color(0x4f);
vga_blank();
- vga_printsz("Kernel panic: ");
- vga_printsz(message);
- vga_printsz("\nHalting.");
+ logsz("Kernel panic: ");
+ logsz(message);
+ logsz("\nHalting.");
while (1)
asm volatile ("hlt");
} \ No newline at end of file
diff --git a/src/kernel/pci.c b/src/kernel/pci.c
index 5d8170d..28ca6c6 100644
--- a/src/kernel/pci.c
+++ b/src/kernel/pci.c
@@ -10,7 +10,7 @@ enum {
};
uint16_t n_pci_devices = 0;
-struct pci_device *pci_device_pages[256];
+static struct pci_device *pci_device_pages[256];
#define PCI_DEVICES_PER_PAGE (4096 / sizeof(struct pci_device))
@@ -29,20 +29,21 @@ struct pci_device *find_pci_device_from_class_and_subclass(uint8_t class, uint8_
return 0;
}
-struct pci_device *next_pci_device() {
+static struct pci_device *next_pci_device() {
if (!(n_pci_devices % PCI_DEVICES_PER_PAGE))
- pci_device_pages[n_pci_devices / PCI_DEVICES_PER_PAGE] = allocate_pages(1);
+ if (!(pci_device_pages[n_pci_devices / PCI_DEVICES_PER_PAGE] = allocate_pages(1)))
+ panic("Out of memory in PCI enumeration");
return nth_pci_device(n_pci_devices++);
}
-static inline uint32_t pci_read_config(uint16_t number, uint8_t reg) {
+static uint32_t pci_read_config(uint16_t number, uint8_t reg) {
uint32_t cspace_addr = 0x80000000 | (number << 8) | (reg << 2);
outd(PCP_SELECT, cspace_addr);
return ind(PCP_READ);
}
-void pci_device_check(uint16_t number) {
+static void pci_device_check(uint16_t number) {
uint32_t id = pci_read_config(number, 0);
if ((id & 0xffff) == 0xffff)
return;
diff --git a/src/kernel/serial.c b/src/kernel/serial.c
index c92f173..9ca8315 100644
--- a/src/kernel/serial.c
+++ b/src/kernel/serial.c
@@ -48,54 +48,47 @@ enum {
CLS_READ = 0x01
};
-bool error;
-#define SERIAL_SPIN_LIMIT 65535
+static const uint16_t ports[] = {
+ CP_1, CP_2, CP_3, CP_4
+};
+
+static bool error[] = {
+ false, false, false, false
+};
-bool serr() {
- return error;
+void reset_error(enum serial_port n) {
+ error[n] = false;
}
void init_serial() {
- error = false;
- outb(CP_1 | CP_INT, 0);
- outb(CP_1 | CP_LINE, CL_BAUD);
- outb(CP_1 | CP_DIVLOW, 0x03);//38400
- outb(CP_1 | CP_DIVHIGH, 0x00);//baud
- outb(CP_1 | CP_LINE, CL_8BIT);
- outb(CP_1 | CP_FIFO, 0xc7);//?
+ for (enum serial_port i = COM1; i <= COM4; ++i) {
+ outb(ports[i] | CP_INT, 0);
+ outb(ports[i] | CP_LINE, CL_BAUD);
+ outb(ports[i] | CP_DIVLOW, 0x03);//38400
+ outb(ports[i] | CP_DIVHIGH, 0x00);//baud
+ outb(ports[i] | CP_LINE, CL_8BIT);
+ outb(ports[i] | CP_FIFO, 0xc7);//?
+ }
}
-void sout(char b) {
- if (error)
+typedef uint16_t serial_spin_t;
+
+void sout(enum serial_port n, uint8_t b) {
+ if (error[n])
return;
- uint16_t s = SERIAL_SPIN_LIMIT;
- while (!(inb(CP_1 | CP_LINE_S) & CLS_WRITE))
- if (!--s) {
- error = true;
+ serial_spin_t spinner = -1;
+ while (!(inb(ports[n] | CP_LINE_S) & CLS_WRITE))
+ if (--spinner) {
+ error[n] = true;
return;
}
- outb(CP_1 | CP_DATA, (uint8_t)b);
-}
-
-void soutsz(const char *s) {
- while (*s)
- sout(*(s++));
-}
-
-void soutsn(const char *s, uint8_t n) {
- while (n--)
- sout(*(s++));
+ outb(ports[n] | CP_DATA, b);
}
-char sin() {
- if (error)
+uint8_t sin(enum serial_port n) {
+ if (error[n])
return 0;
- while (!(inb(CP_1 | CP_LINE_S) & CLS_READ))
+ while (!(inb(ports[n] | CP_LINE_S) & CLS_READ))
;//spin
- return (char)inb(CP_1 | CP_DATA);
-}
-
-void sinsn(char *s, uint8_t n) {
- while (n--)
- *(s++) = sin();
+ return inb(ports[n] | CP_DATA);
} \ No newline at end of file
diff --git a/src/kernel/serial.h b/src/kernel/serial.h
index 2fb21a6..2ac359d 100644
--- a/src/kernel/serial.h
+++ b/src/kernel/serial.h
@@ -1,15 +1,19 @@
#ifndef SERIAL_H
#define SERIAL_H
-#include <stdbool.h>
#include <stdint.h>
-bool serr() __attribute__ ((pure));
+enum serial_port {
+ COM1,
+ COM2,
+ COM3,
+ COM4
+};
+
+void reset_error(enum serial_port n);
void init_serial();
-void sout(char b);
-void soutsz(const char *s);
-void soutsn(const char *s, uint8_t n);
-char sin();
-void sinsn(char *s, uint8_t n);
+
+void sout(enum serial_port n, uint8_t b);
+uint8_t sin(enum serial_port n);
#endif \ No newline at end of file
diff --git a/src/kernel/vesa.c b/src/kernel/vesa.c
deleted file mode 100644
index 4cdabb2..0000000
--- a/src/kernel/vesa.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#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)
-// }
-} \ No newline at end of file
diff --git a/src/kernel/vesa.h b/src/kernel/vesa.h
deleted file mode 100644
index b2f17c8..0000000
--- a/src/kernel/vesa.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef VESA_H
-#define VESA_H
-
-#include <stdint.h>
-
-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();
-
-#endif \ No newline at end of file
diff --git a/src/kernel/vga.c b/src/kernel/vga.c
index e103732..7506416 100644
--- a/src/kernel/vga.c
+++ b/src/kernel/vga.c
@@ -1,61 +1,41 @@
#include <stdbool.h>
#include <stdint.h>
-#define VGA_COM_MIRROR
-
-#ifdef VGA_COM_MIRROR
-#include "serial.h"
-#endif
-
#define VGA_COLUMNS 80
#define VGA_LINES 25
#define VGA_START (uint16_t *)0x000b8000
#define VGA_END (VGA_START + VGA_COLUMNS * VGA_LINES)
-uint16_t *cursor = VGA_START;
-uint16_t color = 0x1f00;
+static uint16_t *cursor = VGA_START;
+static uint16_t mask;
void vga_set_color(uint8_t new_color) {
- color = new_color << 8;
+ mask = new_color << 8;
}
void vga_scroll() {
- cursor = VGA_START;
+ for (uint32_t *i = (uint32_t *)VGA_START; i < (uint32_t *)(VGA_END - VGA_COLUMNS); ++i)
+ *i = *(i + VGA_COLUMNS / 2);
+ uint32_t f = (mask | (uint8_t)' ') * 0x00010001;
+ for (uint32_t *i = (uint32_t *)(VGA_END - VGA_COLUMNS); i < (uint32_t *)VGA_END; ++i)
+ *i++ = f;
+ cursor -= VGA_COLUMNS;
}
void vga_blank() {
-#ifdef VGA_COM_MIRROR
- soutsz("\r\n\r\n<CLEAR>\r\n\r\n");
-#endif
- uint32_t f = (color << 16) | color | 0x00200020;
+ uint32_t f = (mask | (uint8_t)' ') * 0x00010001;
uint32_t *p = (uint32_t *)VGA_START;
while (p < (uint32_t *)VGA_END)
- *(p++) = f;
+ *p++ = f;
cursor = VGA_START;
}
void vga_printch(char ch) {
if (ch == '\n') {
-#ifdef VGA_COM_MIRROR
- soutsz("\r\n");
-#endif
if ((cursor = cursor - (cursor - VGA_START) % VGA_COLUMNS + VGA_COLUMNS) == VGA_END)
vga_scroll();
return;
}
-#ifdef VGA_COM_MIRROR
- sout(ch);
-#endif
- *(cursor++) = color | (uint8_t)ch;
+ *cursor++ = mask | (uint8_t)ch;
if (cursor == VGA_END)
vga_scroll();
-}
-
-void vga_printsz(const char *sz) {
- while (*sz)
- vga_printch(*(sz++));
-}
-
-void vga_printsn(const char *sn, uint8_t n) {
- while (n--)
- vga_printch(*(sn++));
} \ No newline at end of file
diff --git a/src/kernel/vga.h b/src/kernel/vga.h
index e88ddfe..703080f 100644
--- a/src/kernel/vga.h
+++ b/src/kernel/vga.h
@@ -7,7 +7,5 @@ void vga_set_color(uint8_t color);
void vga_blank();
void vga_scroll();
void vga_printch(char ch);
-void vga_printsz(const char *sz);
-void vga_printsn(const char *sn, uint8_t n);
#endif \ No newline at end of file