Give up on RYOB, use mb instead
This commit is contained in:
parent
ac1d0714a0
commit
12193e7920
|
@ -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
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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:
|
|
@ -0,0 +1,3 @@
|
|||
menuentry "shadeOS Dev Build" {
|
||||
multiboot /boot/shade.bin
|
||||
}
|
|
@ -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");
|
||||
*/
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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);
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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';
|
||||
}
|
|
@ -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
|
|
@ -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 New Issue