summaryrefslogtreecommitdiff
path: root/stage3
diff options
context:
space:
mode:
authorLizzy Fleckenstein <lizzy@vlhl.dev>2023-12-15 16:10:22 +0100
committerLizzy Fleckenstein <lizzy@vlhl.dev>2023-12-15 16:11:38 +0100
commit2298d17186cb0e58a96d285384de431902da9b1e (patch)
tree635d642931d9f55e701639ee3b3707e0e28a805e /stage3
parent8a25a2935a60e65fcb3e2b715bada858f5fcd6a2 (diff)
downloadcuddles-2298d17186cb0e58a96d285384de431902da9b1e.tar.xz
big chungus
* fix a heap corruption bug * add qemu support * add an ATA driver * add an USTAR read-only file system * boot from disk instead of floppy * font rendering * image rendering * PCI enumeration * init script
Diffstat (limited to 'stage3')
-rw-r--r--stage3/anna.c21
-rw-r--r--stage3/anna.h6
-rw-r--r--stage3/ata.c158
-rw-r--r--stage3/ata.h12
-rw-r--r--stage3/font.c79
-rw-r--r--stage3/font.h10
-rw-r--r--stage3/font_classic.c (renamed from stage3/letters.c)151
-rw-r--r--stage3/font_classic.h15
-rw-r--r--stage3/fs.c31
-rw-r--r--stage3/fs.h13
-rw-r--r--stage3/gfx.c16
-rw-r--r--stage3/gfx.h3
-rw-r--r--stage3/heap.c2
-rw-r--r--stage3/interrupts.c14
-rw-r--r--stage3/letters.h17
-rw-r--r--stage3/main.c172
-rw-r--r--stage3/pci.c40
-rw-r--r--stage3/pci.h6
-rw-r--r--stage3/string.c56
-rw-r--r--stage3/string.h12
20 files changed, 666 insertions, 168 deletions
diff --git a/stage3/anna.c b/stage3/anna.c
deleted file mode 100644
index d590ee7..0000000
--- a/stage3/anna.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "font.h"
-
-void uwu()
-{
- print(
- " -------- -------- " "\n"
- " --/ \\ / \\--" "\n"
- " / \\/ \\" "\n"
- "/ \\" "\n"
- "| |" "\n"
- "| anna |" "\n"
- "\\ /" "\n"
- " \\ /" "\n"
- " \\ /" "\n"
- " \\ /" "\n"
- " \\ /" "\n"
- " \\ /" "\n"
- " \\ /" "\n"
- " \\ /" "\n"
- " \\/" "\n");
-}
diff --git a/stage3/anna.h b/stage3/anna.h
deleted file mode 100644
index 42bb664..0000000
--- a/stage3/anna.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef ANNA_H
-#define ANNA_H
-
-void uwu();
-
-#endif
diff --git a/stage3/ata.c b/stage3/ata.c
new file mode 100644
index 0000000..ccfd695
--- /dev/null
+++ b/stage3/ata.c
@@ -0,0 +1,158 @@
+#include "ata.h"
+#include "halt.h"
+#include "heap.h"
+#include "io.h"
+#include "font.h"
+
+#define ATA_IO_DATA 0
+#define ATA_IO_ERR 1
+#define ATA_IO_FEATURES 1
+#define ATA_IO_SECTORS 2
+#define ATA_IO_LBA_LOW 3
+#define ATA_IO_LBA_MID 4
+#define ATA_IO_LBA_HIGH 5
+#define ATA_IO_HEAD 6
+#define ATA_IO_STATUS 7
+#define ATA_IO_COMMAND 7
+
+#define IO_ATA0_DATA 0x1F0
+#define IO_ATA0_CTRL 0x3F6
+
+#define ATA_CMD_IDENTIFY 0xEC
+#define ATA_CMD_READ_SECTORS_EXT 0x24
+
+typedef struct __attribute__((packed)) {
+ bool err : 1;
+ bool idx : 1;
+ bool corr : 1; // corrected data
+ bool drq : 1; // has data or ready to accept data
+ bool srv : 1; // overlapped
+ bool df : 1; // drive fault
+ bool rdy : 1; // clear if spun down or error
+ bool bsy : 1; // preparing/busy
+} ata_status;
+
+typedef struct {
+ unsigned int bits : 4;
+ bool doll : 1;
+ bool one0 : 1;
+ bool lba : 1;
+ bool one1 : 1;
+} __attribute__((packed)) ata_head;
+
+void ata_recv(u16 *buffer)
+{
+ for (;;) {
+ ata_status status = BITCAST(inb(IO_ATA0_DATA + ATA_IO_STATUS), u8, ata_status);
+
+ if (status.err) {
+ u8 err = inb(IO_ATA0_DATA + ATA_IO_ERR);
+
+ const char *errors[] = {
+ "address mark not found\n",
+ "track zero not found\n",
+ "aborted command\n",
+ "media change request\n",
+ "id not found\n",
+ "media changed\n",
+ "uncorrectable data error\n",
+ "bad block detected\n",
+ };
+
+ for (int i = 0; i < 8; i++)
+ if (err & (1 << i))
+ print(errors[i]);
+
+ panic("ata0-witch error\n");
+ } else if (status.drq)
+ break;
+ }
+
+ for (int i = 0; i < 256; i++)
+ buffer[i] = inw(IO_ATA0_DATA + ATA_IO_DATA);
+}
+
+void ata_delay()
+{
+ for (int i = 0; i < 15; i++)
+ inb(IO_ATA0_DATA + ATA_IO_STATUS);
+}
+
+void ata_init()
+{
+ u8 floating = inb(IO_ATA0_DATA + ATA_IO_STATUS);
+ if (floating == 0xFF)
+ panic("ata0 floating\n");
+
+ outb(IO_ATA0_DATA + ATA_IO_HEAD, BITCAST(((ata_head) {
+ .bits = 0,
+ .doll = false,
+ .one0 = true,
+ .lba = false,
+ .one1 = true,
+ }), ata_head, u8));
+ ata_delay();
+ outb(IO_ATA0_DATA + ATA_IO_LBA_LOW, 0);
+ outb(IO_ATA0_DATA + ATA_IO_LBA_MID, 0);
+ outb(IO_ATA0_DATA + ATA_IO_LBA_HIGH, 0);
+ outb(IO_ATA0_DATA + ATA_IO_COMMAND, ATA_CMD_IDENTIFY);
+
+ u8 status_byte = inb(IO_ATA0_DATA + ATA_IO_STATUS);
+ if (status_byte == 0)
+ panic("no ata0-witch drive\n");
+
+ while (BITCAST(status_byte, u8, ata_status).bsy)
+ status_byte = inb(IO_ATA0_DATA + ATA_IO_STATUS);
+
+ if (inb(IO_ATA0_DATA + ATA_IO_LBA_MID) != 0 || inb(IO_ATA0_DATA + ATA_IO_LBA_HIGH) != 0)
+ panic("ata0-witch is not ATA\n");
+
+ u16 *idvec = malloc(256 * sizeof *idvec);
+ ata_recv(idvec);
+
+ if (!(idvec[83] & (1 << 10)))
+ panic("ata0-witch does not support LBA48 mode\n");
+
+ // u64 lba48_sectors = *(u64 *) &idvec[100];
+ // print_num(lba48_sectors, 10, 0); print("\n");
+
+ free(idvec);
+}
+
+void ata_read(u64 lba, u16 sectors, void *buffer)
+{
+ outb(IO_ATA0_DATA + ATA_IO_HEAD, BITCAST(((ata_head) {
+ .bits = 0,
+ .doll = false,
+ .one0 = true,
+ .lba = true,
+ .one1 = true,
+ }), ata_head, u8));
+ ata_delay();
+ outb(IO_ATA0_DATA + ATA_IO_SECTORS, sectors >> 8);
+ outb(IO_ATA0_DATA + ATA_IO_LBA_LOW, (lba >> 24) & 0xff);
+ outb(IO_ATA0_DATA + ATA_IO_LBA_MID, (lba >> 32) & 0xff);
+ outb(IO_ATA0_DATA + ATA_IO_LBA_HIGH, (lba >> 40) & 0xff);
+ outb(IO_ATA0_DATA + ATA_IO_SECTORS, sectors & 0xff);
+ outb(IO_ATA0_DATA + ATA_IO_LBA_LOW, lba & 0xff);
+ outb(IO_ATA0_DATA + ATA_IO_LBA_MID, (lba >> 8) & 0xff);
+ outb(IO_ATA0_DATA + ATA_IO_LBA_HIGH, (lba >> 16) & 0xff);
+ outb(IO_ATA0_DATA + ATA_IO_COMMAND, ATA_CMD_READ_SECTORS_EXT);
+
+ for (u16 i = 0; i < sectors; i++)
+ ata_recv(buffer + i*512);
+}
+
+void *ata_read_full(u64 lba, u64 sectors)
+{
+ void *buffer = malloc(512 * sectors);
+
+ for (u64 off = 0; off < sectors; off += 0x10000) {
+ u64 sects = sectors - off;
+ if (sects >= 0x10000)
+ sects = 0;
+ ata_read(lba + off, (u16) sects, buffer + off * 512);
+ }
+
+ return buffer;
+}
diff --git a/stage3/ata.h b/stage3/ata.h
new file mode 100644
index 0000000..56743e8
--- /dev/null
+++ b/stage3/ata.h
@@ -0,0 +1,12 @@
+#ifndef ATA_H
+#define ATA_H
+
+#include "def.h"
+
+void ata_recv(u16 *buffer);
+void ata_delay();
+void ata_init();
+void ata_read(u64 lba, u16 sectors, void *buffer);
+void *ata_read_full(u64 lba, u64 sectors);
+
+#endif
diff --git a/stage3/font.c b/stage3/font.c
index 291cdb1..9e315e6 100644
--- a/stage3/font.c
+++ b/stage3/font.c
@@ -1,10 +1,17 @@
#include "font.h"
-#include "letters.h"
+#include "font_classic.h"
#include "gfx.h"
+#include "heap.h"
+#include "memory.h"
// important: must be a multiple of 2, else code won't work
#define TAB_SIZE 4
+#define CHAR_WIDTH 8
+#define CHAR_HEIGHT 16
+
+static u8 *font; // u8[256][16]
+
static u16 font_size;
static u16 outer_width, outer_height;
@@ -12,17 +19,55 @@ static u16 cursor_x, cursor_y;
static u16 screen_width, screen_height;
-void set_font_size(u16 size)
+void font_init()
+{
+ font = malloc(256 * 16);
+}
+
+void font_set_size(u16 size)
{
font_size = size;
- outer_width = (LETTER_WIDTH + 2) * font_size;
- outer_height = (LETTER_HEIGHT + 2) * font_size;
+ outer_width = CHAR_WIDTH * font_size;
+ outer_height = CHAR_HEIGHT * font_size;
screen_width = gfx_info->width / outer_width;
screen_height = gfx_info->height / outer_height;
}
+void font_load_blob(const void *blob)
+{
+ memcpy(font, blob, 256*16);
+}
+
+void font_load_classic()
+{
+ memset(font, 0, 256 * 16);
+
+ classic_char *cfont = font_classic();
+
+ int scale = 2;
+ int xpad = (CHAR_WIDTH - CLASSIC_CHAR_WIDTH * scale) / 2;
+ int ypad = (CHAR_HEIGHT - CLASSIC_CHAR_HEIGHT * scale) / 2;
+
+ for (int i = 0; i < 255; i++)
+ for (int xc = 0; xc < CLASSIC_CHAR_WIDTH; xc++)
+ for (int yc = 0; yc < CLASSIC_CHAR_HEIGHT; yc++) {
+ if (!cfont[i].data[yc * CLASSIC_CHAR_WIDTH + xc])
+ continue;
+
+ for (int xf = 0; xf < scale; xf++)
+ for (int yf = 0; yf < scale; yf++) {
+ int x = xc * scale + xpad + xf;
+ int y = yc * scale + ypad + yf;
+
+ font[i * CHAR_HEIGHT + y] |= (1 << x);
+ }
+ }
+
+ free(cfont);
+}
+
static void render_char(u8 c)
{
u16 base_x = cursor_x * outer_width;
@@ -30,14 +75,14 @@ static void render_char(u8 c)
gfx_set_area(base_x, base_y, outer_width, outer_height, 0xFF000000);
- for (u16 x = 0; x < LETTER_WIDTH; x++)
- for (u16 y = 0; y < LETTER_HEIGHT; y++) {
- if (!letters[c].data[y * LETTER_WIDTH + x])
+ for (u16 x = 0; x < CHAR_WIDTH; x++)
+ for (u16 y = 0; y < CHAR_HEIGHT; y++) {
+ if (!(font[c * CHAR_HEIGHT + y] & (1 << x)))
continue;
gfx_set_area(
- base_x + (x + 1) * font_size,
- base_y + (y + 1) * font_size,
+ base_x + x * font_size,
+ base_y + y * font_size,
font_size, font_size, 0xFFFFFFFF);
}
}
@@ -103,8 +148,13 @@ void print(const char *line)
print_char(*line++);
}
+void printn(const char *line, usize len)
+{
+ for (usize i = 0; i < len; i++)
+ print_char(*line++);
+}
-void print_num(u64 x, u8 base, u8 pad)
+void print_padded(u64 x, u8 base, u8 pad_len, char pad_char)
{
char digit[65];
char *ptr = &digit[64];
@@ -116,8 +166,13 @@ void print_num(u64 x, u8 base, u8 pad)
x /= base;
} while (x != 0);
- while (ptr > digit + 64 - pad)
- *--ptr = ' ';
+ while (ptr > digit + 64 - pad_len)
+ *--ptr = pad_char;
print(ptr);
}
+
+void print_num(u64 x, u8 base, u8 pad)
+{
+ print_padded(x, base, pad, ' ');
+}
diff --git a/stage3/font.h b/stage3/font.h
index 009d1de..ec99118 100644
--- a/stage3/font.h
+++ b/stage3/font.h
@@ -3,9 +3,15 @@
#include "def.h"
+void font_init();
+void font_set_size(u16 size);
+void font_load_blob(const void *blob);
+void font_load_classic();
+
void print(const char *line);
-void set_font_size(u16 size);
+void printn(const char *line, usize len);
void print_char(char c);
-void print_num(u64 x, u8 base, u8 pad);
+void print_num(u64 x, u8 base, u8 pad_len);
+void print_padded(u64 x, u8 base, u8 pad_len, char pad_char);
#endif
diff --git a/stage3/letters.c b/stage3/font_classic.c
index 43f78fb..4346f16 100644
--- a/stage3/letters.c
+++ b/stage3/font_classic.c
@@ -1,490 +1,495 @@
-#include "letters.h"
+#include "font_classic.h"
+#include "heap.h"
+#include "memory.h"
-Letter letters[256];
-
-void letters_init()
+classic_char *font_classic()
{
- letters[' '] = (Letter) {{
+ classic_char *font = malloc(256 * sizeof *font);
+ memset(font, 0, 256 * sizeof *font);
+
+ font[' '] = (classic_char) {{
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0
}};
- letters['!'] = (Letter) {{
+ font['!'] = (classic_char) {{
0, 1, 0,
0, 1, 0,
0, 1, 0,
0, 0, 0,
0, 1, 0
}};
- letters['\"'] = (Letter) {{
+ font['\"'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
0, 0, 0,
0, 0, 0,
0, 0, 0
}};
- letters['#'] = (Letter) {{
+ font['#'] = (classic_char) {{
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 0, 1
}};
- letters['$'] = (Letter) {{
+ font['$'] = (classic_char) {{
0, 1, 0,
1, 1, 1,
0, 1, 0,
1, 1, 1,
0, 1, 0
}};
- letters['%'] = (Letter) {{
+ font['%'] = (classic_char) {{
1, 0, 1,
0, 0, 1,
0, 1, 0,
1, 0, 0,
1, 0, 1
}};
- letters['&'] = (Letter) {{
+ font['&'] = (classic_char) {{
1, 1, 0,
1, 0, 0,
1, 1, 1,
1, 0, 1,
1, 1, 1
}};
- letters['\''] = (Letter) {{
+ font['\''] = (classic_char) {{
0, 1, 0,
0, 1, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0
}};
- letters['('] = (Letter) {{
+ font['('] = (classic_char) {{
0, 1, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
0, 1, 0
}};
- letters[')'] = (Letter) {{
+ font[')'] = (classic_char) {{
0, 1, 0,
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 1, 0
}};
- letters['*'] = (Letter) {{
+ font['*'] = (classic_char) {{
1, 0, 1,
0, 1, 0,
1, 0, 1,
0, 0, 0,
0, 0, 0
}};
- letters['+'] = (Letter) {{
+ font['+'] = (classic_char) {{
0, 0, 0,
0, 1, 0,
1, 1, 1,
0, 1, 0,
0, 0, 0
}};
- letters[','] = (Letter) {{
+ font[','] = (classic_char) {{
0, 0, 0,
0, 0, 0,
0, 1, 0,
0, 1, 0,
1, 0, 0
}};
- letters['-'] = (Letter) {{
+ font['-'] = (classic_char) {{
0, 0, 0,
0, 0, 0,
1, 1, 1,
0, 0, 0,
0, 0, 0
}};
- letters['.'] = (Letter) {{
+ font['.'] = (classic_char) {{
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 1, 0
}};
- letters['/'] = (Letter) {{
+ font['/'] = (classic_char) {{
0, 0, 1,
0, 0, 1,
0, 1, 0,
1, 0, 0,
1, 0, 0
}};
- letters['0'] = (Letter) {{
+ font['0'] = (classic_char) {{
0, 1, 0,
1, 0, 1,
1, 0, 1,
1, 0, 1,
0, 1, 0
}};
- letters['1'] = (Letter) {{
+ font['1'] = (classic_char) {{
0, 0, 1,
0, 1, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1
}};
- letters['2'] = (Letter) {{
+ font['2'] = (classic_char) {{
1, 1, 1,
1, 0, 1,
0, 1, 0,
1, 0, 0,
1, 1, 1
}};
- letters['3'] = (Letter) {{
+ font['3'] = (classic_char) {{
1, 1, 1,
0, 0, 1,
0, 1, 1,
0, 0, 1,
1, 1, 1
}};
- letters['4'] = (Letter) {{
+ font['4'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
1, 1, 1,
0, 0, 1,
0, 0, 1
}};
- letters['5'] = (Letter) {{
+ font['5'] = (classic_char) {{
1, 1, 1,
1, 0, 0,
1, 1, 1,
0, 0, 1,
1, 1, 0
}};
- letters['6'] = (Letter) {{
+ font['6'] = (classic_char) {{
1, 1, 1,
1, 0, 0,
1, 1, 1,
1, 0, 1,
1, 1, 1
}};
- letters['7'] = (Letter) {{
+ font['7'] = (classic_char) {{
1, 1, 1,
0, 0, 1,
0, 1, 0,
1, 0, 0,
1, 0, 0
}};
- letters['8'] = (Letter) {{
+ font['8'] = (classic_char) {{
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 1, 1
}};
- letters['9'] = (Letter) {{
+ font['9'] = (classic_char) {{
1, 1, 1,
1, 0, 1,
1, 1, 1,
0, 0, 1,
1, 1, 1
}};
- letters[':'] = (Letter) {{
+ font[':'] = (classic_char) {{
0, 0, 0,
0, 1, 0,
0, 0, 0,
0, 1, 0,
0, 0, 0
}};
- letters[';'] = (Letter) {{
+ font[';'] = (classic_char) {{
0, 1, 0,
0, 0, 0,
0, 1, 0,
0, 1, 0,
1, 0, 0
}};
- letters['<'] = (Letter) {{
+ font['<'] = (classic_char) {{
0, 0, 0,
0, 1, 0,
1, 0, 0,
0, 1, 0,
0, 0, 0
}};
- letters['='] = (Letter) {{
+ font['='] = (classic_char) {{
0, 0, 0,
1, 1, 1,
0, 0, 0,
1, 1, 1,
0, 0, 0
}};
- letters['>'] = (Letter) {{
+ font['>'] = (classic_char) {{
0, 0, 0,
0, 1, 0,
0, 0, 1,
0, 1, 0,
0, 0, 0
}};
- letters['?'] = (Letter) {{
+ font['?'] = (classic_char) {{
1, 1, 1,
0, 0, 1,
0, 1, 0,
0, 0, 0,
0, 1, 0
}};
- letters['@'] = (Letter) {{
+ font['@'] = (classic_char) {{
0, 0, 0,
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 1, 1
}};
- letters['['] = (Letter) {{
+ font['['] = (classic_char) {{
1, 1, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 1, 0
}};
- letters[']'] = (Letter) {{
+ font[']'] = (classic_char) {{
0, 1, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 1, 1
}};
- letters['\\'] = (Letter) {{
+ font['\\'] = (classic_char) {{
1, 0, 0,
1, 0, 0,
0, 1, 0,
0, 0, 1,
0, 0, 1
}};
- letters['^'] = (Letter) {{
+ font['^'] = (classic_char) {{
0, 1, 0,
1, 0, 1,
0, 0, 0,
0, 0, 0,
0, 0, 0
}};
- letters['_'] = (Letter) {{
+ font['_'] = (classic_char) {{
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
1, 1, 1
}};
- letters['`'] = (Letter) {{
+ font['`'] = (classic_char) {{
0, 1, 0,
0, 0, 1,
0, 0, 0,
0, 0, 0,
0, 0, 0
}};
- letters['~'] = (Letter) {{
+ font['~'] = (classic_char) {{
0, 0, 0,
0, 0, 1,
1, 1, 1,
1, 0, 0,
0, 0, 0
}};
- letters['{'] = (Letter) {{
+ font['{'] = (classic_char) {{
0, 1, 1,
0, 1, 0,
1, 1, 0,
0, 1, 0,
0, 1, 1
}};
- letters['}'] = (Letter) {{
+ font['}'] = (classic_char) {{
1, 1, 0,
0, 1, 0,
0, 1, 1,
0, 1, 0,
1, 1, 0
}};
- letters['|'] = (Letter) {{
+ font['|'] = (classic_char) {{
0, 1, 0,
0, 1, 0,
0, 1, 0,
0, 1, 0,
0, 1, 0
}};
- letters['A'] = letters['a'] = (Letter) {{
+ font['A'] = font['a'] = (classic_char) {{
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 0, 1
}};
- letters['B'] = letters['b'] = (Letter) {{
+ font['B'] = font['b'] = (classic_char) {{
1, 1, 0,
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 1, 0
}};
- letters['C'] = letters['c'] = (Letter) {{
+ font['C'] = font['c'] = (classic_char) {{
1, 1, 1,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 1, 1
}};
- letters['D'] = letters['d'] = (Letter) {{
+ font['D'] = font['d'] = (classic_char) {{
1, 1, 0,
1, 0, 1,
1, 0, 1,
1, 0, 1,
1, 1, 0
}};
- letters['E'] = letters['e'] = (Letter) {{
+ font['E'] = font['e'] = (classic_char) {{
1, 1, 1,
1, 0, 0,
1, 1, 1,
1, 0, 0,
1, 1, 1
}};
- letters['F'] = letters['f'] = (Letter) {{
+ font['F'] = font['f'] = (classic_char) {{
1, 1, 1,
1, 0, 0,
1, 1, 1,
1, 0, 0,
1, 0, 0
}};
- letters['G'] = letters['g'] = (Letter) {{
+ font['G'] = font['g'] = (classic_char) {{
1, 1, 1,
1, 0, 0,
1, 0, 1,
1, 0, 1,
1, 1, 1
}};
- letters['H'] = letters['h'] = (Letter) {{
+ font['H'] = font['h'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 0, 1
}};
- letters['I'] = letters['i'] = (Letter) {{
+ font['I'] = font['i'] = (classic_char) {{
1, 1, 1,
0, 1, 0,
0, 1, 0,
0, 1, 0,
1, 1, 1
}};
- letters['J'] = letters['j'] = (Letter) {{
+ font['J'] = font['j'] = (classic_char) {{
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1,
1, 1, 1
}};
- letters['K'] = letters['k'] = (Letter) {{
+ font['K'] = font['k'] = (classic_char) {{
1, 0, 1,
1, 1, 0,
1, 0, 0,
1, 1, 0,
1, 0, 1,
}};
- letters['L'] = letters['l'] = (Letter) {{
+ font['L'] = font['l'] = (classic_char) {{
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 1, 1
}};
- letters['M'] = letters['m'] = (Letter) {{
+ font['M'] = font['m'] = (classic_char) {{
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 0, 1,
1, 0, 1
}};
- letters['N'] = letters['n'] = (Letter) {{
+ font['N'] = font['n'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
1, 1, 1,
1, 1, 1,
1, 0, 1
}};
- letters['O'] = letters['o'] = (Letter) {{
+ font['O'] = font['o'] = (classic_char) {{
1, 1, 1,
1, 0, 1,
1, 0, 1,
1, 0, 1,
1, 1, 1
}};
- letters['P'] = letters['p'] = (Letter) {{
+ font['P'] = font['p'] = (classic_char) {{
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 0, 0,
1, 0, 0
}};
- letters['Q'] = letters['q'] = (Letter) {{
+ font['Q'] = font['q'] = (classic_char) {{
1, 1, 1,
1, 0, 1,
1, 0, 1,
1, 1, 1,
0, 0, 1
}};
- letters['R'] = letters['r'] = (Letter) {{
+ font['R'] = font['r'] = (classic_char) {{
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 1, 0,
1, 0, 1
}};
- letters['S'] = letters['s'] = (Letter) {{
+ font['S'] = font['s'] = (classic_char) {{
1, 1, 1,
1, 0, 0,
1, 1, 1,
0, 0, 1,
1, 1, 1
}};
- letters['T'] = letters['t'] = (Letter) {{
+ font['T'] = font['t'] = (classic_char) {{
1, 1, 1,
0, 1, 0,
0, 1, 0,
0, 1, 0,
0, 1, 0
}};
- letters['U'] = letters['u'] = (Letter) {{
+ font['U'] = font['u'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
1, 0, 1,
1, 0, 1,
1, 1, 1
}};
- letters['V'] = letters['v'] = (Letter) {{
+ font['V'] = font['v'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
1, 0, 1,
1, 0, 1,
0, 1, 0
}};
- letters['W'] = letters['w'] = (Letter) {{
+ font['W'] = font['w'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
1, 0, 1,
1, 1, 1,
1, 0, 1
}};
- letters['X'] = letters['x'] = (Letter) {{
+ font['X'] = font['x'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
0, 1, 0,
1, 0, 1,
1, 0, 1
}};
- letters['Y'] = letters['y'] = (Letter) {{
+ font['Y'] = font['y'] = (classic_char) {{
1, 0, 1,
1, 0, 1,
1, 1, 1,
0, 1, 0,
0, 1, 0
}};
- letters['Z'] = letters['z'] = (Letter) {{
+ font['Z'] = font['z'] = (classic_char) {{
1, 1, 1,
0, 0, 1,
0, 1, 0,
1, 0, 0,
1, 1, 1
}};
+
+ return font;
}
diff --git a/stage3/font_classic.h b/stage3/font_classic.h
new file mode 100644
index 0000000..cc80873
--- /dev/null
+++ b/stage3/font_classic.h
@@ -0,0 +1,15 @@
+#ifndef FONT_CLASSIC_H
+#define FONT_CLASSIC_H
+
+#include "def.h"
+
+#define CLASSIC_CHAR_WIDTH 3
+#define CLASSIC_CHAR_HEIGHT 5
+
+typedef struct __attribute__((packed)) {
+ u8 data[CLASSIC_CHAR_WIDTH * CLASSIC_CHAR_HEIGHT];
+} classic_char;
+
+classic_char *font_classic();
+
+#endif
diff --git a/stage3/fs.c b/stage3/fs.c
new file mode 100644
index 0000000..9f7ea51
--- /dev/null
+++ b/stage3/fs.c
@@ -0,0 +1,31 @@
+#include "fs.h"
+#include "ata.h"
+#include "string.h"
+#include "memory.h"
+#include "heap.h"
+
+file fs_read(const char *filename)
+{
+ u64 start = (*(u32 *) (0x1000-10-8))/512;
+
+ for (;;) {
+ u8 *info = ata_read_full(start, 1);
+
+ if (memcmp(info+257, "ustar", 5) != 0) {
+ free(info);
+ return (file) { .len = 0, .data = nil };
+ }
+
+ u8 *infop = info+124;
+ usize fsize = parse_num(&infop, 8, 11);
+ usize fsect = (fsize+511)/512;
+
+ if (memcmp(info, filename, strlen(filename) + 1) == 0) {
+ free(info);
+ return (file) { .len = fsize, .data = ata_read_full(start+1, fsect) };
+ } else {
+ free(info);
+ start += 1 + fsect;
+ }
+ }
+}
diff --git a/stage3/fs.h b/stage3/fs.h
new file mode 100644
index 0000000..b585577
--- /dev/null
+++ b/stage3/fs.h
@@ -0,0 +1,13 @@
+#ifndef FS_H
+#define FS_H
+
+#include "def.h"
+
+typedef struct {
+ usize len;
+ void *data;
+} file;
+
+file fs_read(const char *filename);
+
+#endif
diff --git a/stage3/gfx.c b/stage3/gfx.c
index 2afc766..79c76a3 100644
--- a/stage3/gfx.c
+++ b/stage3/gfx.c
@@ -1,4 +1,5 @@
#include "gfx.h"
+#include "memory.h"
struct GfxInfo *gfx_info = (void *) (0x1000-10);
@@ -6,10 +7,10 @@ struct GfxInfo *gfx_info = (void *) (0x1000-10);
u32 make_color(color col)
{
return ((u32) 0)
- & ((u32) col.r << 0)
- & ((u32) col.g << 8)
- & ((u32) col.b << 16)
- & ((u32) col.a << 24);
+ | ((u32) col.b << 0)
+ | ((u32) col.g << 8)
+ | ((u32) col.r << 16)
+ | ((u32) col.a << 24);
}
void gfx_set_pixel(u16 x, u16 y, u32 col)
@@ -30,3 +31,10 @@ void gfx_set_area(u16 x, u16 y, u16 w, u16 h, u32 col)
*((u32 *) rbeg) = col;
}
}
+
+void gfx_draw_img(u16 x, u16 y, u16 w, u16 h, color *img)
+{
+ void *cbeg = (void *) (u64) (gfx_info->framebuffer + y * gfx_info->pitch + x * sizeof(color));
+ for (u16 yi = 0; yi < h; cbeg += gfx_info->pitch, yi++)
+ memcpy(cbeg, img + yi * w, w * sizeof(color));
+}
diff --git a/stage3/gfx.h b/stage3/gfx.h
index 47e98db..6eee074 100644
--- a/stage3/gfx.h
+++ b/stage3/gfx.h
@@ -10,12 +10,13 @@ extern struct __attribute__((packed)) GfxInfo {
u32 framebuffer;
} *gfx_info;
-typedef struct {
+typedef struct __attribute__((packed)) {
u8 r, g, b, a;
} color;
u32 make_color(color col);
void gfx_set_pixel(u16 x, u16 y, u32 col);
void gfx_set_area(u16 x, u16 y, u16 w, u16 h, u32 col);
+void gfx_draw_img(u16 x, u16 y, u16 w, u16 h, color *img);
#endif
diff --git a/stage3/heap.c b/stage3/heap.c
index 2909ba7..dd1b23a 100644
--- a/stage3/heap.c
+++ b/stage3/heap.c
@@ -46,7 +46,7 @@ void *try_malloc(usize size)
prev->next = h->next;
} else {
// split
- h->size -= size;
+ h->size -= size + sizeof(Header);
h = ((void *) h) + sizeof(Header) + h->size;
h->size = size;
}
diff --git a/stage3/interrupts.c b/stage3/interrupts.c
index e7b819e..71f953f 100644
--- a/stage3/interrupts.c
+++ b/stage3/interrupts.c
@@ -102,6 +102,13 @@ void interrupt_handler(interrupt_frame *frame)
}
}
+typedef struct {
+ u16 size;
+ u64 addr;
+} __attribute__((packed)) idt_descriptor;
+
+idt_descriptor idtr;
+
void init_interrupts()
{
typedef struct {
@@ -139,12 +146,7 @@ void init_interrupts()
};
}
- typedef struct {
- u16 size;
- u64 addr;
- } __attribute__((packed)) idt_descriptor;
-
- idt_descriptor idtr = {
+ idtr = (idt_descriptor) {
.size = 256 * sizeof *idt - 1,
.addr = (u64) &idt[0],
};
diff --git a/stage3/letters.h b/stage3/letters.h
deleted file mode 100644
index ffaa6d5..0000000
--- a/stage3/letters.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef LETTERS_H
-#define LETTERS_H
-
-#include "def.h"
-
-#define LETTER_WIDTH 3
-#define LETTER_HEIGHT 5
-
-typedef struct __attribute__((packed)) {
- u8 data[LETTER_HEIGHT * LETTER_WIDTH];
-} Letter;
-
-extern Letter letters[];
-
-void letters_init();
-
-#endif
diff --git a/stage3/main.c b/stage3/main.c
index d3ebe9d..5362984 100644
--- a/stage3/main.c
+++ b/stage3/main.c
@@ -1,20 +1,34 @@
+void kmain();
+
+void init()
+{
+ kmain();
+}
+
#include "def.h"
#include "paging.h"
#include "gfx.h"
#include "halt.h"
#include "heap.h"
#include "font.h"
-#include "letters.h"
#include "interrupts.h"
#include "pic.h"
-#include "anna.h"
-
-void init()
+#include "io.h"
+#include "memory.h"
+#include "ata.h"
+#include "fs.h"
+#include "string.h"
+#include "pci.h"
+
+void eat_whitespace(char **str)
{
- letters_init();
+ while (**str == ' ' || **str == '\t')
+ (*str)++;
+}
+void kmain()
+{
heap_init();
- set_font_size(2);
#define MMAP for (MemRegion *mreg = (void *) 0x500; mreg->start != nil; mreg++)
@@ -42,20 +56,9 @@ void init()
// gfx init
gfx_set_area(0, 0, gfx_info->width, gfx_info->height, 0xFF000000);
- // charset demo
- {
- const u8 max = '~' - '!' + 1;
-
- char str[max + 1];
- str[max] = '\0';
-
- for (u8 i = 0; i < max; i++)
- str[i] = i + '!';
-
- print("charset demo:\n");
- print(str);
- print("\n");
- }
+ font_init();
+ font_set_size(1);
+ font_load_classic();
// memory map
print("memory map:\n");
@@ -70,11 +73,130 @@ void init()
init_interrupts();
pic_init();
+ ata_init();
+
+ file f = fs_read("init");
+ if (f.data == nil)
+ panic("no init script");
+
+ // this is horrible horrible horrible
+ // if you read this i am genuinely sorry
+
+ char *init = malloc(f.len+1);
+ char *init_orig = init;
+ init[f.len] = '\0';
+ memcpy(init, f.data, f.len);
+ free(f.data);
+
+ for (;;) {
+ eat_whitespace(&init);
+
+ if (*init == '\0')
+ break;
+ else if (*init == '\n') {
+ init++;
+ continue;
+ }
+
+ if (strncmp(init, "echo ", strlen("echo ")) == 0) {
+ init += strlen("echo ");
+ usize idx = find_char(init, '\n');
+ printn(init, idx);
+ print("\n");
+ init += idx;
+ } else if (strncmp(init, "cat ", strlen("cat ")) == 0) {
+ init += strlen("cat ");
+ usize idx = find_char(init, '\n');
+
+ char filename[idx+1];
+ filename[idx] = '\0';
+ memcpy(filename, init, idx);
+
+ file f = fs_read(filename);
+ if (f.data == nil) {
+ print("cat: file not found: ");
+ print(filename);
+ print("\n");
+ } else {
+ printn(f.data, f.len);
+ free(f.data);
+ }
+
+ init += idx;
+ } else if (strncmp(init, "font ", strlen("font ")) == 0) {
+ init += strlen("font ");
+ usize idx = find_char(init, '\n');
+
+ char filename[idx+1];
+ filename[idx] = '\0';
+ memcpy(filename, init, idx);
+
+ file f = fs_read(filename);
+ if (f.data == nil) {
+ print("font: file not found: ");
+ print(filename);
+ print("\n");
+ } else {
+ if (f.len == 16*256)
+ font_load_blob(f.data);
+ else
+ print("font: file has wrong size\n");
+ free(f.data);
+ }
+
+ init += idx;
+ } else if (strncmp(init, "img ", strlen("img ")) == 0) {
+ init += strlen("img ");
+ usize idx = find_char(init, '\n');
+
+ char filename[idx+1];
+ filename[idx] = '\0';
+ memcpy(filename, init, idx);
+
+ file f = fs_read(filename);
+ if (f.data == nil) {
+ print("img: file not found: ");
+ print(filename);
+ print("\n");
+ } else {
+ if (f.len < 2 * sizeof(u32))
+ print("img: missing header\n");
+ else {
+ u32 width = ((u32 *) f.data)[0];
+ u32 height = ((u32 *) f.data)[1];
+ if (f.len != 2 * sizeof(u32) + width * height * sizeof(color))
+ panic("img: invalid file size\n");
+ gfx_draw_img(gfx_info->width-width, 0, width, height, f.data + 2 * sizeof(u32));
+ }
+ free(f.data);
+ }
+
+ init += idx;
+ } else if (strncmp(init, "lspci", strlen("lspci")) == 0) {
+ pci_enumerate();
+ init += find_char(init, '\n');
+ } else if (strncmp(init, "charset_demo", strlen("charset_demo")) == 0) {
+ const u8 max = '~' - '!' + 1;
+
+ char str[max + 1];
+ str[max] = '\0';
+
+ for (u8 i = 0; i < max; i++)
+ str[i] = i + '!';
+
+ print("charset demo:\n");
+ print(str);
+ print("\n");
+ init += find_char(init, '\n');
+ } else {
+ print("unknown command: ");
+ usize idx = find_char(init, '\n');
+ printn(init, idx);
+ print("\n");
+ init += idx;
+ }
+ }
- uwu();
-
- // unmask_irq(IRQ_PIT);
- enable_irqs();
-
+ free(init_orig);
halt();
}
diff --git a/stage3/pci.c b/stage3/pci.c
new file mode 100644
index 0000000..164071d
--- /dev/null
+++ b/stage3/pci.c
@@ -0,0 +1,40 @@
+#include "pci.h"
+#include "def.h"
+#include "io.h"
+#include "font.h"
+
+#define PCI_CONFIG_ADDRESS 0xCF8
+#define PCI_CONFIG_DATA 0xCFC
+
+void pci_enumerate()
+{
+ typedef struct __attribute__((packed)) {
+ u8 offset;
+ unsigned int func : 3;
+ unsigned int dev : 5;
+ u8 bus;
+ unsigned int reserved : 7;
+ bool enable : 1;
+ } pci_config_addr;
+
+ for (int bus = 0; bus < 256; bus++)
+ for (int dev = 0; dev < 32; dev++) {
+ pci_config_addr addr = {
+ .offset = 0,
+ .func = 0,
+ .dev = dev,
+ .bus = bus,
+ .enable = true,
+ };
+
+ outl(PCI_CONFIG_ADDRESS, BITCAST(addr, pci_config_addr, u32));
+ u32 x = inl(PCI_CONFIG_DATA);
+ if (x != 0xFFFFFFFF) {
+ print("bus: "); print_num(bus, 16, 2);
+ print(" dev: "); print_num(dev, 16, 1);
+ print(" vendor: "); print_num(x & 0xFFFF, 16, 4);
+ print(" id: "); print_num((x >> 16) & 0xFFFF, 16, 4);
+ print("\n");
+ }
+ }
+}
diff --git a/stage3/pci.h b/stage3/pci.h
new file mode 100644
index 0000000..ac893ee
--- /dev/null
+++ b/stage3/pci.h
@@ -0,0 +1,6 @@
+#ifndef PCI_H
+#define PCI_H
+
+void pci_enumerate();
+
+#endif
diff --git a/stage3/string.c b/stage3/string.c
new file mode 100644
index 0000000..ff4bfc3
--- /dev/null
+++ b/stage3/string.c
@@ -0,0 +1,56 @@
+#include "string.h"
+
+usize find_char(const char *str, char chr)
+{
+ usize ret = 0;
+ while (*str != chr && *str != '\0')
+ str++, ret++;
+ return ret;
+}
+
+u64 parse_num(u8 **str, u8 base, isize size)
+{
+ u64 x = 0;
+
+ while (size-- != 0) {
+ u8 c = **str;
+
+ u64 d;
+ if (c >= '0' && c <= '9')
+ d = c - '0';
+ else if (c >= 'a' && c <= 'z')
+ d = c - 'a';
+ else if (c >= 'A' && c <= 'z')
+ d = c - 'A';
+ else
+ return x;
+
+ if (d >= base)
+ return x;
+
+ (*str)++;
+ x = x * base + d;
+ }
+
+ return x;
+}
+
+usize strlen(const char *str)
+{
+ return find_char(str, '\0');
+}
+
+int strcmp(const char *p1, const char *p2)
+{
+ while (*p1 == *p2 && *p1 != '\0')
+ p1++, p2++;
+ return *p1 - *p2;
+}
+
+int strncmp(const char *p1, const char *p2, usize size)
+{
+ for (usize i = 0; i < size; i++)
+ if (p1[i] != p2[i])
+ return p1[i]-p2[i];
+ return 0;
+}
diff --git a/stage3/string.h b/stage3/string.h
new file mode 100644
index 0000000..2738f60
--- /dev/null
+++ b/stage3/string.h
@@ -0,0 +1,12 @@
+#ifndef STRING_H
+#define STRING_H
+
+#include "def.h"
+
+u64 parse_num(u8 **str, u8 base, isize size);
+usize find_char(const char *str, char chr);
+usize strlen(const char *str);
+int strcmp(const char *p1, const char *p2);
+int strncmp(const char *p1, const char *p2, usize size);
+
+#endif