diff options
author | Marvin Borner | 2021-07-04 22:29:36 +0200 |
---|---|---|
committer | Marvin Borner | 2021-07-04 22:29:36 +0200 |
commit | c7047fa8ff78a7ee9de9e48e9310fd5afbc264a3 (patch) | |
tree | 6f7561564605659af6b9dcae7af7c182e33616ae | |
parent | 9b8698769535846d029c44247956eed9a21f1185 (diff) |
Added stuff
Very descriptive!
-rw-r--r-- | src/loader/ide.c | 73 | ||||
-rw-r--r-- | src/loader/inc/assert.h | 17 | ||||
-rw-r--r-- | src/loader/inc/ide.h | 73 | ||||
-rw-r--r-- | src/loader/inc/lib.h | 3 | ||||
-rw-r--r-- | src/loader/inc/log.h | 2 | ||||
-rw-r--r-- | src/loader/lib.c | 47 | ||||
-rw-r--r-- | src/loader/log.c | 79 | ||||
-rw-r--r-- | src/loader/main.c | 7 |
8 files changed, 289 insertions, 12 deletions
diff --git a/src/loader/ide.c b/src/loader/ide.c new file mode 100644 index 0000000..f279bc2 --- /dev/null +++ b/src/loader/ide.c @@ -0,0 +1,73 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#include <cpu.h> +#include <def.h> +#include <ide.h> +#include <log.h> + +static u8 ide_buf[SECTOR_SIZE] = { 0 }; + +static void ide_select_drive(u8 bus, u8 drive) +{ + if (bus == ATA_PRIMARY) { + if (drive == ATA_MASTER) + outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xa0); + else + outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xb0); + } else { + if (drive == ATA_MASTER) + outb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xa0); + else + outb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xb0); + } +} + +static u8 ide_find(u8 bus, u8 drive) +{ + u16 io = bus == ATA_PRIMARY ? ATA_PRIMARY_IO : ATA_SECONDARY_IO; + ide_select_drive(bus, drive); + + // Reset + outb(io + ATA_REG_SECCOUNT0, 0); + outb(io + ATA_REG_LBA0, 0); + outb(io + ATA_REG_LBA1, 0); + outb(io + ATA_REG_LBA2, 0); + + // Identify + outb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + u8 status = inb(io + ATA_REG_STATUS); + if (!status) + return 0; + + while ((inb(io + ATA_REG_STATUS) & ATA_SR_BSY) != 0) + ; + + do { + status = inb(io + ATA_REG_STATUS); + if (status & ATA_SR_ERR) + return 0; + } while ((status & ATA_SR_DRQ) == 0); + + for (int i = 0; i < BLOCK_COUNT; i++) + *(u16 *)(ide_buf + i * 2) = inw(io + ATA_REG_DATA); + + return 1; +} + +static void ata_probe(void) +{ + for (u8 i = 0; i < 4; i++) { + u32 bus = i < 2 ? ATA_PRIMARY : ATA_SECONDARY; + u32 drive = i % 2 ? ATA_MASTER : ATA_SLAVE; + + if (!ide_find(bus, drive)) + continue; + + log("[IDE] Found hd%c\n", 'a' + i); + } +} + +void ata_install(void) +{ + ata_probe(); +} diff --git a/src/loader/inc/assert.h b/src/loader/inc/assert.h new file mode 100644 index 0000000..65db119 --- /dev/null +++ b/src/loader/inc/assert.h @@ -0,0 +1,17 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef ASSERT_H +#define ASSERT_H + +#include <log.h> +#define assert(exp) \ + { \ + if (!(exp)) { \ + log("%s:%d: %s: Kernel assertion '%s' failed\n", __FILE__, __LINE__, \ + __func__, #exp); \ + while (1) \ + __asm__ volatile("cli\nhlt"); \ + } \ + } + +#endif diff --git a/src/loader/inc/ide.h b/src/loader/inc/ide.h new file mode 100644 index 0000000..24b4eb1 --- /dev/null +++ b/src/loader/inc/ide.h @@ -0,0 +1,73 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef IDE_H +#define IDE_H + +#define BLOCK_SIZE 1024 +#define BLOCK_COUNT 256 // BLOCK_SIZE / sizeof(u32) +#define SECTOR_SIZE 512 +#define SECTOR_COUNT (BLOCK_SIZE / SECTOR_SIZE) + +#define ATA_PRIMARY_IO 0x1f0 +#define ATA_SECONDARY_IO 0x170 + +// From spec +#define ATA_PRIMARY 0x00 +#define ATA_SECONDARY 0x01 +#define ATA_READ 0x00 +#define ATA_WRITE 0x013 +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x01 +#define ATA_SR_BSY 0x80 +#define ATA_SR_DRDY 0x40 +#define ATA_SR_DF 0x20 +#define ATA_SR_DSC 0x10 +#define ATA_SR_DRQ 0x08 +#define ATA_SR_CORR 0x04 +#define ATA_SR_IDX 0x02 +#define ATA_SR_ERR 0x01 +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SECCOUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0a +#define ATA_REG_LBA5 0x0b +#define ATA_REG_CONTROL 0x0c +#define ATA_REG_ALTSTATUS 0x0c +#define ATA_REG_DEVADDRESS 0x0d +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xc8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xca +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xe7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xea +#define ATA_CMD_PACKET 0xa0 +#define ATA_CMD_IDENTIFY_PACKET 0xa1 +#define ATA_CMD_IDENTIFY 0xec +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +void ata_install(void); + +#endif diff --git a/src/loader/inc/lib.h b/src/loader/inc/lib.h index 997db67..d5984dd 100644 --- a/src/loader/inc/lib.h +++ b/src/loader/inc/lib.h @@ -9,6 +9,9 @@ u32 strlen(const char *str); u32 strnlen(const char *s, u32 max); u32 strlcpy(char *dst, const char *src, u32 size); +void *memcpy(void *dest, const void *src, u32 n); +void *memset(void *dest, u32 val, u32 n); + int itoa(s32 value, char *buffer, u32 base); #endif diff --git a/src/loader/inc/log.h b/src/loader/inc/log.h index 2d65a76..6fad366 100644 --- a/src/loader/inc/log.h +++ b/src/loader/inc/log.h @@ -6,6 +6,8 @@ void serial_install(void); void serial_print(const char *data); +void vga_clear(void); + void log(const char *format, ...); #endif diff --git a/src/loader/lib.c b/src/loader/lib.c index c54ef14..a9fec01 100644 --- a/src/loader/lib.c +++ b/src/loader/lib.c @@ -45,6 +45,53 @@ u32 strlcpy(char *dst, const char *src, u32 size) } /** + * Common memory functions + */ + +void *memcpy(void *dest, const void *src, u32 n) +{ + // Inspired by jgraef at osdev + u32 num_dwords = n / 4; + u32 num_bytes = n % 4; + u32 *dest32 = (u32 *)dest; + const u32 *src32 = (const u32 *)src; + u8 *dest8 = ((u8 *)dest) + num_dwords * 4; + const u8 *src8 = ((const u8 *)src) + num_dwords * 4; + + __asm__ volatile("rep movsl\n" + : "=S"(src32), "=D"(dest32), "=c"(num_dwords) + : "S"(src32), "D"(dest32), "c"(num_dwords) + : "memory"); + + for (u32 i = 0; i < num_bytes; i++) + dest8[i] = src8[i]; + + return dest; +} + +void *memset(void *dest, u32 val, u32 n) +{ + // Inspired by jgraef at osdev + u32 uval = val; + u32 num_dwords = n / 4; + u32 num_bytes = n % 4; + u32 *dest32 = (u32 *)dest; + u8 *dest8 = ((u8 *)dest) + num_dwords * 4; + u8 val8 = (u8)val; + u32 val32 = uval | (uval << 8) | (uval << 16) | (uval << 24); + + __asm__ volatile("rep stosl\n" + : "=D"(dest32), "=c"(num_dwords) + : "D"(dest32), "c"(num_dwords), "a"(val32) + : "memory"); + + for (u32 i = 0; i < num_bytes; i++) + dest8[i] = val8; + + return dest; +} + +/** * Conversion */ diff --git a/src/loader/log.c b/src/loader/log.c index a2c05f0..5d60f38 100644 --- a/src/loader/log.c +++ b/src/loader/log.c @@ -1,3 +1,4 @@ +#include <assert.h> #include <cpu.h> #include <lib.h> #include <log.h> @@ -62,27 +63,36 @@ static u32 vsnprintf(char *str, u32 size, const char *format, va_list ap) * Serial */ +#define PORT 0x3f8 + void serial_install(void) { - outb(0x3f8 + 1, 0x00); - outb(0x3f8 + 3, 0x80); - outb(0x3f8 + 0, 0x03); - outb(0x3f8 + 1, 0x00); - outb(0x3f8 + 3, 0x03); - outb(0x3f8 + 2, 0xc7); - outb(0x3f8 + 4, 0x0B); + outb(PORT + 1, 0x00); + outb(PORT + 3, 0x80); + outb(PORT + 0, 0x03); + outb(PORT + 1, 0x00); + outb(PORT + 3, 0x03); + outb(PORT + 2, 0xc7); + + // Test serial chip + outb(PORT + 4, 0x1e); // Enable loopback + outb(PORT + 0, 0xae); // Write + assert(inb(PORT + 0) == 0xae); // Verify receive + + // Activate + outb(PORT + 4, 0x0f); } -static int is_transmit_empty(void) +static int serial_empty(void) { - return inb(0x3f8 + 5) & 0x20; + return inb(PORT + 5) & 0x20; } static void serial_put(char ch) { - while (is_transmit_empty() == 0) + while (serial_empty() == 0) ; - outb(0x3f8, (u8)ch); + outb(PORT, (u8)ch); } void serial_print(const char *data) @@ -92,6 +102,52 @@ void serial_print(const char *data) } /** + * VGA + */ + +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 +#define VGA_ADDRESS 0xb8000 + +void vga_clear(void) +{ + u16 *out = (u16 *)VGA_ADDRESS; + for (u16 i = 0; i < 80 * 25; i++) + out[i] = 0; +} + +static void vga_put(char ch) +{ + static u8 x = 0; + static u8 y = 0; + + if (ch == '\n') { + x = 0; + y++; + return; + } else if (x + 1 == VGA_WIDTH) { + x = 0; + y++; + } else if (y + 1 == VGA_HEIGHT) { + x = 0; + y = 0; + vga_clear(); + } + + u8 *out = (u8 *)(VGA_ADDRESS + 2 * (x + y * VGA_WIDTH)); + *out++ = ch; + *out++ = 0x07; + + x++; +} + +static void vga_print(const char *data) +{ + for (const char *p = data; *p; p++) + vga_put(*p); +} + +/** * Universal print function */ @@ -105,4 +161,5 @@ void log(const char *format, ...) va_end(ap); serial_print(buf); + vga_print(buf); } diff --git a/src/loader/main.c b/src/loader/main.c index 54b5122..53bf53e 100644 --- a/src/loader/main.c +++ b/src/loader/main.c @@ -1,6 +1,7 @@ // MIT License, Copyright (c) 2021 Marvin Borner #include <def.h> +#include <ide.h> #include <log.h> /** @@ -10,8 +11,12 @@ int start(void); int start(void) { + vga_clear(); serial_install(); - log("Hello %d\n", 42); + + log("Log initiated\n"); + + ata_install(); while (1) ; |