Implemented initial printk. Added multiboot support.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -5,7 +5,7 @@ GNU	?= $(PREFIX)/$(ARCH)/bin/$(ARCH)
 | 
			
		||||
 | 
			
		||||
# Source files
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
	movl $stack_top, %esp
 | 
			
		||||
	
 | 
			
		||||
	# Push the multiboot information onto the stack
 | 
			
		||||
	push %ebx
 | 
			
		||||
	push %eax
 | 
			
		||||
	# Call the main kernel function
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
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>
 | 
			
		||||
 | 
			
		||||
int strindexof(char c, const char *str);
 | 
			
		||||
size_t strlen(const char *str);
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Create a VGA color
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
// Initialize a VGA term
 | 
			
		||||
void term_init(struct vgastate *state);
 | 
			
		||||
 | 
			
		||||
// Write a character to a VGA term
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
// Scroll the term down 1 line
 | 
			
		||||
void term_scroll(struct vgastate *state);
 | 
			
		||||
 | 
			
		||||
// Set VGA term color
 | 
			
		||||
void term_setColor(struct vgastate *state, uint8_t color);
 | 
			
		||||
 | 
			
		||||
// Write a string to a VGA term
 | 
			
		||||
void term_test(struct vgastate *term);
 | 
			
		||||
void term_writeStr(struct vgastate *state, const char *data);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,36 +1,20 @@
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <brados/printk.h>
 | 
			
		||||
#include <brados/string.h>
 | 
			
		||||
#include <video/vga.h>
 | 
			
		||||
#include <multiboot.h>
 | 
			
		||||
 | 
			
		||||
// Make sure we are using the right compiler
 | 
			
		||||
#if defined(__linux__)
 | 
			
		||||
#error "You are using the wrong compiler."
 | 
			
		||||
#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
 | 
			
		||||
void brados_main()
 | 
			
		||||
void brados_main(uint32_t multiMagic, uint32_t multiAddr)
 | 
			
		||||
{
 | 
			
		||||
	// Initialize VGA terminal
 | 
			
		||||
	struct vgastate term;
 | 
			
		||||
	term_init(&term);
 | 
			
		||||
	
 | 
			
		||||
@@ -38,7 +22,21 @@ void brados_main()
 | 
			
		||||
	term_writeStr(&term, "Welcome to BRaDOS!\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.");
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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>
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
size_t strlen(const char *str)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user