summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile50
-rw-r--r--bochsrc5
-rw-r--r--fs/blahaj.cuddleimgbin0 -> 262152 bytes
-rw-r--r--fs/blahaj.pngbin0 -> 64603 bytes
-rw-r--r--fs/fonts/Bm437_IBM_VGA_8x16.cuddlefontbin0 -> 4096 bytes
-rw-r--r--fs/fonts/otb/Bm437_IBM_VGA_8x16.otbbin0 -> 10312 bytes
-rw-r--r--fs/fonts/otb/ter-u16b.otbbin0 -> 38828 bytes
-rw-r--r--fs/fonts/otb/ter-u16n.otbbin0 -> 38848 bytes
-rw-r--r--fs/fonts/ter-u16n.cuddlefontbin0 -> 4096 bytes
-rw-r--r--fs/init10
-rw-r--r--fs/uwu.txt15
-rw-r--r--stage1/main.asm6
-rw-r--r--stage3.ld2
-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
-rw-r--r--util/png2cuddleimg/.gitignore1
-rw-r--r--util/png2cuddleimg/Makefile2
-rw-r--r--util/png2cuddleimg/main.c68
-rw-r--r--util/ttf2cuddlefont/.gitignore1
-rw-r--r--util/ttf2cuddlefont/Makefile2
-rw-r--r--util/ttf2cuddlefont/main.c52
40 files changed, 862 insertions, 189 deletions
diff --git a/.gitignore b/.gitignore
index d659ca8..1179c33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
-*.out
+*.bin
*.o
*.img
*.map
bx_enh_dbg.ini
stage3/isr.asm
+fs.tar
diff --git a/Makefile b/Makefile
index fb3b7e2..e02f94c 100644
--- a/Makefile
+++ b/Makefile
@@ -24,22 +24,29 @@ STAGE3 = \
stage3/paging.o \
stage3/heap.o \
stage3/font.o \
- stage3/letters.o \
- stage3/anna.o
+ stage3/font_classic.o \
+ stage3/ata.o \
+ stage3/string.o \
+ stage3/pci.o \
+ stage3/fs.o
-cuddles.img: stage1.out stage2.out stage3.out
- cat stage{1,2,3}.out > cuddles.img
+PAD_BOUNDARY = pad() { truncate -s $$(echo "($$(du -b $$1 | cut -f1)+$$2-1)/$$2*$$2" | bc) $$1; }; pad
-stage1.out: stage1/main.asm stage1/print.asm stage2.out stage3.out
- nasm -f bin stage1/main.asm -o stage1.out \
- -dKSIZE=$$(du -cb stage{2,3}.out | tail -n1 | cut -f1)
+cuddles.img: stage1.bin stage2.bin stage3.bin fs.tar
+ cat stage{1,2,3}.bin fs.tar > cuddles.img
+ $(PAD_BOUNDARY) cuddles.img 1048576
-stage2.out: stage2/main.asm stage2/mmap.asm stage2/paging.asm stage2/vesa.asm stage1/print.asm
- nasm -f bin stage2/main.asm -o stage2.out
- dd if=/dev/zero bs=1 count=$$(echo 4608-$$(du -b stage2.out | cut -f1) | bc) >> stage2.out
+stage1.bin: stage1/main.asm stage1/print.asm stage2.bin stage3.bin
+ nasm -f bin stage1/main.asm -o stage1.bin \
+ -dKSIZE=$$(du -cb stage{2,3}.bin | tail -n1 | cut -f1)
-stage3.out: $(STAGE3) stage3.ld
+stage2.bin: stage2/main.asm stage2/mmap.asm stage2/paging.asm stage2/vesa.asm stage1/print.asm
+ nasm -f bin stage2/main.asm -o stage2.bin
+ truncate -s 4608 stage2.bin
+
+stage3.bin: $(STAGE3) stage3.ld
ld $(STAGE3) -T stage3.ld -Map=stage3.map
+ $(PAD_BOUNDARY) stage3.bin 512
stage3/%.o: stage3/%.asm
nasm -f elf64 $< -o $@
@@ -50,19 +57,28 @@ stage3/%.o: stage3/%.c
stage3/isr.asm: stage3/isr.lua
lua stage3/isr.lua > stage3/isr.asm
-.PHONY: run clean flash disas map
+fs.tar: $(shell find fs | sed 's/ /\\ /g')
+ cd fs && tar --format=ustar -cf ../fs.tar *
+
+.PHONY: run clean flash disas map qemu bochs
-run: cuddles.img
+bochs: cuddles.img
+ rm -f cuddles.img.lock
echo c | bochs -q
+qemu: cuddles.img
+ qemu-system-x86_64 -drive format=raw,file=cuddles.img
+
+run: qemu
+
clean:
- rm -rf stage3/*.o *.out *.img *.map stage3/isr.asm
+ rm -rf stage3/*.o *.bin *.img *.map stage3/isr.asm fs.tar
flash: cuddles.img
dd if=cuddles.img of=$(DEV)
-disas: stage3.out
- objdump -b binary -D -M intel -m i386:x86-64 stage3.out --adjust-vma 0x9000 --disassembler-color=on
+disas: stage3.bin
+ objdump -b binary -D -M intel -m i386:x86-64 stage3.bin --adjust-vma 0x9000 --disassembler-color=on
-map: stage3.out
+map: stage3.bin
cat stage3.map
diff --git a/bochsrc b/bochsrc
index fcda911..a6c40a3 100644
--- a/bochsrc
+++ b/bochsrc
@@ -1,5 +1,6 @@
-floppya: 1_44=cuddles.img, status=inserted
-boot: a
+#floppya: 1_44=cuddles.img, status=inserted
+ata0-master: type=disk, path="cuddles.img", mode=flat
+boot: c
#display_library: x, options="gui_debug"
megs: 32
#debug: PIC=report
diff --git a/fs/blahaj.cuddleimg b/fs/blahaj.cuddleimg
new file mode 100644
index 0000000..f616983
--- /dev/null
+++ b/fs/blahaj.cuddleimg
Binary files differ
diff --git a/fs/blahaj.png b/fs/blahaj.png
new file mode 100644
index 0000000..d7d5b26
--- /dev/null
+++ b/fs/blahaj.png
Binary files differ
diff --git a/fs/fonts/Bm437_IBM_VGA_8x16.cuddlefont b/fs/fonts/Bm437_IBM_VGA_8x16.cuddlefont
new file mode 100644
index 0000000..8809f2d
--- /dev/null
+++ b/fs/fonts/Bm437_IBM_VGA_8x16.cuddlefont
Binary files differ
diff --git a/fs/fonts/otb/Bm437_IBM_VGA_8x16.otb b/fs/fonts/otb/Bm437_IBM_VGA_8x16.otb
new file mode 100644
index 0000000..2dc41c3
--- /dev/null
+++ b/fs/fonts/otb/Bm437_IBM_VGA_8x16.otb
Binary files differ
diff --git a/fs/fonts/otb/ter-u16b.otb b/fs/fonts/otb/ter-u16b.otb
new file mode 100644
index 0000000..8c8070a
--- /dev/null
+++ b/fs/fonts/otb/ter-u16b.otb
Binary files differ
diff --git a/fs/fonts/otb/ter-u16n.otb b/fs/fonts/otb/ter-u16n.otb
new file mode 100644
index 0000000..28a468d
--- /dev/null
+++ b/fs/fonts/otb/ter-u16n.otb
Binary files differ
diff --git a/fs/fonts/ter-u16n.cuddlefont b/fs/fonts/ter-u16n.cuddlefont
new file mode 100644
index 0000000..9bc55e7
--- /dev/null
+++ b/fs/fonts/ter-u16n.cuddlefont
Binary files differ
diff --git a/fs/init b/fs/init
new file mode 100644
index 0000000..61b0a77
--- /dev/null
+++ b/fs/init
@@ -0,0 +1,10 @@
+font fonts/Bm437_IBM_VGA_8x16.cuddlefont
+echo hello world
+cat uwu.txt
+charset_demo
+lspci
+echo meow meow meow
+img blahaj.cuddleimg
+font fonts/ter-u16n.cuddlefont
+echo This is the terminus font!
+charset_demo
diff --git a/fs/uwu.txt b/fs/uwu.txt
new file mode 100644
index 0000000..9c758be
--- /dev/null
+++ b/fs/uwu.txt
@@ -0,0 +1,15 @@
+ -------- --------
+ --/ \ / \--
+ / \/ \
+/ \
+| |
+| anna |
+\ /
+ \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ \/
diff --git a/stage1/main.asm b/stage1/main.asm
index c51fc59..33264b0 100644
--- a/stage1/main.asm
+++ b/stage1/main.asm
@@ -19,6 +19,9 @@ boot:
mov ebx, .msg
call print_str
+ ; save offset of the file system
+ mov dword[0x1000-10-8], KSIZE+512
+
; print boot drive
pusha
movzx eax, dl
@@ -145,5 +148,8 @@ load_stages:
%include "stage1/print.asm"
+times 440-($-$$) db 0
+db "hugs"
+
times 510-($-$$) db 0
dw 0xAA55
diff --git a/stage3.ld b/stage3.ld
index 002874a..45a1486 100644
--- a/stage3.ld
+++ b/stage3.ld
@@ -1,4 +1,4 @@
-OUTPUT(stage3.out)
+OUTPUT(stage3.bin)
OUTPUT_FORMAT(binary)
SECTIONS
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
diff --git a/util/png2cuddleimg/.gitignore b/util/png2cuddleimg/.gitignore
new file mode 100644
index 0000000..daad221
--- /dev/null
+++ b/util/png2cuddleimg/.gitignore
@@ -0,0 +1 @@
+png2cuddleimg
diff --git a/util/png2cuddleimg/Makefile b/util/png2cuddleimg/Makefile
new file mode 100644
index 0000000..3a18ee6
--- /dev/null
+++ b/util/png2cuddleimg/Makefile
@@ -0,0 +1,2 @@
+png2cuddleimg: main.c
+ gcc $$(pkg-config --cflags --libs libpng) -Wall -Wextra main.c -o png2cuddleimg
diff --git a/util/png2cuddleimg/main.c b/util/png2cuddleimg/main.c
new file mode 100644
index 0000000..8dbfb14
--- /dev/null
+++ b/util/png2cuddleimg/main.c
@@ -0,0 +1,68 @@
+#include <png.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <endian.h>
+
+int main(int argc, char *argv[])
+{
+#define TRY(expr, ...) if (!(expr)) { \
+ fprintf(stderr, "%s: ", argv[0]); \
+ fprintf(stderr, __VA_ARGS__); \
+ if (file != NULL) fclose(file); \
+ png_destroy_read_struct(&png, &info, NULL); \
+ return EXIT_FAILURE; }
+
+ FILE *file = NULL;
+ png_structp png = NULL;
+ png_infop info = NULL;
+
+ TRY(argc == 2, "usage: %s infile.png > outfile.cuddleimg\n", argv[0]);
+ TRY((file = fopen(argv[1], "r")) != NULL, "failed to open %s\n", argv[1]);
+
+ TRY(png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL),
+ "png_create_read_struct failed\n");
+
+ TRY(info = png_create_info_struct(png), "png_create_info_struct failed\n");
+
+ png_init_io(png, file);
+ png_read_info(png, info);
+
+ png_uint_32 width = png_get_image_width(png, info);
+ png_uint_32 height = png_get_image_height(png, info);
+ png_byte color_type = png_get_color_type(png, info);
+ png_byte bit_depth = png_get_bit_depth(png, info);
+
+ if (bit_depth == 16)
+ png_set_strip_16(png);
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png);
+ if(png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png);
+ if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png);
+
+ png_read_update_info(png, info);
+
+ fwrite(&width, 1, sizeof width, stdout);
+ fwrite(&height, 1, sizeof height, stdout);
+
+ png_uint_32 pitch = png_get_rowbytes(png, info);
+ png_byte row[pitch];
+ for (png_uint_32 y = 0; y < height; y++) {
+ png_read_row(png, row, NULL);
+
+ for (png_uint_32 x = 0; x < width; x++) {
+ png_byte tmp = row[4*x];
+ row[4*x] = row[4*x+2];
+ row[4*x+2] = tmp;
+ }
+
+ fwrite(row, 1, pitch, stdout);
+ }
+
+ fclose(file);
+ png_destroy_read_struct(&png, &info, NULL);
+ return EXIT_SUCCESS;
+}
diff --git a/util/ttf2cuddlefont/.gitignore b/util/ttf2cuddlefont/.gitignore
new file mode 100644
index 0000000..1423b0e
--- /dev/null
+++ b/util/ttf2cuddlefont/.gitignore
@@ -0,0 +1 @@
+ttf2cuddlefont
diff --git a/util/ttf2cuddlefont/Makefile b/util/ttf2cuddlefont/Makefile
new file mode 100644
index 0000000..82b54cf
--- /dev/null
+++ b/util/ttf2cuddlefont/Makefile
@@ -0,0 +1,2 @@
+ttf2cuddlefont: main.c
+ gcc $$(pkg-config --cflags --libs freetype2) -Wall -Wextra main.c -o ttf2cuddlefont
diff --git a/util/ttf2cuddlefont/main.c b/util/ttf2cuddlefont/main.c
new file mode 100644
index 0000000..764dec9
--- /dev/null
+++ b/util/ttf2cuddlefont/main.c
@@ -0,0 +1,52 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+static inline unsigned char bitreverse(unsigned char b) {
+ b = (b & 0b11110000) >> 4 | (b & 0b00001111) << 4;
+ b = (b & 0b11001100) >> 2 | (b & 0b00110011) << 2;
+ b = (b & 0b10101010) >> 1 | (b & 0b01010101) << 1;
+ return b;
+}
+
+int main(int argc, char *argv[])
+{
+#define TRY(expr, ...) if (!(expr)) \
+ { fprintf(stderr, "%s: ", argv[0]); fprintf(stderr, __VA_ARGS__); return EXIT_FAILURE; }
+
+ TRY(argc == 2, "usage: %s infile.ttf > outfile.cuddlefont\n", argv[0]);
+
+ FT_Library lib;
+ TRY(FT_Init_FreeType(&lib) == 0, "failed to initialize freetype\n");
+
+ FT_Face face;
+ TRY(FT_New_Face(lib, argv[1], 0, &face) == 0, "failed to load %s\n", argv[1]);
+ // TRY(FT_Set_Pixel_Sizes(face, 0, 16) == 0, "failed to select pixel size of 8x16\n");
+
+ for (int i = 0;; i++) {
+ TRY(i != face->num_fixed_sizes, "no 8x16 size available\n");
+
+ if (face->available_sizes[i].height == 16 &&
+ face->available_sizes[i].width == 8) {
+ TRY(FT_Select_Size(face, i) == 0, "failed to select font size");
+ break;
+ }
+ }
+
+ assert(bitreverse(0b10000000) == 0b00000001);
+
+ for (int i = 0; i < 256; i++) {
+ TRY(FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT) == 0,
+ "failed to load glyph %d\n", i);
+
+ TRY(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO) == 0,
+ "failed to render glyph %d\n", i);
+
+ for (unsigned int y = 0; y < 16; y++)
+ putchar(bitreverse(face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch]));
+ }
+}