first commit

This commit is contained in:
Sami Samhuri 2011-03-01 21:04:06 -08:00
commit 9c18212f37
13 changed files with 403 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
src/*.o
bochs.out
src/kernel

9
bochsrc Normal file
View file

@ -0,0 +1,9 @@
megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
floppya: 1_44=/dev/loop0, status=inserted
boot: a
log: bochs.out
mouse: enabled=0
clock: sync=realtime
cpu: ips=500000

BIN
floppy.img Normal file

Binary file not shown.

6
run_bochs.sh Executable file
View file

@ -0,0 +1,6 @@
#!/bin/sh
losetup /dev/loop0 floppy.img
bochs -f bochsrc
sleep 1
losetup -d /dev/loop0

16
src/Makefile Normal file
View file

@ -0,0 +1,16 @@
SOURCES=boot.o main.o common.o monitor.o
CFLAGS=-nostdlib -nostdinc -fno-builtin -fno-stack-protector
LDFLAGS=-T link.ld
ASFLAGS=-f elf
all: $(SOURCES) link
clean:
-rm *.o kernel
link:
ld $(LDFLAGS) -o kernel $(SOURCES)
.s.o:
yasm $(ASFLAGS) $<

45
src/boot.s Normal file
View file

@ -0,0 +1,45 @@
;;
;; boot.s -- Kernel start location. Also defines multiboot header.
;; Based on Bran's kernel development tutorial file start.asm
;;
MBOOT_PAGE_ALIGN equ 1<<0 ; Load kernel and modules on a page boundary
MBOOT_MEM_INFO equ 1<<1 ; Provide your kernel with memory info
MBOOT_HEADER_MAGIC equ 0x1BADB002 ; Multiboot Magic value
;; NOTE: We do not use MBOOT_AOUT_KLUDGE. It means that GRUB does not
;; pass us a symbol table.
MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO
MBOOT_CHECKSUM equ -(MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS)
[BITS 32] ; All instructions should be 32-bit.
[GLOBAL mboot] ; Make 'mboot' accessible from C.
[EXTERN code] ; Start of the '.text' section.
[EXTERN bss] ; Start of the .bss section.
[EXTERN end] ; End of the last loadable section.
mboot:
dd MBOOT_HEADER_MAGIC ; GRUB will search for this value on each
;; 4-byte boundary in your kernel file
dd MBOOT_HEADER_FLAGS ; How GRUB should load your file / settings
dd MBOOT_CHECKSUM ; To ensure that the above values are correct
dd mboot ; Location of this descriptor
dd code ; Start of kernel '.text' (code) section.
dd bss ; End of kernel '.data' section.
dd end ; End of kernel.
dd start ; Kernel entry point (initial EIP).
[GLOBAL start] ; Kernel entry point.
[EXTERN main] ; This is the entry point of our C code
start:
push ebx ; Load multiboot header location
;; Execute the kernel:
cli ; Disable interrupts.
call main ; call our main() function.
jmp $ ; Enter an infinite loop, to stop the processor
;; executing whatever rubbish is in the memory
;; after our kernel!

36
src/common.c Normal file
View file

@ -0,0 +1,36 @@
// common.c -- Defines some global functions.
// From JamesM's kernel development tutorials.
#include "common.h"
// Write a byte out to the specified port.
void outb(u16int port, u8int value)
{
asm volatile ("outb %1, %0" : : "dN" (port), "a" (value));
}
u8int inb(u16int port)
{
u8int ret;
asm volatile("inb %1, %0" : "=a" (ret) : "dN" (port));
return ret;
}
u16int inw(u16int port)
{
u16int ret;
asm volatile ("inw %1, %0" : "=a" (ret) : "dN" (port));
return ret;
}

29
src/common.h Normal file
View file

@ -0,0 +1,29 @@
// common.h -- Defines typedefs and some global functions.
// From JamesM's kernel development tutorials.
#ifndef COMMON_H
#define COMMON_H
// Some nice typedefs, to standardise sizes across platforms.
// These typedefs are written for 32-bit X86.
typedef unsigned int u32int;
typedef int s32int;
typedef unsigned short u16int;
typedef short s16int;
typedef unsigned char u8int;
typedef char s8int;
void outb(u16int port, u8int value);
u8int inb(u16int port);
u16int inw(u16int port);
#endif

32
src/link.ld Normal file
View file

@ -0,0 +1,32 @@
/* Link.ld -- Linker script for the kernel - ensure everything goes in the */
/* Correct place. */
/* Original file taken from Bran's Kernel Development */
/* tutorials: http://www.osdever.net/bkerndev/index.php. */
ENTRY(start)
SECTIONS
{
.text 0x100000 :
{
code = .; _code = .; __code = .;
*(.text)
. = ALIGN(4096);
}
.data :
{
data = .; _data = .; __data = .;
*(.data)
*(.rodata)
. = ALIGN(4096);
}
.bss :
{
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}

18
src/main.c Normal file
View file

@ -0,0 +1,18 @@
// main.c -- Defines the C-code kernel entry point, calls initialisation routines.
// Made for JamesM's tutorials
#include "monitor.h"
int main(struct multiboot *mboot_ptr)
{
monitor_clear();
monitor_write("Hello, world!");
monitor_newline();
monitor_write_dec(42);
monitor_newline();
monitor_write_hex(0xdeadbeef);
return 0xdeadbeef;
}

174
src/monitor.c Normal file
View file

@ -0,0 +1,174 @@
#include "monitor.h"
// The VGA framebuffer starts at 0xB8000.
u16int *video_memory = (u16int *)0xB8000;
u8int cursor_x = 0;
u8int cursor_y = 0;
// Updates the hardware cursor.
static void move_cursor()
{
// The screen is 80 characters wide...
u16int cursorLocation = cursor_y * 80 + cursor_x;
outb(0x3D4, 14);
// Tell the VGA board we are setting the high cursor byte.
outb(0x3D5, cursorLocation >> 8);
// Send the high cursor byte.
outb(0x3D4, 15);
// Tell the VGA board we are setting the low cursor byte.
outb(0x3D5, cursorLocation);
// Send the low cursor byte.
}
// Scrolls the text on the screen up by one line.
static void scroll()
{
// Get a space character with the default colour attributes.
u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
u16int blank = 0x20 /* space */ | (attributeByte << 8);
// Row 25 is the end, this means we need to scroll up
if (cursor_y >= 25) {
// Move the current text chunk that makes up the screen
// back in the buffer by a line
int i;
for (i = 0*80; i < 24*80; i++) {
video_memory[i] = video_memory[i+80];
}
// The last line should now be blank. Do this by writing
// 80 spaces to it.
for (i = 24*80; i < 25*80; i++) {
video_memory[i] = blank;
}
// The cursor should now be on the last line.
cursor_y = 24;
}
}
// Writes a single character out to the screen.
void monitor_put(char c)
{
// The background colour is black (0), the foreground is white (15).
u8int backColour = 0;
u8int foreColour = 15;
// The attribute byte is made up of two nibbles - the lower being the
// foreground colour, and the upper the background colour.
u8int attributeByte = (backColour << 4) | (foreColour & 0x0F);
// The attribute byte is the top 8 bits of the word we have to send to the
// VGA board.
u16int attribute = attributeByte << 8;
u16int *location;
// Handle a backspace, by moving the cursor back one space
if (c == 0x08 && cursor_x) {
cursor_x--;
}
// Handle a tab by increasing the cursor's X, but only to a point
// where it is divisible by 8.
else if (c == 0x09) {
cursor_x = (cursor_x+8) & ~(8-1);
}
// Handle carriage return
else if (c == '\r') {
cursor_x = 0;
}
// Handle newline by moving cursor back to left and increasing the row
else if (c == '\n') {
cursor_x = 0;
cursor_y++;
}
// Handle any other printable character.
else if(c >= ' ') {
location = video_memory + (cursor_y*80 + cursor_x);
*location = c | attribute;
cursor_x++;
}
// Check if we need to insert a new line because we have reached the end
// of the screen.
if (cursor_x >= 80) {
cursor_x = 0;
cursor_y ++;
}
// Scroll the screen if needed.
scroll();
// Move the hardware cursor.
move_cursor();
}
// Clears the screen, by copying lots of spaces to the framebuffer.
void monitor_clear()
{
// Make an attribute byte for the default colours
u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
u16int blank = 0x20 /* space */ | (attributeByte << 8);
int i;
for (i = 0; i < 80*25; i++) {
video_memory[i] = blank;
}
// Move the hardware cursor back to the start.
cursor_x = 0;
cursor_y = 0;
move_cursor();
}
// Outputs a null-terminated ASCII string to the monitor.
void monitor_write(char *c)
{
int i = 0;
while (c[i]) {
monitor_put(c[i++]);
}
}
void monitor_newline()
{
while (cursor_x > 0) monitor_put(' ');
}
void monitor_write_hex(u32int n)
{
static char hex_chars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };
u32int mask = 0xf0000000;
int i = 28;
while (i >= 0) {
monitor_put(hex_chars[(n & mask) >> i]);
mask >>= 4;
i -= 4;
}
}
u32int pow(base, exp)
{
u32int n = base;
if (exp == 0) return 1;
while (exp > 1) {
n *= base;
exp--;
}
return n;
}
void monitor_write_dec(u32int n)
{
static char dec_chars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
int i = 7;
while (i >= 0) {
monitor_put(dec_chars[(n / pow(10, i--)) % 10]);
}
}

27
src/monitor.h Normal file
View file

@ -0,0 +1,27 @@
// monitor.h -- Defines the interface for monitor.h
// From JamesM's kernel development tutorials.
#ifndef MONITOR_H
#define MONITOR_H
#include "common.h"
// Write a single character out to the screen.
void monitor_put(char c);
// Clear the screen to all black.
void monitor_clear();
// Output a null-terminated ASCII string to the monitor.
void monitor_write(char *c);
// Move the cursor to the next line
void monitor_newline();
// Output a number to the screen in hexadecimal notation.
void monitor_write_hex(u32int n);
// Output a number to the screen in decimal notation.
void monitor_write_dec(u32int n);
#endif // MONITOR_H

8
update_image.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/sh
losetup /dev/loop0 floppy.img
mount /dev/loop0 /mnt
cp src/kernel /mnt/kernel
sleep 1
umount /mnt
losetup -d /dev/loop0