diff options
| author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2023-12-15 16:10:22 +0100 |
|---|---|---|
| committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2023-12-15 16:11:38 +0100 |
| commit | 2298d17186cb0e58a96d285384de431902da9b1e (patch) | |
| tree | 635d642931d9f55e701639ee3b3707e0e28a805e /stage3 | |
| parent | 8a25a2935a60e65fcb3e2b715bada858f5fcd6a2 (diff) | |
| download | cuddles-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.c | 21 | ||||
| -rw-r--r-- | stage3/anna.h | 6 | ||||
| -rw-r--r-- | stage3/ata.c | 158 | ||||
| -rw-r--r-- | stage3/ata.h | 12 | ||||
| -rw-r--r-- | stage3/font.c | 79 | ||||
| -rw-r--r-- | stage3/font.h | 10 | ||||
| -rw-r--r-- | stage3/font_classic.c (renamed from stage3/letters.c) | 151 | ||||
| -rw-r--r-- | stage3/font_classic.h | 15 | ||||
| -rw-r--r-- | stage3/fs.c | 31 | ||||
| -rw-r--r-- | stage3/fs.h | 13 | ||||
| -rw-r--r-- | stage3/gfx.c | 16 | ||||
| -rw-r--r-- | stage3/gfx.h | 3 | ||||
| -rw-r--r-- | stage3/heap.c | 2 | ||||
| -rw-r--r-- | stage3/interrupts.c | 14 | ||||
| -rw-r--r-- | stage3/letters.h | 17 | ||||
| -rw-r--r-- | stage3/main.c | 172 | ||||
| -rw-r--r-- | stage3/pci.c | 40 | ||||
| -rw-r--r-- | stage3/pci.h | 6 | ||||
| -rw-r--r-- | stage3/string.c | 56 | ||||
| -rw-r--r-- | stage3/string.h | 12 |
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 |
