Implemented initial printk. Added multiboot support.
This commit is contained in:
parent
3b27d50edb
commit
f23f3a8a8d
2
Makefile
2
Makefile
@ -5,7 +5,7 @@ GNU ?= $(PREFIX)/$(ARCH)/bin/$(ARCH)
|
|||||||
|
|
||||||
# Source files
|
# Source files
|
||||||
SOURCES_ASM := arch/$(ARCH)/boot.s
|
SOURCES_ASM := arch/$(ARCH)/boot.s
|
||||||
SOURCES_C := driver/video/vga.c kernel/brados.c lib/string.c
|
SOURCES_C := arch/$(ARCH)/multiboot.c driver/video/vga.c kernel/brados.c kernel/printk.c lib/string.c
|
||||||
|
|
||||||
# Object files
|
# Object files
|
||||||
OBJS := $(patsubst %.s,%.o,$(SOURCES_ASM))
|
OBJS := $(patsubst %.s,%.o,$(SOURCES_ASM))
|
||||||
|
13
arch/arm-none-eabi/multiboot.c
Normal file
13
arch/arm-none-eabi/multiboot.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <multiboot.h>
|
||||||
|
|
||||||
|
uint32_t multiboot_getAddress()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t multiboot_getMagic()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
@ -27,6 +27,9 @@ _start:
|
|||||||
# Setup the stack
|
# Setup the stack
|
||||||
movl $stack_top, %esp
|
movl $stack_top, %esp
|
||||||
|
|
||||||
|
# Push the multiboot information onto the stack
|
||||||
|
push %ebx
|
||||||
|
push %eax
|
||||||
# Call the main kernel function
|
# Call the main kernel function
|
||||||
call brados_main
|
call brados_main
|
||||||
|
|
||||||
|
23
arch/i586-elf/multiboot.c
Normal file
23
arch/i586-elf/multiboot.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <multiboot.h>
|
||||||
|
|
||||||
|
uint32_t multiboot_getAddress()
|
||||||
|
{
|
||||||
|
uint32_t address = 0;
|
||||||
|
__asm__(
|
||||||
|
"movl %%ebx, %0;"
|
||||||
|
:"=r"(address)
|
||||||
|
);
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t multiboot_getMagic()
|
||||||
|
{
|
||||||
|
uint32_t magic = 0;
|
||||||
|
__asm__(
|
||||||
|
"movl %%eax, %0;"
|
||||||
|
:"=r"(magic)
|
||||||
|
);
|
||||||
|
return magic;
|
||||||
|
}
|
@ -82,6 +82,26 @@ void term_setColor(struct vgastate *state, uint8_t color)
|
|||||||
state->term_color = color;
|
state->term_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test various VGA functionality
|
||||||
|
void term_test(struct vgastate *term)
|
||||||
|
{
|
||||||
|
// Test line wrapping
|
||||||
|
term_writeStr(term, "Welcome to the desert of the real. I thought what I'd do was I'd pretend I was one of those deaf mutes.\n\n");
|
||||||
|
|
||||||
|
// Test colors
|
||||||
|
term_setColor(term, make_color(VGA_COLOR_BLACK, VGA_COLOR_WHITE));
|
||||||
|
term_writeStr(term, "This text should be inverse.\n");
|
||||||
|
term_setColor(term, make_color(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_GREEN));
|
||||||
|
term_writeStr(term, "This text should be colorful.\n\n");
|
||||||
|
|
||||||
|
// Test scrolling
|
||||||
|
term_setColor(term, make_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK));
|
||||||
|
for (size_t i = 0; i < 20; i++) {
|
||||||
|
term_writeStr(term, "Printing some lines.\n");
|
||||||
|
for (volatile size_t j = 0; j < 100000000; j++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write a string to a VGA term
|
// Write a string to a VGA term
|
||||||
void term_writeStr(struct vgastate *state, const char *data)
|
void term_writeStr(struct vgastate *state, const char *data)
|
||||||
{
|
{
|
||||||
|
8
include/brados/printk.h
Normal file
8
include/brados/printk.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef __brados_printk_h__
|
||||||
|
#define __brados_printk_h__
|
||||||
|
|
||||||
|
#include <video/vga.h>
|
||||||
|
|
||||||
|
int printk(struct vgastate *term, const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int strindexof(char c, const char *str);
|
||||||
size_t strlen(const char *str);
|
size_t strlen(const char *str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
79
include/multiboot.h
Normal file
79
include/multiboot.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef __brados_multiboot_h__
|
||||||
|
#define __brados_multiboot_h__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// For more information on this structure, see:
|
||||||
|
// http://www.gnu.org/software/grub/manual/multiboot/multiboot.html
|
||||||
|
struct multiboot_header {
|
||||||
|
// Indicates the presence and validity of other fields
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
// Present if bit 0 in 'flags' is set
|
||||||
|
uint32_t mem_lower;
|
||||||
|
uint32_t mem_upper;
|
||||||
|
|
||||||
|
// Present if bit 1 in 'flags' is set
|
||||||
|
uint32_t boot_device;
|
||||||
|
|
||||||
|
// Present if bit 2 in 'flags' is set
|
||||||
|
uint32_t cmdline;
|
||||||
|
|
||||||
|
// Present if bit 3 in 'flags' is set
|
||||||
|
uint32_t mods_count;
|
||||||
|
uint32_t mods_addr;
|
||||||
|
|
||||||
|
// Present if bits 4 or 5 are present in 'flags'
|
||||||
|
// NOTE: Bits 4 and 5 are mutually exclusive. Bit 4 indicates fields
|
||||||
|
// related to a.out kernel images, while bit 5 indicated fields related
|
||||||
|
// to ELF kernel images. Since BRaDOS is an ELF kernel, the bit 5 field
|
||||||
|
// names will be used.
|
||||||
|
uint32_t shdr_num; // "tabsize" for an a.out kernel
|
||||||
|
uint32_t shdr_size; // "strsize" for an a.out kernel
|
||||||
|
uint32_t shdr_addr; // "addr" for an a.out kernel
|
||||||
|
uint32_t shdr_shndx; // "reserved" for an a.out kernel
|
||||||
|
|
||||||
|
// Present if bit 6 in 'flags' is set
|
||||||
|
uint32_t mmap_length;
|
||||||
|
uint32_t mmap_addr;
|
||||||
|
|
||||||
|
// Present if bit 7 in 'flags' is set
|
||||||
|
uint32_t drives_length;
|
||||||
|
uint32_t drives_addr;
|
||||||
|
|
||||||
|
// Present if bit 8 in 'flags' is set
|
||||||
|
uint32_t config_table;
|
||||||
|
|
||||||
|
// Present if bit 9 in 'flags' is set
|
||||||
|
uint32_t boot_loader_name;
|
||||||
|
|
||||||
|
// Present if bit 10 in 'flags' is set
|
||||||
|
uint32_t apm_table;
|
||||||
|
|
||||||
|
// Present if bit 11 in 'flags' is set
|
||||||
|
uint32_t vbe_control_info;
|
||||||
|
uint32_t vbe_mode_info;
|
||||||
|
uint16_t vbe_mode;
|
||||||
|
uint16_t vbe_interface_seg;
|
||||||
|
uint16_t vbe_interface_off;
|
||||||
|
uint16_t vbe_interface_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_mmap {
|
||||||
|
uint32_t size;
|
||||||
|
uint64_t base_addr;
|
||||||
|
uint64_t length;
|
||||||
|
uint32_t type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_mod {
|
||||||
|
uint32_t mod_start;
|
||||||
|
uint32_t mod_end;
|
||||||
|
uint32_t string;
|
||||||
|
uint32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t multiboot_getAddress();
|
||||||
|
uint32_t multiboot_getMagic();
|
||||||
|
|
||||||
|
#endif
|
@ -37,28 +37,14 @@ enum vga_color
|
|||||||
VGA_COLOR_WHITE = 15
|
VGA_COLOR_WHITE = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a VGA color
|
|
||||||
uint8_t make_color(enum vga_color fg, enum vga_color bg);
|
uint8_t make_color(enum vga_color fg, enum vga_color bg);
|
||||||
|
|
||||||
// Create a VGA character
|
|
||||||
uint16_t make_vgaEntry(char c, uint8_t color);
|
uint16_t make_vgaEntry(char c, uint8_t color);
|
||||||
|
|
||||||
// Initialize a VGA term
|
|
||||||
void term_init(struct vgastate *state);
|
void term_init(struct vgastate *state);
|
||||||
|
|
||||||
// Write a character to a VGA term
|
|
||||||
void term_putChar(struct vgastate *state, char c);
|
void term_putChar(struct vgastate *state, char c);
|
||||||
|
|
||||||
// Place a character in a VGA term's buffer
|
|
||||||
void term_putEntryAt(struct vgastate *state, char c, uint8_t color, size_t x, size_t y);
|
void term_putEntryAt(struct vgastate *state, char c, uint8_t color, size_t x, size_t y);
|
||||||
|
|
||||||
// Scroll the term down 1 line
|
|
||||||
void term_scroll(struct vgastate *state);
|
void term_scroll(struct vgastate *state);
|
||||||
|
|
||||||
// Set VGA term color
|
|
||||||
void term_setColor(struct vgastate *state, uint8_t color);
|
void term_setColor(struct vgastate *state, uint8_t color);
|
||||||
|
void term_test(struct vgastate *term);
|
||||||
// Write a string to a VGA term
|
|
||||||
void term_writeStr(struct vgastate *state, const char *data);
|
void term_writeStr(struct vgastate *state, const char *data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,36 +1,20 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <brados/printk.h>
|
||||||
#include <brados/string.h>
|
#include <brados/string.h>
|
||||||
#include <video/vga.h>
|
#include <video/vga.h>
|
||||||
|
#include <multiboot.h>
|
||||||
|
|
||||||
// Make sure we are using the right compiler
|
// Make sure we are using the right compiler
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#error "You are using the wrong compiler."
|
#error "You are using the wrong compiler."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Test various VGA functionality
|
|
||||||
void vgaTests(struct vgastate *term)
|
|
||||||
{
|
|
||||||
// Test line wrapping
|
|
||||||
term_writeStr(term, "Welcome to the desert of the real. I thought what I'd do was I'd pretend I was one of those deaf mutes.\n\n");
|
|
||||||
|
|
||||||
// Test colors
|
|
||||||
term_setColor(term, make_color(VGA_COLOR_BLACK, VGA_COLOR_WHITE));
|
|
||||||
term_writeStr(term, "This text should be inverse.\n");
|
|
||||||
term_setColor(term, make_color(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_GREEN));
|
|
||||||
term_writeStr(term, "This text should be colorful.\n\n");
|
|
||||||
|
|
||||||
// Test scrolling
|
|
||||||
term_setColor(term, make_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK));
|
|
||||||
for (size_t i = 0; i < 20; i++) {
|
|
||||||
term_writeStr(term, "Printing some lines.\n");
|
|
||||||
for (volatile size_t j = 0; j < 100000000; j++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main kernel function
|
// Main kernel function
|
||||||
void brados_main()
|
void brados_main(uint32_t multiMagic, uint32_t multiAddr)
|
||||||
{
|
{
|
||||||
|
// Initialize VGA terminal
|
||||||
struct vgastate term;
|
struct vgastate term;
|
||||||
term_init(&term);
|
term_init(&term);
|
||||||
|
|
||||||
@ -38,7 +22,21 @@ void brados_main()
|
|||||||
term_writeStr(&term, "Welcome to BRaDOS!\n");
|
term_writeStr(&term, "Welcome to BRaDOS!\n");
|
||||||
term_writeStr(&term, "written by L. Bradley LaBoon\n\n");
|
term_writeStr(&term, "written by L. Bradley LaBoon\n\n");
|
||||||
|
|
||||||
vgaTests(&term);
|
// VGA tests
|
||||||
|
//term_test(&term);
|
||||||
|
|
||||||
|
// Get multiboot info
|
||||||
|
printk(&term, "Multiboot value: %x\n", multiMagic);
|
||||||
|
if (multiMagic != 0x2BADB002) {
|
||||||
|
term_writeStr(&term, "Error! Multiboot header not present. Quitting.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printk(&term, "Multiboot address: %x\n", multiAddr);
|
||||||
|
struct multiboot_header *multiHead = (struct multiboot_header *) multiAddr;
|
||||||
|
printk(&term, "Flags: %x\nMem Lower: %x\nMem Upper: %x\n", multiHead->flags, multiHead->mem_lower, multiHead->mem_upper);
|
||||||
|
char *bootName = (char *) multiHead->boot_loader_name;
|
||||||
|
printk(&term, "Boot loader: %s\n\n", bootName);
|
||||||
|
|
||||||
|
// Done
|
||||||
term_writeStr(&term, "Done.");
|
term_writeStr(&term, "Done.");
|
||||||
}
|
}
|
||||||
|
76
kernel/printk.c
Normal file
76
kernel/printk.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <brados/printk.h>
|
||||||
|
#include <brados/string.h>
|
||||||
|
#include <video/vga.h>
|
||||||
|
|
||||||
|
const char *BASE16 = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
static int printNum(struct vgastate *term, unsigned int num, unsigned int base)
|
||||||
|
{
|
||||||
|
int numPrinted = 0;
|
||||||
|
int digit = num % base;
|
||||||
|
if (num >= base)
|
||||||
|
numPrinted += printNum(term, num / base, base);
|
||||||
|
term_putChar(term, BASE16[digit]);
|
||||||
|
numPrinted++;
|
||||||
|
return numPrinted;
|
||||||
|
}
|
||||||
|
|
||||||
|
int printk(struct vgastate *term, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
int numPrinted = 0;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < strlen(fmt); i++) {
|
||||||
|
if (fmt[i] == '%') {
|
||||||
|
int d;
|
||||||
|
unsigned int x;
|
||||||
|
char *s;
|
||||||
|
switch (fmt[i+1]) {
|
||||||
|
case '%':
|
||||||
|
term_putChar(term, '%');
|
||||||
|
numPrinted++;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
term_putChar(term, (char) va_arg(args, int));
|
||||||
|
numPrinted++;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
d = va_arg(args, int);
|
||||||
|
if (d < 0) {
|
||||||
|
term_putChar(term, '-');
|
||||||
|
numPrinted++;
|
||||||
|
d *= -1;
|
||||||
|
}
|
||||||
|
numPrinted += printNum(term, (unsigned int) d, 10);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
s = va_arg(args, char *);
|
||||||
|
term_writeStr(term, s);
|
||||||
|
numPrinted += strlen(s);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
x = va_arg(args, unsigned int);
|
||||||
|
term_writeStr(term, "0x");
|
||||||
|
numPrinted += 2;
|
||||||
|
numPrinted += printNum(term, x, 16);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
term_putChar(term, fmt[i+1]);
|
||||||
|
numPrinted++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
term_putChar(term, fmt[i]);
|
||||||
|
numPrinted++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
return numPrinted;
|
||||||
|
}
|
12
lib/string.c
12
lib/string.c
@ -2,6 +2,18 @@
|
|||||||
|
|
||||||
#include <brados/string.h>
|
#include <brados/string.h>
|
||||||
|
|
||||||
|
// Find the first instance of c in str
|
||||||
|
// Returns -1 if c is not found
|
||||||
|
int strindexof(char c, const char *str)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < strlen(str); i++) {
|
||||||
|
if (str[i] == c)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the length of a string
|
// Find the length of a string
|
||||||
size_t strlen(const char *str)
|
size_t strlen(const char *str)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user