Give up on RYOB, use mb instead
This commit is contained in:
parent
ac1d0714a0
commit
12193e7920
22 changed files with 475 additions and 0 deletions
54
Makefile
Normal file
54
Makefile
Normal file
|
@ -0,0 +1,54 @@
|
|||
ASM ?= nasm
|
||||
CC := i686-elf-gcc
|
||||
GDB := i686-elf-gdb
|
||||
LD := i686-elf-ld
|
||||
|
||||
C_FILES = $(shell find src/ -type f -name '*.c')
|
||||
CO_FILES = $(patsubst src/%.c, obj/%.o, $(C_FILES))
|
||||
ASM_FILES = $(shell find src/kernel/ -type f -name '*.asm')
|
||||
AO_FILES = $(patsubst src/kernel/%.asm, obj/kernel/%.o, $(ASM_FILES))
|
||||
|
||||
KERNEL_O_FILES = ${CO_FILES} ${AO_FILES}
|
||||
|
||||
iso: bin/shade.iso
|
||||
|
||||
obj/boot.o: src/boot.asm
|
||||
$(ASM) -felf32 $^ -o $@
|
||||
|
||||
bin/shade.bin: obj/boot.o ${KERNEL_O_FILES}
|
||||
mkdir -p bin
|
||||
$(CC) -T src/linker.ld -ffreestanding -O2 -nostdlib $^ -o $@ -lgcc
|
||||
grub-file --is-x86-multiboot bin/shade.bin
|
||||
|
||||
bin/shade.iso: bin/shade.bin
|
||||
mkdir -p isodir/boot/grub
|
||||
cp bin/shade.bin isodir/boot/shade.bin
|
||||
cp src/iso/grub.cfg isodir/boot/grub/grub.cfg
|
||||
grub-mkrescue -o bin/shade.iso isodir
|
||||
rm -rf isodir
|
||||
|
||||
obj/%.o: src/%.c
|
||||
mkdir -p "$(@D)"
|
||||
$(CC) -ffreestanding -O2 -Wall -Wextra -c $< -o $@
|
||||
|
||||
obj/%.o: src/%.asm
|
||||
mkdir -p "$(@D)"
|
||||
$(ASM) -f elf $< -o $@
|
||||
|
||||
|
||||
run: clean bin/shade.iso
|
||||
qemu-system-x86_64 -hdd bin/shade.iso
|
||||
|
||||
debug: clean bin/shade.iso bin/shade.bin
|
||||
qemu-system-x86_64 -s -S -hdd bin/shade.iso &
|
||||
${GDB} os-image.bin -ex "symbol-file bin/shade.bin" -ex "target remote localhost:1234"
|
||||
|
||||
|
||||
clean:
|
||||
find obj -type f -name '*.o' -exec rm {} +
|
||||
find obj -type f -name '*.bin' -exec rm {} +
|
||||
find bin -type f -name '*.o' -exec rm {} +
|
||||
find bin -type f -name '*.bin' -exec rm {} +
|
||||
find . -type f -name '*.dis' -exec rm {} +
|
||||
rm -f kernel.elf
|
||||
rm -rf isodir
|
BIN
bin/shade.bin
Executable file
BIN
bin/shade.bin
Executable file
Binary file not shown.
BIN
bin/shade.iso
Normal file
BIN
bin/shade.iso
Normal file
Binary file not shown.
BIN
obj/boot.o
Normal file
BIN
obj/boot.o
Normal file
Binary file not shown.
BIN
obj/kernel/kernel.o
Normal file
BIN
obj/kernel/kernel.o
Normal file
Binary file not shown.
BIN
obj/kernel/platform/drivers/ports.o
Normal file
BIN
obj/kernel/platform/drivers/ports.o
Normal file
Binary file not shown.
BIN
obj/kernel/print.o
Normal file
BIN
obj/kernel/print.o
Normal file
Binary file not shown.
BIN
obj/kernel/strings.o
Normal file
BIN
obj/kernel/strings.o
Normal file
Binary file not shown.
BIN
obj/kernel/util.o
Normal file
BIN
obj/kernel/util.o
Normal file
Binary file not shown.
38
src/boot.asm
Normal file
38
src/boot.asm
Normal file
|
@ -0,0 +1,38 @@
|
|||
; Declare constants for the multiboot header.
|
||||
MBALIGN equ 1 << 0 ; align loaded modules on page boundaries
|
||||
MEMINFO equ 1 << 1 ; provide memory map
|
||||
FLAGS equ MBALIGN | MEMINFO ; this is the Multiboot 'flag' field
|
||||
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
|
||||
CHECKSUM equ -(MAGIC + FLAGS) ; checksum of above, to prove we are multiboot
|
||||
|
||||
section .multiboot
|
||||
align 4
|
||||
dd MAGIC
|
||||
dd FLAGS
|
||||
dd CHECKSUM
|
||||
|
||||
section .bss
|
||||
align 16
|
||||
|
||||
stack_bottom:
|
||||
resb 16384
|
||||
stack_top:
|
||||
|
||||
; _start = entry to kernel
|
||||
; Since the bootloader will be gone, it doesn't make sense to return from this
|
||||
section .text
|
||||
|
||||
global _start:function (_start.end - _start)
|
||||
_start:
|
||||
; 32bit protected mode, no int, no paging
|
||||
mov esp, stack_top ; Initialize stack
|
||||
|
||||
extern kmain
|
||||
call kmain
|
||||
|
||||
cli ; Turn off interrupts in case they are on
|
||||
.hang:
|
||||
hlt ; Totally halt the cpu
|
||||
jmp .hang ; If the cpu un-halts for some reason, halt again
|
||||
|
||||
.end:
|
3
src/iso/grub.cfg
Normal file
3
src/iso/grub.cfg
Normal file
|
@ -0,0 +1,3 @@
|
|||
menuentry "shadeOS Dev Build" {
|
||||
multiboot /boot/shade.bin
|
||||
}
|
55
src/kernel/kernel.c
Normal file
55
src/kernel/kernel.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include "./platform/drivers/ports.h"
|
||||
#include "print.h"
|
||||
#include "./platform/types.h"
|
||||
//#include "./platform/interrupts/int.h"
|
||||
|
||||
void dummy_test_entrypoint() {}
|
||||
|
||||
void kernel_welcome() {
|
||||
print_str("Welcome to ");
|
||||
print_set_color(PRINT_COLOR_CYAN, PRINT_COLOR_BLACK);
|
||||
print_str("Shade");
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
print_str("!\n");
|
||||
|
||||
print_str("shadeOS kernel version ");
|
||||
|
||||
print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK);
|
||||
print_str("0.2.2");
|
||||
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
print_newline();
|
||||
|
||||
print_str("Running on ");
|
||||
|
||||
print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK);
|
||||
print_str("shade-development");
|
||||
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
|
||||
print_newline();
|
||||
}
|
||||
|
||||
// kMain
|
||||
void kmain() {
|
||||
// Initialize screen buffer
|
||||
struct Char* buffer = (struct Char*) 0xb8000;
|
||||
|
||||
clear_all(); // Clear screen
|
||||
set_cursor_pos(0, 0); // Set cursor position
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set print color
|
||||
|
||||
// welcome messages
|
||||
kernel_msg_ok("Initialized display successfully\n");
|
||||
kernel_welcome();
|
||||
|
||||
print_str("Copyright (c) e3team 2022. All rights reserved.\n");
|
||||
print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n");
|
||||
print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n");
|
||||
/*
|
||||
idt_init();
|
||||
kernel_msg_ok("Interrupts initialized");
|
||||
|
||||
__asm__ __volatile__("int $2");
|
||||
*/
|
||||
}
|
26
src/kernel/platform/drivers/ports.c
Normal file
26
src/kernel/platform/drivers/ports.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Read 1 byte from specified port
|
||||
*/
|
||||
unsigned char port_byte_in(unsigned short port) {
|
||||
unsigned char result;
|
||||
// source and dest are backwards.
|
||||
// "=a (result)" set the C variable to the value of register e'a'x
|
||||
// '"d" (port) map the C variable port into e'd'x register
|
||||
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
|
||||
}
|
||||
|
||||
void port_byte_out(unsigned short port, unsigned char data) {
|
||||
// both regs are C vars, nothing is returned, so no '=' in asm syntax
|
||||
// comma because two vars in input area and none in return area
|
||||
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
|
||||
}
|
||||
|
||||
unsigned short port_word_in(unsigned short port) {
|
||||
unsigned short result;
|
||||
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void port_word_out(unsigned short port, unsigned short data) {
|
||||
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
|
||||
}
|
4
src/kernel/platform/drivers/ports.h
Normal file
4
src/kernel/platform/drivers/ports.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
unsigned char port_byte_in(unsigned short port);
|
||||
void port_byte_out(unsigned short port, unsigned char data);
|
||||
unsigned short port_word_in(unsigned short port);
|
||||
void port_word_out(unsigned short port, unsigned short data);
|
18
src/kernel/platform/types.h
Normal file
18
src/kernel/platform/types.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef int i32;
|
||||
typedef unsigned short u16;
|
||||
typedef short i16;
|
||||
typedef unsigned char u8;
|
||||
typedef char i8;
|
||||
|
||||
#define high16(i32) (i32 & 0xffff)
|
||||
#define low16(i32) ((i32>>16) & 0xffff)
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NULL 0
|
||||
|
||||
#endif
|
110
src/kernel/print.c
Normal file
110
src/kernel/print.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
#include "print.h"
|
||||
#include "./platform/drivers/ports.h"
|
||||
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
char color = PRINT_COLOR_WHITE | PRINT_COLOR_BLACK << 4;
|
||||
|
||||
void clear_row(int row) {
|
||||
struct Char* buffer = (struct Char*) 0xb8000;
|
||||
|
||||
struct Char empty = (struct Char) {
|
||||
character: ' ',
|
||||
color: color,
|
||||
};
|
||||
|
||||
for (int x = 0; x < NUM_COLS; x++) {
|
||||
buffer[x + NUM_COLS * row] = empty;
|
||||
}
|
||||
set_cursor_pos(col, row);
|
||||
}
|
||||
|
||||
void clear_all() {
|
||||
for (int i = 0; i < NUM_ROWS; i++) {
|
||||
clear_row(i);
|
||||
}
|
||||
set_cursor_pos(col, row);
|
||||
}
|
||||
|
||||
void print_newline() {
|
||||
struct Char* buffer = (struct Char*) 0xb8000;
|
||||
|
||||
col = 0;
|
||||
|
||||
if (row < NUM_ROWS - 1) {
|
||||
row++;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int row = 1; row < NUM_ROWS; row++) {
|
||||
for (int col = 0; col < NUM_COLS; col++) {
|
||||
struct Char character = buffer[col + NUM_COLS * row];
|
||||
buffer[col + NUM_COLS * (row - 1)] = character;
|
||||
}
|
||||
}
|
||||
|
||||
clear_row(NUM_COLS - 1);
|
||||
set_cursor_pos(col, row);
|
||||
}
|
||||
|
||||
void print_char(char character) {
|
||||
struct Char* buffer = (struct Char*) 0xb8000;
|
||||
|
||||
if (character == '\n') {
|
||||
print_newline();
|
||||
return;
|
||||
}
|
||||
|
||||
if (col > NUM_COLS) {
|
||||
print_newline();
|
||||
}
|
||||
|
||||
struct Char cr = (struct Char) {
|
||||
character: character,
|
||||
color: color,
|
||||
};
|
||||
buffer[col + NUM_COLS * row] = cr;
|
||||
|
||||
col++;
|
||||
set_cursor_pos(col, row);
|
||||
}
|
||||
|
||||
void print_str(char* str) {
|
||||
for (int i = 0; 1; i++) {
|
||||
char character = (char) str[i];
|
||||
|
||||
if (character == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
print_char(character);
|
||||
}
|
||||
}
|
||||
|
||||
void print_set_color(char foreground, char background) {
|
||||
color = foreground + (background << 4);
|
||||
}
|
||||
|
||||
void set_cursor_pos(int col, int row) {
|
||||
int offset = col + NUM_COLS * row;
|
||||
port_byte_out(REG_SCREEN_CTRL, 14);
|
||||
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
|
||||
port_byte_out(REG_SCREEN_CTRL, 15);
|
||||
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset & 0xff));
|
||||
}
|
||||
|
||||
void kernel_msg_ok(char* msg) {
|
||||
char ok_p1[] = "[ ";
|
||||
char ok_p2[] = "OK ";
|
||||
char ok_p3[] = "] ";
|
||||
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
print_str(ok_p1);
|
||||
|
||||
print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK);
|
||||
print_str(ok_p2);
|
||||
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
print_str(ok_p3);
|
||||
print_str(msg);
|
||||
}
|
44
src/kernel/print.h
Normal file
44
src/kernel/print.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef PRINT_H
|
||||
#define PRINT_H
|
||||
#define REG_SCREEN_CTRL 0x3d4
|
||||
#define REG_SCREEN_DATA 0x3d5
|
||||
|
||||
enum {
|
||||
PRINT_COLOR_BLACK = 0,
|
||||
PRINT_COLOR_BLUE = 1,
|
||||
PRINT_COLOR_GREEN = 2,
|
||||
PRINT_COLOR_CYAN = 3,
|
||||
PRINT_COLOR_RED = 4,
|
||||
PRINT_COLOR_MAGENTA = 5,
|
||||
PRINT_COLOR_BROWN = 6,
|
||||
PRINT_COLOR_LIGHT_GRAY = 7,
|
||||
PRINT_COLOR_DARK_GRAY = 8,
|
||||
PRINT_COLOR_LIGHT_BLUE = 9,
|
||||
PRINT_COLOR_LIGHT_GREEN = 10,
|
||||
PRINT_COLOR_LIGHT_CYAN = 11,
|
||||
PRINT_COLOR_LIGHT_RED = 12,
|
||||
PRINT_COLOR_PINK = 13,
|
||||
PRINT_COLOR_YELLOW = 14,
|
||||
PRINT_COLOR_WHITE = 15,
|
||||
};
|
||||
|
||||
const static int NUM_COLS = 80;
|
||||
const static int NUM_ROWS = 25;
|
||||
|
||||
struct Char {
|
||||
char character;
|
||||
char color;
|
||||
};
|
||||
|
||||
void clear_row(int row);
|
||||
void clear_all();
|
||||
|
||||
void print_newline();
|
||||
void print_char(char character);
|
||||
void print_set_color(char foreground, char background);
|
||||
void print_str(char* str);
|
||||
|
||||
void set_cursor_pos(int col, int row);
|
||||
|
||||
void kernel_msg_ok(char* msg);
|
||||
#endif
|
48
src/kernel/strings.c
Normal file
48
src/kernel/strings.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "strings.h"
|
||||
#include "./platform/types.h"
|
||||
|
||||
void itoa(int n, char str[]) {
|
||||
int i, sign;
|
||||
if ((sign = n) < 0) n = -n;
|
||||
i = 0;
|
||||
do {
|
||||
str[i++] = n % 10 + '0';
|
||||
} while ((n /= 10) > 0);
|
||||
|
||||
if (sign < 0) str[i++] = '-';
|
||||
str[i] = '\0';
|
||||
|
||||
strrev(str);
|
||||
}
|
||||
|
||||
/* K&R */
|
||||
void strrev(char s[]) {
|
||||
int c, i, j;
|
||||
for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
|
||||
c = s[i];
|
||||
s[i] = s[j];
|
||||
s[j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* K&R */
|
||||
int strlen(char s[]) {
|
||||
int i = 0;
|
||||
while (s[i] != '\0') ++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
char* strcpy(char* strDest, const char* strSrc) {
|
||||
if ( (strDest == NULL) || (strSrc == NULL) ) {
|
||||
return NULL;
|
||||
}
|
||||
char* strDestCopy = strDest;
|
||||
while ((*strDest++=*strSrc++)!='\0');
|
||||
return strDestCopy;
|
||||
}
|
||||
|
||||
char* strcnc(char* str1, char* str2) {
|
||||
char* str_dest;
|
||||
strcpy(str_dest, str1);
|
||||
strcpy(str_dest, str2);
|
||||
}
|
10
src/kernel/strings.h
Normal file
10
src/kernel/strings.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef STRINGS_H
|
||||
#define STRINGS_H
|
||||
|
||||
void itoa(int n, char str[]);
|
||||
void strrev(char s[]);
|
||||
int strlen(char s[]);
|
||||
char* strcpy(char* strDest, const char* strSrc);
|
||||
char* strcnc(char* str1, char* str2);
|
||||
|
||||
#endif
|
25
src/kernel/util.c
Normal file
25
src/kernel/util.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "util.h"
|
||||
|
||||
void memcpy(char *source, char *dest, int nbytes) {
|
||||
int i;
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
*(dest + i) = *(source + i);
|
||||
}
|
||||
}
|
||||
|
||||
void memset(char *dest, char val, int len) {
|
||||
char *temp = (char *)dest;
|
||||
for(; len !=0; len--) *temp++ = val;
|
||||
}
|
||||
|
||||
void int_to_ascii(int n, char str[]) {
|
||||
int i, sign;
|
||||
if ((sign = n) < 0) n = -n;
|
||||
i = 0;
|
||||
do {
|
||||
str[i++] = n % 10 + '0';
|
||||
} while ((n /= 10) > 0);
|
||||
|
||||
if (sign < 0) str[i++] = '-';
|
||||
str[i] = '\0';
|
||||
}
|
8
src/kernel/util.h
Normal file
8
src/kernel/util.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
void memcpy(char *source, char *dest, int nbytes);
|
||||
void memset(char *dest, char val, int len);
|
||||
void int_to_ascii(int n, char str[]);
|
||||
|
||||
#endif
|
32
src/linker.ld
Normal file
32
src/linker.ld
Normal file
|
@ -0,0 +1,32 @@
|
|||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 1M;
|
||||
|
||||
/* MB header */
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.text)
|
||||
}
|
||||
|
||||
/* Read-only data. */
|
||||
.rodata BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
/* Read-write data (initialized) */
|
||||
.data BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
/* Read-write data (uninitialized) and stack */
|
||||
.bss BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue