Add printf, gdb support, fix gdt
diff --git a/src/.gdbinit b/src/.gdbinit
new file mode 100644
index 0000000..24efe1e
--- /dev/null
+++ b/src/.gdbinit
@@ -0,0 +1 @@
+target remote localhost:1234
diff --git a/src/Makefile b/src/Makefile
index 7383c59..23ef8f4 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,4 +1,4 @@
-SOURCES = boot.o main.o descriptor_tables.o mem.o vga.o gdt_flush.o idt.o interrupts.o
+SOURCES = boot.o main.o descriptor_tables.o mem.o vga.o gdt_flush.o idt.o interrupts.o log.o
CFLAGS = -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 -O2 -g
LDFLAGS = -Tlink.ld -melf_i386
ASMFLAGS = -felf
@@ -7,9 +7,18 @@
ld $(LDFLAGS) -o $@ $^
clean:
- rm -f *.o *.bin *.elf
+ rm -f *.o *.bin *.elf ../bin/*.iso
-qemu: install
+debug: kernel.elf
+ qemu-system-i386 -s -S -kernel kernel.elf &
+ @echo run "target remote localhost:1234" to connect to qemu
+ gdb
+ @pkill qemu-system-i38
+
+qemu: kernel.elf
+ qemu-system-i386 -monitor stdio -kernel kernel.elf
+
+qemu-iso: install
qemu-system-i386 -monitor stdio ../bin/bluejay.iso
.s.o:
@@ -17,6 +26,7 @@
install: kernel.elf
cp kernel.elf ../boot/
+ rm -f ../bin/bluejay.iso
grub-mkrescue -o ../bin/bluejay.iso ..
-.PHONY: install qemu clean
+.PHONY: install qemu clean qemu-iso debug
diff --git a/src/boot.s b/src/boot.s
index 5c4381c..c71ef40 100644
--- a/src/boot.s
+++ b/src/boot.s
@@ -27,11 +27,11 @@
dd start
[global start]
- [extern main] ; C code
+ [extern kmain] ; C code
start:
push ebx ; Holds multiboot header location
cli
- call main
+ call kmain
jmp $
diff --git a/src/descriptor_tables.c b/src/descriptor_tables.c
index 3b121b1..36e6f8f 100644
--- a/src/descriptor_tables.c
+++ b/src/descriptor_tables.c
@@ -52,6 +52,7 @@
void init_gdt()
{
+ vga_write("Initializing GDT...\n");
gdt_pointer.limit = sizeof(struct gdt_entry) * 5 - 1;
gdt_pointer.base = (uint)&gdt_entries;
@@ -61,6 +62,9 @@
gdt_set_gate(3, 0, ~0, 0xfa, 0xcf); // User mode code segment
gdt_set_gate(4, 0, ~0, 0xf2, 0xcf); // User mode data segment
+ for (volatile uint i = 0; i < 0x1000; i++)
+ {} // waste some time, for some reason this helps
+
gdt_flush((uint) &gdt_pointer);
vga_write("GDT Initialized\n");
diff --git a/src/descriptor_tables.h b/src/descriptor_tables.h
index d918f4a..6f3fb89 100644
--- a/src/descriptor_tables.h
+++ b/src/descriptor_tables.h
@@ -16,7 +16,7 @@
uint a_dpl : 2;
uint a_dt : 1;
uint a_type : 4;
- };
+ } __attribute__((packed));
uchar access;
};
@@ -29,7 +29,7 @@
uint g_d : 1;
uint g_zero : 2; /* includes A */
uint g_len : 4;
- };
+ } __attribute__((packed));
uchar granularity;
};
@@ -59,7 +59,7 @@
uchar f_p : 1;
uchar f_dpl : 2;
uchar f_const : 5;
- };
+ } __attribute__((packed));
uchar flags;
};
diff --git a/src/interrupts.c b/src/interrupts.c
index 615f367..c8ded7c 100644
--- a/src/interrupts.c
+++ b/src/interrupts.c
@@ -11,5 +11,7 @@
void isr_handler(struct registers regs)
{
- vga_write("Interrupt triggered\n");
+ vga_write("Interrupt triggered! ");
+ vga_putx(regs.interrupt_number);
+ vga_write("\n");
}
diff --git a/src/kint.h b/src/kint.h
index 5b363aa..0184443 100644
--- a/src/kint.h
+++ b/src/kint.h
@@ -6,3 +6,11 @@
typedef unsigned long ulong;
typedef unsigned long long size_t;
+
+typedef uchar bool;
+
+enum
+{
+ false = 0,
+ true,
+};
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 0000000..19959e7
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,63 @@
+#include "log.h"
+#include "kint.h"
+#include "vga.h"
+#include "stdarg.h"
+
+void kprintf(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ while (*format)
+ {
+ if (*format == '%')
+ {
+ format++;
+
+ switch (*format)
+ {
+ case 'd':
+ {
+ uint x = (uint) va_arg(args, uint);
+ vga_putd(x);
+ break;
+ }
+
+ case 'x':
+ {
+ // consider hex always unsigned
+ uint x = (uint) va_arg(args, uint);
+ vga_putx(x);
+ break;
+ }
+
+ case 's':
+ {
+ char *s = va_arg(args, char *);
+ vga_write(s);
+ break;
+ }
+ }
+ format++;
+ }
+ else
+ {
+ vga_put(*format);
+ format++;
+ }
+ }
+
+ va_end(args);
+}
+
+void kassert_int(bool condition, const char *message, const char *file, const int line)
+{
+ if (!condition)
+ {
+ vga_set_color(LIGHT_RED, BLACK);
+ kprintf("ASSERTION FAILED: %s:%d\n%s\n", file, line, message);
+
+ while (1)
+ {}
+ }
+}
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000..48da93e
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "kint.h"
+
+void kprintf(const char *format, ...);
+void kassert_int(bool condition, const char *message, const char *file, const int line);
+
+#define kassert(cond, msg) kassert_int((cond), (msg), __FILE__, __LINE__)
diff --git a/src/main.c b/src/main.c
index 4854924..f5b6200 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,19 +1,24 @@
#include "vga.h"
+#include "log.h"
#include "descriptor_tables.h"
-int main(void *mboot)
+int kmain(void *mboot)
{
vga_clear();
vga_set_color(LIGHT_BLUE, BLACK);
vga_write("Hello!\nWelcome to Bluejay OS\n");
-
vga_set_color(WHITE, BLACK);
- init_idt();
+ init_descriptor_tables();
- //init_descriptor_tables();
+ vga_set_color(LIGHT_GREEN, BLACK);
+ vga_write("Setup complete!\n");
+ vga_set_color(WHITE, BLACK);
- //asm volatile("int $0x03");
+ kassert(0, "should fail");
+
+ while (1)
+ {}
return 0xCAFEBABE;
}
diff --git a/src/stdarg.h b/src/stdarg.h
new file mode 100644
index 0000000..3af5dbb
--- /dev/null
+++ b/src/stdarg.h
@@ -0,0 +1,127 @@
+/* Copyright (C) 1989-2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/*
+ * ISO C Standard: 7.15 Variable arguments <stdarg.h>
+ */
+
+#ifndef _STDARG_H
+#ifndef _ANSI_STDARG_H_
+#ifndef __need___va_list
+#define _STDARG_H
+#define _ANSI_STDARG_H_
+#endif /* not __need___va_list */
+#undef __need___va_list
+
+/* Define __gnuc_va_list. */
+
+#ifndef __GNUC_VA_LIST
+#define __GNUC_VA_LIST
+typedef __builtin_va_list __gnuc_va_list;
+#endif
+
+/* Define the standard macros for the user,
+ if this invocation was from the user program. */
+#ifdef _STDARG_H
+
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L \
+ || __cplusplus + 0 >= 201103L
+#define va_copy(d,s) __builtin_va_copy(d,s)
+#endif
+#define __va_copy(d,s) __builtin_va_copy(d,s)
+
+/* Define va_list, if desired, from __gnuc_va_list. */
+/* We deliberately do not define va_list when called from
+ stdio.h, because ANSI C says that stdio.h is not supposed to define
+ va_list. stdio.h needs to have access to that data type,
+ but must not use that name. It should use the name __gnuc_va_list,
+ which is safe because it is reserved for the implementation. */
+
+#ifdef _BSD_VA_LIST
+#undef _BSD_VA_LIST
+#endif
+
+#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST))
+/* SVR4.2 uses _VA_LIST for an internal alias for va_list,
+ so we must avoid testing it and setting it here.
+ SVR4 uses _VA_LIST as a flag in stdarg.h, but we should
+ have no conflict with that. */
+#ifndef _VA_LIST_
+#define _VA_LIST_
+#ifdef __i860__
+#ifndef _VA_LIST
+#define _VA_LIST va_list
+#endif
+#endif /* __i860__ */
+typedef __gnuc_va_list va_list;
+#ifdef _SCO_DS
+#define __VA_LIST
+#endif
+#endif /* _VA_LIST_ */
+#else /* not __svr4__ || _SCO_DS */
+
+/* The macro _VA_LIST_ is the same thing used by this file in Ultrix.
+ But on BSD NET2 we must not test or define or undef it.
+ (Note that the comments in NET 2's ansi.h
+ are incorrect for _VA_LIST_--see stdio.h!) */
+#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT)
+/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */
+#ifndef _VA_LIST_DEFINED
+/* The macro _VA_LIST is used in SCO Unix 3.2. */
+#ifndef _VA_LIST
+/* The macro _VA_LIST_T_H is used in the Bull dpx2 */
+#ifndef _VA_LIST_T_H
+/* The macro __va_list__ is used by BeOS. */
+#ifndef __va_list__
+typedef __gnuc_va_list va_list;
+#endif /* not __va_list__ */
+#endif /* not _VA_LIST_T_H */
+#endif /* not _VA_LIST */
+#endif /* not _VA_LIST_DEFINED */
+#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
+#define _VA_LIST_
+#endif
+#ifndef _VA_LIST
+#define _VA_LIST
+#endif
+#ifndef _VA_LIST_DEFINED
+#define _VA_LIST_DEFINED
+#endif
+#ifndef _VA_LIST_T_H
+#define _VA_LIST_T_H
+#endif
+#ifndef __va_list__
+#define __va_list__
+#endif
+
+#endif /* not _VA_LIST_, except on certain systems */
+
+#endif /* not __svr4__ */
+
+#endif /* _STDARG_H */
+
+#endif /* not _ANSI_STDARG_H_ */
+#endif /* not _STDARG_H */
diff --git a/src/vga.c b/src/vga.c
index 1b10833..11fbc0c 100644
--- a/src/vga.c
+++ b/src/vga.c
@@ -1,5 +1,6 @@
#include "vga.h"
#include "mem.h"
+#include "log.h"
static uint cursor_x = 0;
static uint cursor_y = 0;
@@ -88,24 +89,44 @@
void vga_putd(uint d)
{
-
+ char str[48];
+ memset(str, 0, 48);
+ uint i = 0;
+
+ while (d > 0 && i < 48) // should never be more than 48 digits anyway
+ {
+ str[i++] = (d % 10) + '0';
+ d /= 10;
+ }
+
+ for (uint j = i; j; j--)
+ {
+ vga_put(str[j - 1]);
+ }
}
-static void vga_put_nibble(uchar n)
+static bool vga_put_nibble(uchar n, bool first)
{
+ if (first && n == 0)
+ return true;
+
if (n <= 9)
vga_put('0' + n);
else
vga_put('A' + n - 10);
+
+ return false;
}
void vga_putx(uint x)
{
+ bool first = true;
+
for (uint mask = 0xFF000000, shift = 24; mask; mask >>= 8, shift -= 8)
{
uchar byte = (x & mask) >> shift;
- vga_put_nibble((byte & 0xf0) >> 8);
- vga_put_nibble(byte & 0x0f);
+ first = vga_put_nibble((byte & 0xf0) >> 8, first);
+ first = vga_put_nibble(byte & 0x0f, first);
}
}
diff --git a/src/vga.h b/src/vga.h
index 0968ca1..9c7ba16 100644
--- a/src/vga.h
+++ b/src/vga.h
@@ -24,6 +24,7 @@
void vga_set_color(enum vga_colors fg, enum vga_colors bg);
void vga_put(char c);
+void vga_putd(uint d);
void vga_putx(uint x);
void vga_clear();
void vga_write(char *c);