summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarvin Borner2021-07-04 22:29:36 +0200
committerMarvin Borner2021-07-04 22:29:36 +0200
commitc7047fa8ff78a7ee9de9e48e9310fd5afbc264a3 (patch)
tree6f7561564605659af6b9dcae7af7c182e33616ae
parent9b8698769535846d029c44247956eed9a21f1185 (diff)
Added stuff
Very descriptive!
-rw-r--r--src/loader/ide.c73
-rw-r--r--src/loader/inc/assert.h17
-rw-r--r--src/loader/inc/ide.h73
-rw-r--r--src/loader/inc/lib.h3
-rw-r--r--src/loader/inc/log.h2
-rw-r--r--src/loader/lib.c47
-rw-r--r--src/loader/log.c79
-rw-r--r--src/loader/main.c7
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)
;