diff options
author | Benji Dial <benji3.141@gmail.com> | 2020-05-24 11:02:43 -0400 |
---|---|---|
committer | Benji Dial <benji3.141@gmail.com> | 2020-05-24 11:02:43 -0400 |
commit | 02f14113cbf14c6f842fb43ecbc68d0c851ef3b0 (patch) | |
tree | 75d2d943d9822b3f945fd947e9b91eec1d68e900 | |
parent | 31d8ae388a7ded576abd3e3d99c3d9193ea6d704 (diff) | |
download | portland-os-02f14113cbf14c6f842fb43ecbc68d0c851ef3b0.tar.gz |
very basic vga, ata, serial drivers. start of fat and fs drivers
-rw-r--r-- | doc/internal/mem.txt | 8 | ||||
-rw-r--r-- | makefile | 30 | ||||
-rw-r--r-- | src/boot.asm | 9 | ||||
-rw-r--r-- | src/kernel/ata.c | 113 | ||||
-rw-r--r-- | src/kernel/ata.h | 6 | ||||
-rw-r--r-- | src/kernel/fat.c | 21 | ||||
-rw-r--r-- | src/kernel/fat.h | 17 | ||||
-rw-r--r-- | src/kernel/fs.c | 82 | ||||
-rw-r--r-- | src/kernel/fs.h | 10 | ||||
-rw-r--r-- | src/kernel/link.ld | 4 | ||||
-rw-r--r-- | src/kernel/main.c | 28 | ||||
-rw-r--r-- | src/kernel/panic.c | 31 | ||||
-rw-r--r-- | src/kernel/panic.h | 4 | ||||
-rw-r--r-- | src/kernel/serial.c | 100 | ||||
-rw-r--r-- | src/kernel/serial.h | 10 | ||||
-rw-r--r-- | src/kernel/util.asm | 37 | ||||
-rw-r--r-- | src/kernel/util.c | 100 | ||||
-rw-r--r-- | src/kernel/util.h | 13 | ||||
-rw-r--r-- | src/kernel/vga.c | 58 | ||||
-rw-r--r-- | src/kernel/vga.h | 6 | ||||
-rw-r--r-- | src/kernel/vga.inc | 11 |
21 files changed, 633 insertions, 65 deletions
diff --git a/doc/internal/mem.txt b/doc/internal/mem.txt index d3b7696..cc5d301 100644 --- a/doc/internal/mem.txt +++ b/doc/internal/mem.txt @@ -1,4 +1,8 @@ -0x0001.0000 - 0x0002.ffff: unused +0x0001.0000 - 0x0002.5fff: unused +0x0002.6000 - 0x0002.bfff: fat +0x0002.c000 - 0x0002.ffff: file buffers 0x0003.0000 - 0x0003.7fff: kernel 0x0003.8000 - 0x0003.ffff: stack -0x0004.0000 - 0x0007.ffff: unused
\ No newline at end of file +0x0004.0000 - 0x0007.ffff: unused +0x0008.0000 - 0x000d.9fff: ramd +0x000d.a000 - 0xffff.ffff: unused
\ No newline at end of file @@ -1,20 +1,32 @@ -qemu: floppy - qemu-system-i386 out/floppy.img - -floppy: kernel boot +disk: kernel boot mkdir -p obj out - /sbin/mkfs.fat -C -R 17 -n "PORTLAND OS" obj/shadow.img 1440 + /sbin/mkfs.fat -C -f 1 -F 12 -n "PORTLAND OS" -R 17 obj/shadow.img 8192 echo -n -e '\xeb\x3c' > obj/jmp.bin dd if=obj/jmp.bin of=obj/shadow.img obs=2 conv=notrunc dd if=out/boot.bin of=obj/shadow.img obs=1 seek=62 conv=notrunc dd if=out/kernel.bin of=obj/shadow.img seek=1 conv=notrunc - mv obj/shadow.img out/floppy.img + mv obj/shadow.img out/disk.img + +vbox-image: disk + VBoxManage convertfromraw out/disk.img out/disk.vdi --uuid a61929ed-3bf2-45ff-b98a-44f87c616dba + +kdump: kernel + objdump -M intel -d obj/kernel.elf > out/kernel.dasm +kgccargs = -m32 -ffreestanding -fno-asynchronous-unwind-tables kernel: mkdir -p obj/kernel out - gcc -m32 -ffreestanding -c src/kernel/main.c -o obj/kernel/main.o - gcc -m32 -ffreestanding -c src/kernel/vga.c -o obj/kernel/vga.o - ld -T src/kernel/link.ld obj/kernel/main.o obj/kernel/vga.o -o out/kernel.bin + gcc ${kgccargs} -c src/kernel/main.c -o obj/kernel/main.o + gcc ${kgccargs} -c src/kernel/vga.c -o obj/kernel/vga.o + gcc ${kgccargs} -c src/kernel/fat.c -o obj/kernel/fat.o + gcc ${kgccargs} -c src/kernel/fs.c -o obj/kernel/fs.o + gcc ${kgccargs} -c src/kernel/ata.c -o obj/kernel/ata.o + gcc ${kgccargs} -c src/kernel/util.c -o obj/kernel/utilc.o + gcc ${kgccargs} -c src/kernel/panic.c -o obj/kernel/panic.o + gcc ${kgccargs} -c src/kernel/serial.c -o obj/kernel/serial.o + nasm -f elf32 src/kernel/util.asm -o obj/kernel/utila.o + ld -T src/kernel/link.ld obj/kernel/main.o obj/kernel/vga.o obj/kernel/fat.o obj/kernel/fs.o obj/kernel/ata.o obj/kernel/utilc.o obj/kernel/panic.o obj/kernel/utila.o obj/kernel/serial.o -o obj/kernel.elf + objcopy -O binary -j .entry -j .bin obj/kernel.elf out/kernel.bin boot: mkdir -p out diff --git a/src/boot.asm b/src/boot.asm index fecf466..f8ff1c8 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -41,9 +41,14 @@ pmode: mov ds, ax mov ax, 0x18 mov ss, ax - mov sp, 0x7ffc + mov esp, 0x00008000 + + xor ebp, ebp + call kernel_segment * 16 - jmp kernel_segment * 16 +halt: + hlt + jmp halt gdt: dw .e - .t diff --git a/src/kernel/ata.c b/src/kernel/ata.c new file mode 100644 index 0000000..0e6cc4e --- /dev/null +++ b/src/kernel/ata.c @@ -0,0 +1,113 @@ +#include <stdint.h> +#include "panic.h" +#include "util.h" +#include "ata.h" + +enum { + AP_PRIMARY = 0x01f0, + AP_SECONDARY = 0x0170, + + AP_DATA = 0x0, + AP_ERROR = 0x1, + AP_FEAT = 0x1, + AP_COUNT = 0x2, + AP_SEC = 0x3, + AP_CYL_L = 0x4, + AP_CYL_H = 0x5, + AP_HD_DR = 0x6, + AP_LBA0 = 0x3, + AP_LBA1 = 0x4, + AP_LBA2 = 0x5, + AP_L3_DR = 0x6, + AP_STAT = 0x7, + AP_CMD = 0x7, + + APC_STAT = 0x0206, + APC_CTRL = 0x0206, + APC_ADDR = 0x0207 +}; + +enum { + ADR_BASE = 0xa0, + ADR_CASCD = 0x10, + ADR_LBA = 0x40 +}; + +enum { + AS_ERROR = 0x01, + AS_INDEX = 0x02, + AS_CORRECT = 0x04, + AS_DREADY = 0x08, + AS_SERVICE = 0x10, + AS_FAULT = 0x20, + AS_READY = 0x40, + AS_BUSY = 0x80 +}; + +enum { + AC_READ = 0x20, + AC_WRITE = 0x30, + AC_FLUSH = 0xe7 +}; + +void ata_ldelay() { + uint16_t i = 65535; + while (i--) + ; +} + +void ata_sdelay() { + uint8_t i = 255; + while (i--) + ; +} + +void ata_dpoll() { + uint8_t s; + while ((s = inb(AP_PRIMARY | AP_STAT) & (AS_BUSY | AS_DREADY)) != AS_DREADY) + if (s & (AS_ERROR | AS_FAULT)) + panic("ATA controller error or fault."); +} + +uint8_t read_sectors(uint16_t start, uint8_t count, void *buffer) { + outb(AP_PRIMARY | AP_L3_DR, ADR_BASE | ADR_LBA); + outb(AP_PRIMARY | AP_LBA2, 0); + outb(AP_PRIMARY | AP_LBA1, start >> 8); + outb(AP_PRIMARY | AP_LBA0, start & 0xff); + outb(AP_PRIMARY | AP_COUNT, count); + outb(AP_PRIMARY | AP_CMD, AC_READ); + uint8_t i = count - 1; + uint16_t *ptr = buffer; + do { + ata_dpoll(); + uint8_t j = 255; + do + *(ptr++) = inw(AP_PRIMARY | AP_DATA); + while (j--); + ata_ldelay(); + } while (i--); + return count;//TODO: return early if necessary +} + +uint8_t write_sectors(uint16_t start, uint8_t count, void *buffer) { + outb(AP_PRIMARY | AP_L3_DR, ADR_BASE | ADR_LBA); + outb(AP_PRIMARY | AP_LBA2, 0); + outb(AP_PRIMARY | AP_LBA1, start >> 8); + outb(AP_PRIMARY | AP_LBA0, start & 0xff); + outb(AP_PRIMARY | AP_COUNT, count); + outb(AP_PRIMARY | AP_CMD, AC_WRITE); + uint8_t i = 0; + uint16_t *ptr = buffer; + do { + ata_dpoll(); + uint8_t j = 0; + do { + ata_sdelay(); + outw(AP_PRIMARY | AP_DATA, *(ptr++)); + } + while (++j); + ata_ldelay(); + } while (++i != count); + outb(AP_PRIMARY | AP_CMD, AC_FLUSH); + return count;//TODO: return early if necessary +}
\ No newline at end of file diff --git a/src/kernel/ata.h b/src/kernel/ata.h new file mode 100644 index 0000000..605f991 --- /dev/null +++ b/src/kernel/ata.h @@ -0,0 +1,6 @@ +#include <stdint.h> + +void init_ata(); + +uint8_t read_sectors(uint16_t start, uint8_t count, void *buffer); +uint8_t write_sectors(uint16_t start, uint8_t count, void *buffer);
\ No newline at end of file diff --git a/src/kernel/fat.c b/src/kernel/fat.c new file mode 100644 index 0000000..00fa61f --- /dev/null +++ b/src/kernel/fat.c @@ -0,0 +1,21 @@ +#include "fat.h" +#include "ata.h" +#include "panic.h" + +void load_fat() { + read_sectors(FAT_INFO->reserved_sectors, FAT_INFO->sectors_per_fat, FAT); +} + +uint16_t get_cluster(uint16_t n) { + uint32_t t = *(uint32_t *)(FAT + (n / 2) * 3); + return (n % 2 ? (t >> 12) : t) & 0xfff; +} + +void set_cluster(uint16_t n, uint16_t v) { + uint32_t *t = (uint32_t *)(FAT + (n / 2) * 3); + *t = (*t & (n % 2 ? 0xff000fff : 0xfffff000)) | (n % 2 ? v << 12 : v); +} + +uint16_t get_start_cluster(uint8_t *path) { + panic("Not implemented (get_start_cluster)."); +}
\ No newline at end of file diff --git a/src/kernel/fat.h b/src/kernel/fat.h index e7aa956..0fbf59f 100644 --- a/src/kernel/fat.h +++ b/src/kernel/fat.h @@ -4,12 +4,12 @@ struct fat_info { uint8_t oem[8]; - uint16_t bytes_per_sector; - uint8_t sectors_per_cluster; + uint16_t bytes_per_sector;//Assumed to be 512 + uint8_t sectors_per_cluster;//Assumed to be 1 uint16_t reserved_sectors; - uint8_t fats; + uint8_t fats;//Assumed to be 1 uint16_t root_entries; - uint16_t sectors; + uint16_t sectors;//Assumed not to be 0 uint8_t media_type; uint16_t sectors_per_fat; uint16_t sectors_per_track; @@ -22,4 +22,11 @@ struct fat_info { uint32_t volume_id; uint8_t label[11]; uint8_t fs_type[8]; -} __attribute__ ((packed));
\ No newline at end of file +} __attribute__ ((packed)); + +#define FAT ((void *)0x00026000) +void load_fat(); +uint16_t get_cluster(uint16_t n); +void set_cluster(uint16_t n, uint16_t v); + +uint16_t get_start_cluster(uint8_t *path);
\ No newline at end of file diff --git a/src/kernel/fs.c b/src/kernel/fs.c new file mode 100644 index 0000000..129e631 --- /dev/null +++ b/src/kernel/fs.c @@ -0,0 +1,82 @@ +#include <stdint.h> +#include "fs.h" +#include "ata.h" +#include "fat.h" +#include <stdbool.h> +#include "panic.h" + +#define MAX_HANDLES 32 +#define FILE_BUFFER(h) ((void *)(0x0002be00 + (h << 9))) +#define HANDLE(h) ((handles - 1)[h]) +#define HEAD(h) (FILE_BUFFER(h) + HANDLE(h).seek % 512) + +struct handle_info { + uint16_t start_cluster; + uint16_t seek; + uint16_t loaded_cluster; + bool dirty; +}; + +struct handle_info handles[MAX_HANDLES]; + +void clear_fs_handles() { + struct handle_info *f = handles; + while (f < handles + MAX_HANDLES) + (f++)->start_cluster = 0; +} + +fs_handle next_handle() { + fs_handle r = 0; + while (HANDLE(++r).start_cluster) + if (r == MAX_HANDLES) + return 0; + return r; +} + +void write_buffer(fs_handle handle) { + HANDLE(handle).dirty = false; + panic("Not implemented (write_buffer)."); +} + +void read_buffer(fs_handle handle) { + if (HANDLE(handle).dirty) + write_buffer(handle); + HANDLE(handle).loaded_cluster = HANDLE(handle).seek >> 9; + panic("Not implemented (read_buffer)."); +} + +fs_handle fs_open(uint8_t *path) { + fs_handle next = next_handle(); + if (!next) + return 0; + uint16_t s = get_start_cluster(path); + if (!s) + return 0; + HANDLE(next).start_cluster = s; + HANDLE(next).seek = 0; + HANDLE(next).dirty = false; + read_buffer(next); + return next; +} + +int16_t fs_seek(fs_handle handle, int16_t by) { + uint16_t old = HANDLE(handle).seek; + uint16_t to = -by > old ? 0 : old + by; + HANDLE(handle).seek = to; + if ((to ^ old) & 0xfe00) + read_buffer(handle); +} + +uint16_t fs_read(fs_handle handle, uint16_t max, void *buffer) { + panic("Not implemented (fs_read)."); +} + +uint16_t fs_write(fs_handle handle, uint16_t max, void *buffer) { + panic("Not implemented (fs_write)."); +} + +void fs_close(fs_handle handle) { + if (HANDLE(handle).dirty) + write_buffer(handle); + HANDLE(handle).start_cluster = 0; +}
\ No newline at end of file diff --git a/src/kernel/fs.h b/src/kernel/fs.h new file mode 100644 index 0000000..821d810 --- /dev/null +++ b/src/kernel/fs.h @@ -0,0 +1,10 @@ +#include <stdint.h> + +void clear_fs_handles(); + +typedef uint8_t fs_handle; +fs_handle fs_open(uint8_t *path); +int16_t fs_seek(fs_handle handle, int16_t by); +uint16_t fs_read(fs_handle handle, uint16_t max, void *buffer); +uint16_t fs_write(fs_handle handle, uint16_t max, void *buffer); +void fs_close(fs_handle handle);
\ No newline at end of file diff --git a/src/kernel/link.ld b/src/kernel/link.ld index 1fcff40..1fc64fd 100644 --- a/src/kernel/link.ld +++ b/src/kernel/link.ld @@ -1,4 +1,4 @@ -OUTPUT_FORMAT(binary) +OUTPUT_FORMAT(elf32-i386) OUTPUT_ARCH(i386) SECTIONS { @@ -10,6 +10,8 @@ SECTIONS { *(.text) *(.rodata) *(.data) + } + /DISCARD/ : { *(.bss) } }
\ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index dbeb11b..877a276 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,14 +1,36 @@ #include <stdint.h> #include "vga.h" #include "fat.h" +#include "fs.h" +#include "ata.h" +#include "panic.h" +#include "serial.h" +#include "util.h" + +uint8_t nbuf[11]; void main() { vga_blank(); - vga_printsz("In kernel-land\n\nDisk label: "); + vga_printsz("Initializing drivers..."); + sinit(); + vga_printsz("\n Serial ready."); + load_fat(); + clear_fs_handles(); + vga_printsz("\n File system ready.\n\nDisk label: "); vga_printsn(FAT_INFO->label, 11); vga_printsz("\nDisk size: "); - vga_printu32((FAT_INFO->sectors * FAT_INFO->bytes_per_sector) >> 10); - vga_printsz("k\n\nHalting..."); + u32_dec(FAT_INFO->sectors >> 1, nbuf); + vga_printsz(nbuf); + vga_printsz("k\n\nFAT start:\n"); + nbuf[3] = 0; + for (uint8_t r = 0; r < 192; r += 24) { + for (uint8_t c = 0; c < 24; ++c) { + u8_hex(*(uint8_t *)(FAT + r + c), nbuf); + nbuf[2] = ' '; + vga_printsz(nbuf); + } + vga_printch('\n'); + } while (1) asm ("hlt"); }
\ No newline at end of file diff --git a/src/kernel/panic.c b/src/kernel/panic.c new file mode 100644 index 0000000..49d4a27 --- /dev/null +++ b/src/kernel/panic.c @@ -0,0 +1,31 @@ +#include <stdint.h> +#include "vga.h" +#include "serial.h" +#include "util.h" + +void halt() { + while (1) + asm volatile ("hlt"); +} + +void panic(uint8_t *message) { + uint32_t frame; + asm ( + "movl %%ebp, %0" + : "=r" (frame)); + vga_set_color(0x4f); + vga_blank(); + vga_printsz("Kernel panic: "); + vga_printsz(message); + vga_printsz("\n\nStack trace:"); + uint8_t stb[6]; + while (1) { + uint32_t ip = *(uint32_t *)(0x38000 + frame + 4); + if (!ip) + halt(); + vga_printsz("\n 0x"); + u16_hex(ip - 0x30000 - 5, stb);//assumes would return to just after a call instruction + vga_printsz(stb); + frame = *(uint32_t *)(0x38000 + frame); + } +}
\ No newline at end of file diff --git a/src/kernel/panic.h b/src/kernel/panic.h new file mode 100644 index 0000000..8972814 --- /dev/null +++ b/src/kernel/panic.h @@ -0,0 +1,4 @@ +#include <stdint.h> + +void panic(uint8_t *message) __attribute__ ((noreturn)); +void halt() __attribute__ ((noreturn));
\ No newline at end of file diff --git a/src/kernel/serial.c b/src/kernel/serial.c new file mode 100644 index 0000000..b88c7ec --- /dev/null +++ b/src/kernel/serial.c @@ -0,0 +1,100 @@ +#include <stdint.h> +#include <stdbool.h> +#include "util.h" + +enum { + CP_DATA = 0x0, + CP_INT = 0x1, + CP_FIFO = 0x2, + CP_LINE = 0x3, + CP_MODEM = 0x4, + CP_LINE_S = 0x5, + CP_MODEM_S = 0x6, + + CP_DIVLOW = 0x0, + CP_DIVHIGH = 0x1, + + CP_1 = 0x03f8, + CP_2 = 0x02f8, + CP_3 = 0x03e8, + CP_4 = 0x02e8 +}; + +enum { + CL_BAUD = 0x80, + + CL_PODD = 0x08, + CL_PEVEN = 0x0c, + CL_PON = 0x18, + CL_POFF = 0x1c, + + CL_LSTOP = 0x4, + + CL_5BIT = 0x0, + CL_6BIT = 0x1, + CL_7BIT = 0x2, + CL_8BIT = 0x3 +}; + +enum { + CLS_B_ERR = 0x80, + CLS_IDLE = 0x40, + CLS_WRITE = 0x20, + CLS_BREAK = 0x10, + CLS_FRAME = 0x08, + CLS_PAR = 0x04, + CLS_OVER = 0x02, + CLS_READ = 0x01 +}; + +bool error; +#define SERIAL_SPIN_LIMIT 65535 + +bool serr() { + return error; +} + +void sinit() { + error = false; + outb(CP_1 | CP_INT, 0); + outb(CP_1 | CP_LINE, CL_BAUD); + outb(CP_1 | CP_DIVLOW, 0x03);//38400 + outb(CP_1 | CP_DIVHIGH, 0x00);//baud + outb(CP_1 | CP_LINE, CL_8BIT); + outb(CP_1 | CP_FIFO, 0xc7);//? +} + +void sout(uint8_t b) { + if (error) + return; + uint16_t s = SERIAL_SPIN_LIMIT; + while (!(inb(CP_1 | CP_LINE_S) & CLS_WRITE)) + if (!--s) { + error = true; + return; + } + outb(CP_1 | CP_DATA, b); +} + +void soutsz(uint8_t *s) { + while (*s) + sout(*(s++)); +} + +void soutsn(uint8_t *s, uint8_t n) { + while (n--) + sout(*(s++)); +} + +uint8_t sin() { + if (error) + return 0; + while (!(inb(CP_1 | CP_LINE_S) & CLS_READ)) + ;//spin + return inb(CP_1 | CP_DATA); +} + +void sinsn(uint8_t *s, uint8_t n) { + while (n--) + *(s++) = sin(); +}
\ No newline at end of file diff --git a/src/kernel/serial.h b/src/kernel/serial.h new file mode 100644 index 0000000..f0465d0 --- /dev/null +++ b/src/kernel/serial.h @@ -0,0 +1,10 @@ +#include <stdint.h> +#include <stdbool.h> + +bool serr(); +void sinit(); +void sout(uint8_t b); +void soutsz(uint8_t *s); +void soutsn(uint8_t *s, uint8_t n); +uint8_t sin(); +void sinsn(uint8_t *s, uint8_t n);
\ No newline at end of file diff --git a/src/kernel/util.asm b/src/kernel/util.asm new file mode 100644 index 0000000..acac17f --- /dev/null +++ b/src/kernel/util.asm @@ -0,0 +1,37 @@ +bits 32 + +global outb +global inb +global outw +global inw + +section .text +outb: + ;word [esp + 4] = port + ;byte [esp + 8] = value + mov dx, word [esp + 4] + mov al, byte [esp + 8] + out dx, al + ret + +inb: + ;word [esp + 4] = port + ;al out = value + mov dx, word [esp + 4] + in al, dx + ret + +outw: + ;word [esp + 4] = port + ;word [esp + 8] = value + mov dx, word [esp + 4] + mov ax, word [esp + 8] + out dx, ax + ret + +inw: + ;word [esp + 4] = port + ;ax out = value + mov dx, word [esp + 4] + in ax, dx + ret
\ No newline at end of file diff --git a/src/kernel/util.c b/src/kernel/util.c new file mode 100644 index 0000000..df6e7d8 --- /dev/null +++ b/src/kernel/util.c @@ -0,0 +1,100 @@ +#include <stdint.h> +#include "panic.h" +#include <stdbool.h> + +void memcpy(void *from, void *to, uint32_t n) { + panic("Not implemented (memcpy)."); +} + +void u32_dec(uint32_t n, uint8_t *b) { + if (!n) { + *(uint16_t *)b = '0'; + return; + } + bool zero = false; + for (uint32_t m = 1000000000; m; m /= 10) { + uint8_t d = (n / m) % 10; + if (zero) + *(b++) = d + '0'; + else if (d) { + zero = true; + *(b++) = d + '0'; + } + } + *b = 0; +} + +void u16_dec(uint16_t n, uint8_t *b) { + if (!n) { + *(uint16_t *)b = '0'; + return; + } + bool zero = false; + for (uint32_t m = 10000; m; m /= 10) { + uint8_t d = (n / m) % 10; + if (zero) + *(b++) = d + '0'; + else if (d) { + zero = true; + *(b++) = d + '0'; + } + } + *b = 0; +} + +void u8_dec(uint8_t n, uint8_t *b) { + if (!n) { + *(uint16_t *)b = '0'; + return; + } + bool zero = false; + for (uint32_t m = 100; m; m /= 10) { + uint8_t d = (n / m) % 10; + if (zero) + *(b++) = d + '0'; + else if (d) { + zero = true; + *(b++) = d + '0'; + } + } + *b = 0; +} + +void u32_hex(uint32_t n, uint8_t *b) { + uint8_t m = 28; + while (1) { + uint8_t d = (n >> m) & 0xf; + *(b++) = d >= 10 ? 'a' + d - 10 : '0' + d; + if (!m) { + *b = 0; + return; + } + m -= 4; + } +} + +void u16_hex(uint16_t n, uint8_t *b) { + uint8_t m = 12; + while (1) { + uint8_t d = (n >> m) & 0xf; + *(b++) = d >= 10 ? 'a' + d - 10 : '0' + d; + if (!m) { + *b = 0; + return; + } + m -= 4; + } +} + +void u8_hex(uint8_t n, uint8_t *b) { + uint8_t m = 4; + while (1) { + uint8_t d = (n >> m) & 0xf; + *(b++) = d >= 10 ? 'a' + d - 10 : '0' + d; + if (!m) { + *b = 0; + return; + } + m -= 4; + } +}
\ No newline at end of file diff --git a/src/kernel/util.h b/src/kernel/util.h new file mode 100644 index 0000000..08b3e4a --- /dev/null +++ b/src/kernel/util.h @@ -0,0 +1,13 @@ +#include <stdint.h> + +void memcpy(void *from, void *to, uint32_t n); +void outb(uint16_t port, uint8_t value); +uint8_t inb(uint16_t port); +void outw(uint16_t port, uint16_t value); +uint16_t inw(uint16_t port); +void u32_dec(uint32_t n, uint8_t *b); +void u16_dec(uint16_t n, uint8_t *b); +void u8_dec(uint8_t n, uint8_t *b); +void u32_hex(uint32_t n, uint8_t *b); +void u16_hex(uint16_t n, uint8_t *b); +void u8_hex(uint8_t n, uint8_t *b);
\ No newline at end of file diff --git a/src/kernel/vga.c b/src/kernel/vga.c index 8e438a8..c387b22 100644 --- a/src/kernel/vga.c +++ b/src/kernel/vga.c @@ -1,6 +1,12 @@ #include <stdint.h> #include <stdbool.h> +#define VGA_COM_MIRROR + +#ifdef VGA_COM_MIRROR +#include "serial.h" +#endif + #define VGA_COLUMNS 80 #define VGA_LINES 25 #define VGA_START (uint16_t *)0x000b8000 @@ -8,11 +14,18 @@ uint16_t *cursor = VGA_START; uint16_t color = 0x1f00; +void vga_set_color(uint8_t new_color) { + color = new_color << 8; +} + void vga_scroll() { cursor = VGA_START; } void vga_blank() { +#ifdef VGA_COM_MIRROR + soutsz("\r\n\r\n<CLEAR>\r\n\r\n"); +#endif uint32_t f = (color << 16) | color | 0x00200020; uint32_t *p = (uint32_t *)VGA_START; while (p < (uint32_t *)VGA_END) @@ -22,10 +35,16 @@ void vga_blank() { void vga_printch(uint8_t ch) { if (ch == '\n') { +#ifdef VGA_COM_MIRROR + soutsz("\r\n"); +#endif if ((cursor = cursor - (cursor - VGA_START) % VGA_COLUMNS + VGA_COLUMNS) == VGA_END) vga_scroll(); return; } +#ifdef VGA_COM_MIRROR + sout(ch); +#endif *(cursor++) = color | ch; if (cursor == VGA_END) vga_scroll(); @@ -39,43 +58,4 @@ void vga_printsz(uint8_t *sz) { void vga_printsn(uint8_t *sn, uint8_t n) { while (n--) vga_printch(*(sn++)); -} - -void vga_printu32(uint32_t n) { - bool zero = false; - for (uint32_t m = 1000000000; m; m /= 10) { - uint8_t d = (n / m) % 10; - if (zero) - vga_printch(d + '0'); - else if (d) { - zero = true; - vga_printch(d + '0'); - } - } -} - -void vga_printu16(uint16_t n) { - bool zero = false; - for (uint16_t m = 10000; m; m /= 10) { - uint8_t d = (n / m) % 10; - if (zero) - vga_printch(d + '0'); - else if (d) { - zero = true; - vga_printch(d + '0'); - } - } -} - -void vga_printu8(uint8_t n) { - bool zero = false; - for (uint8_t m = 100; m; m /= 10) { - uint8_t d = (n / m) % 10; - if (zero) - vga_printch(d + '0'); - else if (d) { - zero = true; - vga_printch(d + '0'); - } - } }
\ No newline at end of file diff --git a/src/kernel/vga.h b/src/kernel/vga.h index 95c6335..1e041df 100644 --- a/src/kernel/vga.h +++ b/src/kernel/vga.h @@ -1,10 +1,8 @@ #include <stdint.h> +void vga_set_color(uint8_t color); void vga_blank(); void vga_scroll(); void vga_printch(uint8_t ch); void vga_printsz(uint8_t *sz); -void vga_printsn(uint8_t *sn, uint8_t n); -void vga_printu32(uint32_t n); -void vga_printu16(uint16_t n); -void vga_printu8(uint8_t n);
\ No newline at end of file +void vga_printsn(uint8_t *sn, uint8_t n);
\ No newline at end of file diff --git a/src/kernel/vga.inc b/src/kernel/vga.inc new file mode 100644 index 0000000..c7244e1 --- /dev/null +++ b/src/kernel/vga.inc @@ -0,0 +1,11 @@ +extern vga_set_color +extern vga_blank +extern vga_scroll +extern vga_printch +extern vga_printsz +extern vga_printsn +extern vga_printu32 +extern vga_printu16 +extern vga_printu8 +extern vga_printu32h +extern vga_printu8h
\ No newline at end of file |