This commit is contained in:
parent
dc17550ed5
commit
915490fa24
21
src/Makefile
21
src/Makefile
|
@ -7,13 +7,14 @@
|
|||
# Desc: Project Makefile #
|
||||
#----------------------------------------------------------------------------#
|
||||
|
||||
CC_NAME="/opt/cross-cc/bin/x86_64-elf-gcc"
|
||||
CWARNS=-Wall -Wextra -Werror
|
||||
CCNAME="/opt/cross-cc/bin/x86_64-elf-gcc"
|
||||
CWARNS=-Wall -Wextra -Werror -pedantic
|
||||
CLDSCR=-T kernel.ld
|
||||
CFLAGS=-nostdlib -ffreestanding -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2
|
||||
CINCLUDES=-I./kaleid
|
||||
CDEFINES=
|
||||
|
||||
CC=$(CC_NAME) $(CWARNS) $(CFLAGS) $(CDEFINES) $(CINCLUDES)
|
||||
CC=$(CCNAME) $(CWARNS) $(CLDSCR) $(CFLAGS) $(CDEFINES) $(CINCLUDES)
|
||||
|
||||
ASM=nasm
|
||||
ASMFLAGS=
|
||||
|
@ -53,14 +54,14 @@ testing: bootloader pseudo_kern
|
|||
|
||||
COBJDIR=$(OBJDIR)/$(COMMDIR)
|
||||
|
||||
COMM_DEPS=$(COMMDIR)/common.h $(COMMDIR)/assert.h $(COMMDIR)/atomic.h $(COMMDIR)/config.h \
|
||||
COMMDEPS=$(COMMDIR)/common.h $(COMMDIR)/assert.h $(COMMDIR)/atomic.h $(COMMDIR)/config.h \
|
||||
$(COMMDIR)/status.h
|
||||
|
||||
COBJECTS=$(COBJDIR)/lib/string.o
|
||||
|
||||
common: common.lib.string.c $(COMM_DEPS)
|
||||
common: common.lib.string.c $(COMMDEPS)
|
||||
|
||||
common.lib.string.c: $(COMMDIR)/lib/string.c $(COMM_DEPS)
|
||||
common.lib.string.c: $(COMMDIR)/lib/string.c $(COMMDEPS)
|
||||
$(CC) -c $(COMMDIR)/lib/string.c -o $(OBJDIR)/$(COMMDIR)/lib/string.o
|
||||
|
||||
#----------------------------------------------------------------------------#
|
||||
|
@ -68,7 +69,7 @@ common.lib.string.c: $(COMMDIR)/lib/string.c $(COMM_DEPS)
|
|||
|
||||
KOBJDIR=$(OBJDIR)/$(KERNDIR)
|
||||
|
||||
KERN_DEPS=$(COMM_DEPS) $(KERNDIR)/init.h $(KERNDIR)/io/terminal.h $(KERNDIR)/io/ports.h
|
||||
KERNDEPS=$(COMMDEPS) $(KERNDIR)/init.h $(KERNDIR)/io/terminal.h $(KERNDIR)/io/ports.h
|
||||
|
||||
kernel: common kernel.io.terminal.c kernel.init.c kernel.io.ports.c
|
||||
$(CC) -o $(BINDIR)/kaleid-kernel.elf \
|
||||
|
@ -76,13 +77,13 @@ kernel: common kernel.io.terminal.c kernel.init.c kernel.io.ports.c
|
|||
$(KOBJDIR)/io/terminal.o $(KOBJDIR)/io/ports.o
|
||||
|
||||
|
||||
kernel.init.c: $(KERNDIR)/init.c $(KERN_DEPS)
|
||||
kernel.init.c: $(KERNDIR)/init.c $(KERNDEPS)
|
||||
$(CC) -c $(KERNDIR)/init.c -o $(KOBJDIR)/init.o
|
||||
|
||||
kernel.io.ports.c: $(KERNDIR)/io/ports.c $(KERN_DEPS)
|
||||
kernel.io.ports.c: $(KERNDIR)/io/ports.c $(KERNDEPS)
|
||||
$(CC) -c $(KERNDIR)/io/ports.c -o $(KOBJDIR)/io/ports.o
|
||||
|
||||
kernel.io.terminal.c: $(KERNDIR)/io/terminal.c $(KERN_DEPS)
|
||||
kernel.io.terminal.c: $(KERNDIR)/io/terminal.c $(KERNDEPS)
|
||||
$(CC) -c $(KERNDIR)/io/terminal.c -o $(KOBJDIR)/io/terminal.o
|
||||
|
||||
|
||||
|
|
|
@ -54,7 +54,8 @@ GDT64:
|
|||
NULL_SELECTOR: ;; null selector within 64 bits
|
||||
dw GDT_LENGTH ; limit of GDT
|
||||
dw GDT64 ; linear address of GDT
|
||||
dd 0x0
|
||||
dd 0x0 ;
|
||||
|
||||
CODE_SELECTOR: ;; 32-bit code selector (ring 0)
|
||||
dw 0x0FFFF ; Segment Limit
|
||||
db 0x0, 0x0, 0x0 ; Base Address
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ;
|
||||
; (x86_64 architecture only) ;
|
||||
;=----------------------------------------------------------------------------=;
|
||||
|
||||
[BITS 16]
|
||||
|
||||
disable_cursor:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ;
|
||||
; (x86_64 architecture only) ;
|
||||
;=----------------------------------------------------------------------------=;
|
||||
|
||||
[BITS 64]
|
||||
|
||||
clear:
|
||||
|
|
|
@ -79,8 +79,8 @@ go:
|
|||
|
||||
;; INIT STACK
|
||||
cli
|
||||
mov ax, STACK_SEG ; Init the staaaaaack
|
||||
mov ss, ax ; Continue init the staaaaaaaack
|
||||
mov ax, STACK_SEG ; Init the stack
|
||||
mov ss, ax ; Continue init the stack
|
||||
mov sp, STACK_OFF ; Ok man, the stack is in 4K :O
|
||||
sti
|
||||
mov bp, (0x7c0-STACK_SEG) << 4 ; Correct bp (the disk description table)
|
||||
|
@ -117,7 +117,7 @@ load_root:
|
|||
mov di, BUFFER_SEG ; Set the extra segment to the disk buffer
|
||||
mov es, di
|
||||
mov di, BUFFER_OFF ; Set es:di and load the root directory into the disk buffer
|
||||
call read_sectors ; Read the sectoooooooors !
|
||||
call read_sectors ; Read the sectors
|
||||
|
||||
;; FIND THE SECOND STAGE LOADER
|
||||
mov di, BUFFER_OFF ; Set es:di to the disk buffer
|
||||
|
@ -128,7 +128,7 @@ search_root:
|
|||
mov si, filename ; Load the filename
|
||||
mov cx, 11 ; Compare first 11 bytes
|
||||
rep cmpsb ; Compare si and di cx times
|
||||
je load_fat ; We found the LOADEEEEEEEER!!!
|
||||
je load_fat ; We found the loader
|
||||
add ax, 32 ; File entry offset
|
||||
mov di, BUFFER_OFF ; Point back to the start of the entry
|
||||
add di, ax ; Add the offset to point to the next entry
|
||||
|
@ -150,7 +150,7 @@ load_fat:
|
|||
mov cx, ax ; Store in cx
|
||||
mov ax, word [reservedSectors] ; Convert the first fat on the disk
|
||||
mov di, BUFFER_OFF ; Set es:di and load the fat sectors into the disk buffer
|
||||
call read_sectors ; Read the sectooooooooooors !!!
|
||||
call read_sectors ; Read the sectors
|
||||
|
||||
;; LOAD THE CLUSTERS OF THE LOADER AND JUMP
|
||||
mov di, LOAD_SEG
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef _I386_TYPE_
|
||||
#define _I386_TYPE_
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#endif
|
|
@ -7,28 +7,32 @@
|
|||
// Desc: Assertions //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef __kaleid_assert_h
|
||||
#define __kaleid_assert_h
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#ifndef _KALCOMM_ASSERT_H
|
||||
#define _KALCOMM_ASSERT_H
|
||||
|
||||
extern const char *panicstr;
|
||||
extern void panic(const char *) __dead;
|
||||
|
||||
#if !defined(_NO_DEBUG)
|
||||
|
||||
#define assert(x) do{if(!(x))panic(#x);}while(0);
|
||||
|
||||
#define assert_never_used(x) do{static bool __anu_##x = FALSE; \
|
||||
assert(__anu_##x == FALSE); __anu_##x = TRUE;}while(0);
|
||||
#define assert_never_used(x) do{static bool __##x##_init = FALSE; \
|
||||
assert(__##x##_init == FALSE); __##x##_init = TRUE;}while(0);
|
||||
|
||||
#define assert_used_once(x) do{static bool __anu_##x; assert(__anu_##x == TRUE);} while(0);
|
||||
#define assert_used_once(x) do{static bool __##x##_init; assert(__##x##_init == TRUE);} while(0);
|
||||
|
||||
#else // NDEBUG
|
||||
#else // not debugging
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#define NDEBUG 1
|
||||
#endif
|
||||
|
||||
#define assert(x)
|
||||
#define assert_never_used(x)
|
||||
#define assert_used_once(x)
|
||||
|
||||
#endif // NDEBUG
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
// Desc: Atomic stuff //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef __kaleid_atomic_h
|
||||
#define __kaleid_atomic_h
|
||||
#ifndef _KALCOMM_ATOMIC_H
|
||||
#define _KALCOMM_ATOMIC_H
|
||||
|
||||
// atomic_t defined in common/types.h
|
||||
|
||||
#define cli() // XXX
|
||||
#define sti() // XXX
|
||||
#define hlt() // XXX
|
||||
#define cli() asm volatile ("cli")
|
||||
#define sti() asm volatile ("sti")
|
||||
#define hlt() asm volatile ("hlt")
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
||||
#ifndef __kaleid_common_h
|
||||
#define __kaleid_common_h
|
||||
#ifndef _KALCOMM_COMMON_H
|
||||
#define _KALCOMM_COMMON_H
|
||||
|
||||
#define true 1
|
||||
#define TRUE 1
|
||||
|
@ -27,6 +27,9 @@
|
|||
#define THROWS(...)
|
||||
#define ERRS(...)
|
||||
|
||||
#define likely(x) __builtin_expect((x), 1)
|
||||
#define unlikely(x) __builtin_expect((x), 0)
|
||||
|
||||
#include "common/types.h"
|
||||
#include "common/config.h"
|
||||
#include "common/atomic.h"
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
// We may do a script that generates "config.h" for the user, asking about
|
||||
// the different configuration choices in the terminal.
|
||||
|
||||
#ifndef __kaleid_config_h
|
||||
#define __kaleid_config_h
|
||||
#ifndef _KALCOMM_CONFIG_H
|
||||
#define _KALCOMM_CONFIG_H
|
||||
|
||||
//------------------------------------------//
|
||||
// General configuration choices //
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
// We may do a script that generates "config.h" for the user, asking about
|
||||
// the different configuration choices in the terminal.
|
||||
|
||||
#ifndef __kaleid_config_h
|
||||
#define __kaleid_config_h
|
||||
#ifndef _KALCOMM_CONFIG_H
|
||||
#define _KALCOMM_CONFIG_H
|
||||
|
||||
//------------------------------------------//
|
||||
// General configuration choices //
|
||||
|
|
|
@ -9,23 +9,16 @@
|
|||
|
||||
#include "common/string.h"
|
||||
|
||||
// XXX several of these should be re-wrote in assembly
|
||||
|
||||
size_t strlen(const char *s)
|
||||
//
|
||||
// Return str's length
|
||||
// TODO multibyte, assembly
|
||||
//
|
||||
size_t strlen(const char *str)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; s; s++, i++);
|
||||
for (i = 0; str; str++, i++);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*size_t wcslen(const wchar_t *s);
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; s; s++, i++);
|
||||
|
||||
return s;
|
||||
}*/
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
||||
#ifndef __kaleid_status_h
|
||||
#define __kaleid_status_h
|
||||
#ifndef _KALCOMM_STATUS_H
|
||||
#define _KALCOMM_STATUS_H
|
||||
|
||||
#define STATUS_FAILED(x) ((x) < 0))
|
||||
#define STATUS_SUCCESS(x) (!STATUS_FAILED(x))
|
||||
|
@ -23,8 +23,9 @@
|
|||
|
||||
#define BAD_ARGUMENT (-4) // invalid arguments, can't be more precise
|
||||
#define BAD_ARG_RANGE (-5) // arguments out of range
|
||||
#define BAD_ARG_NULL (-6) // unexpected NULL argument
|
||||
|
||||
#define TRY_AGAIN (-6) // EAGAIN
|
||||
#define TRY_AGAIN (-7) // EAGAIN
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
||||
#ifndef __kaleid_string_h
|
||||
#define __kaleid_string_h
|
||||
#ifndef _KALCOMM_STRING_H
|
||||
#define _KALCOMM_STRING_H
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
||||
#ifndef __kaleid_types_h
|
||||
#define __kaleid_types_h
|
||||
#ifndef _KALCOMM_TYPES_H
|
||||
#define _KALCOMM_TYPES_H
|
||||
|
||||
typedef _Bool bool;
|
||||
typedef unsigned char uchar;
|
||||
|
@ -23,10 +23,8 @@ typedef uint wchar_t;
|
|||
typedef ulong size_t;
|
||||
typedef long ssize_t;
|
||||
|
||||
|
||||
// XXX
|
||||
typedef int atomic_t;
|
||||
typedef ulong pid_t; // etc...
|
||||
typedef ulong pid_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,11 +10,9 @@
|
|||
#include "kernel/init.h"
|
||||
#include "kernel/io/terminal.h"
|
||||
|
||||
void _start(void)
|
||||
void kstart(void)
|
||||
{
|
||||
assert(strlen("test") == 4);
|
||||
|
||||
kterm_init();
|
||||
kterm_print("Hello World!");
|
||||
panic("Goodbye World :(");
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
// Desc: Include file for init.c //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef __kaleid_kernel_init_h
|
||||
#define __kaleid_kernel_init_h
|
||||
#ifndef _KALKERN_INIT_H
|
||||
#define _KALKERN_INIT_H
|
||||
|
||||
#include "common/common.h"
|
||||
#include "common/string.h"
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
// Desc: Ports I/O //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef __kaleid_kernel_io_ports_h
|
||||
#define __kaleid_kernel_io_ports_h
|
||||
#ifndef _KALKERN_IO_PORTS_H
|
||||
#define _KALKERN_IO_PORTS_H
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
|
|
|
@ -9,139 +9,212 @@
|
|||
|
||||
#include "kernel/io/terminal.h"
|
||||
|
||||
// VGA buffer size
|
||||
static const size_t kterm_width = 80;
|
||||
static const size_t kterm_height = 25;
|
||||
|
||||
// position in the buffer
|
||||
static size_t current_row;
|
||||
static size_t current_col;
|
||||
|
||||
static uchar current_color;
|
||||
|
||||
// each buffer entry is composed of two bytes
|
||||
// one is the color code, the other the character
|
||||
static ushort *const buffer = (ushort *)0xB8000;
|
||||
|
||||
//
|
||||
// VGA-related macros
|
||||
//
|
||||
#define ComputeColorCode(fg, bg) ((fg) | (bg) << 4)
|
||||
#define ComputeEntryOffset(x, y) ((y) * kterm_width + (x))
|
||||
#define ComputeEntryOffset(kt, x, y) ((y) * kt->kt_width + (x))
|
||||
#define ComputeEntry(ch, cl) (((ushort)(ch)) | (ushort)(cl) << 8)
|
||||
|
||||
//
|
||||
// VGA output
|
||||
//
|
||||
static struct kterm _kt_vga = {
|
||||
.kt_buffer = (ushort *)0xB8000,
|
||||
.kt_width = 80,
|
||||
.kt_height = 25,
|
||||
.kt_curr_x = 0,
|
||||
.kt_curr_y = 0,
|
||||
.kt_color = ComputeColorCode(KTERM_COLOR_LGREY, KTERM_COLOR_BLACK),
|
||||
.kt_lock = NULL,
|
||||
#ifndef _NO_DEBUG
|
||||
.kt_init = FALSE,
|
||||
#endif
|
||||
};
|
||||
|
||||
//
|
||||
// Standard output terminal
|
||||
//
|
||||
struct kterm *kt_stdout;
|
||||
|
||||
//
|
||||
// Initialize standard output
|
||||
//
|
||||
void kterm_init(void)
|
||||
{
|
||||
assert_never_used(kterm_init);
|
||||
assert(!kt_stdout && !_kt_vga.kt_init && "kterm_init() called twice");
|
||||
|
||||
kterm_change_color(ComputeColorCode(KTERM_COLOR_LIGHT_GREY, KTERM_COLOR_BLACK));
|
||||
kterm_clear();
|
||||
#ifndef _NO_DEBUG
|
||||
_kt_vga.kt_init = TRUE;
|
||||
#endif
|
||||
|
||||
// to be switched to VESA
|
||||
kt_stdout = &_kt_vga;
|
||||
ktclear();
|
||||
}
|
||||
|
||||
void kterm_clear(void)
|
||||
//
|
||||
// Fills terminal with spaces
|
||||
// XXX would '\0' work too?
|
||||
//
|
||||
status_t kterm_clear(struct kterm *kt)
|
||||
{
|
||||
size_t x, y;
|
||||
size_t i;
|
||||
|
||||
assert_used_once(kterm_init);
|
||||
if (kt == NULL)
|
||||
return BAD_ARG_NULL;
|
||||
|
||||
for (x = 0; x < kterm_width; x++) {
|
||||
for (y = 0; y < kterm_height; y++) {
|
||||
const size_t offset = ComputeEntryOffset(x,y);
|
||||
buffer[offset] = ComputeEntry(' ', current_color);
|
||||
}
|
||||
assert(kt->kt_init && "kterm_clear called before initialization");
|
||||
|
||||
kterm_lock(kt);
|
||||
|
||||
const ushort filler = ComputeEntry(' ', kt->kt_color);
|
||||
const size_t bufsize = kt->kt_width * kt->kt_height;
|
||||
|
||||
for (i = 0; i < bufsize; i++) {
|
||||
// XXX implement memset()
|
||||
kt->kt_buffer[i] = filler;
|
||||
}
|
||||
|
||||
// go back to beginning
|
||||
current_row = current_col = 0;
|
||||
kt->kt_curr_x = kt->kt_curr_y = 0;
|
||||
|
||||
// XXX cursor update
|
||||
}
|
||||
|
||||
status_t kterm_change_color(uchar color)
|
||||
{
|
||||
if (color > KTERM_COLOR_WHITE)
|
||||
return BAD_ARG_RANGE;
|
||||
|
||||
current_color = color;
|
||||
kterm_unlock(kt);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void kterm_putchar(char ch)
|
||||
//
|
||||
// Change the color code
|
||||
//
|
||||
status_t kterm_change_color(struct kterm *kt, uchar color)
|
||||
{
|
||||
if (color > KTERM_COLOR_WHITE)
|
||||
return BAD_ARG_RANGE;
|
||||
|
||||
if (kt == NULL)
|
||||
return BAD_ARG_NULL;
|
||||
|
||||
kterm_lock(kt);
|
||||
kt->kt_color = color;
|
||||
kterm_unlock(kt);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Writes a single character on the terminal (UNLOCKED version)
|
||||
//
|
||||
// DEPRECATED:
|
||||
// - always use kterm_putch (LOCKED version)
|
||||
// - doesn't check for NULL input
|
||||
//
|
||||
void kterm_putch_unlocked(struct kterm *kt, char ch)
|
||||
{
|
||||
int i;
|
||||
size_t prev;
|
||||
|
||||
assert_used_once(kterm_init);
|
||||
size_t prev_row;
|
||||
|
||||
// carriage return takes us back to the beginning of the line
|
||||
// no further test should be necessary
|
||||
if (ch == '\r') { current_col = 0; return; }
|
||||
if (ch == '\r') { kt->kt_curr_x = 0; return; }
|
||||
|
||||
// line feed first takes us to the very end of the line
|
||||
// later in this function we actually do the line feed
|
||||
else if (ch == '\n') { current_col = kterm_width - 1; }
|
||||
else if (ch == '\n') { kt->kt_curr_y = kt->kt_width - 1; }
|
||||
|
||||
// tabulations account for 4 spaces
|
||||
else if (ch == '\t') {
|
||||
prev = current_row;
|
||||
prev_row = kt->kt_curr_y;
|
||||
// compiler will optimize this away
|
||||
for (i = 0; i < 4; i++) {
|
||||
// tabulations can't spread over two lines
|
||||
if (current_row != prev) return;
|
||||
|
||||
kterm_putchar(' ');
|
||||
if (kt->kt_curr_y == prev_row) {
|
||||
kterm_putch_unlocked(kt, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX check whether we were given a writable character
|
||||
else {
|
||||
const size_t offset = ComputeEntryOffset(current_col, current_row);
|
||||
buffer[offset] = ComputeEntry(ch, current_color);
|
||||
const size_t offset = ComputeEntryOffset(kt, kt->kt_curr_x, kt->kt_curr_y);
|
||||
kt->kt_buffer[offset] = ComputeEntry(ch, kt->kt_color);
|
||||
}
|
||||
|
||||
// end of line?
|
||||
if (++current_col == kterm_width) {
|
||||
current_col = 0;
|
||||
if (++kt->kt_curr_x == kt->kt_width) {
|
||||
kt->kt_curr_x = 0;
|
||||
|
||||
// end of buffer?
|
||||
if (++current_row == kterm_height) {
|
||||
current_row = 0;
|
||||
// XXX save previous buffer(?) and clear
|
||||
// line feed + end of buffer?
|
||||
if (++kt->kt_curr_y == kt->kt_height) {
|
||||
kt->kt_curr_y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kterm_print(const char *s)
|
||||
//
|
||||
// Writes a single character on the terminal (LOCKED version)
|
||||
//
|
||||
status_t kterm_putch(struct kterm *kt, char ch)
|
||||
{
|
||||
while (*s) {
|
||||
kterm_putchar(*s);
|
||||
if (kt == NULL)
|
||||
return BAD_ARG_NULL;
|
||||
|
||||
kterm_lock(kt);
|
||||
kterm_putch_unlocked(kt, ch);
|
||||
kterm_unlock(kt);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Print string on kterminal
|
||||
//
|
||||
status_t kterm_print(struct kterm *kt, const char *str)
|
||||
{
|
||||
if (kt == NULL)
|
||||
return BAD_ARG_NULL;
|
||||
|
||||
kterm_lock(kt);
|
||||
while (*str) {
|
||||
kterm_putch_unlocked(kt, *str);
|
||||
s++;
|
||||
}
|
||||
kterm_unlock(kt);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Panic message
|
||||
//
|
||||
const char *panicstr = NULL;
|
||||
|
||||
//
|
||||
// Your best boy panic()
|
||||
//
|
||||
void panic(const char *s)
|
||||
{
|
||||
cli();
|
||||
|
||||
panicstr = s;
|
||||
ktclear();
|
||||
|
||||
kterm_clear();
|
||||
|
||||
kterm_print("panic! - ");
|
||||
kterm_print(s);
|
||||
|
||||
while (1) hlt();
|
||||
|
||||
__builtin_unreachable();
|
||||
if (s == NULL) {
|
||||
s = "(no message given)";
|
||||
}
|
||||
|
||||
if (panicstr) {
|
||||
// shouldn't be possible
|
||||
ktprint("double panic!\n");
|
||||
hlt();
|
||||
}
|
||||
|
||||
panicstr = s;
|
||||
|
||||
ktprint("panic! - ");
|
||||
ktprint(s);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
while (TRUE) {
|
||||
hlt();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,37 +7,60 @@
|
|||
// Desc: Early terminal functions //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef __kaleid_kernel_io_terminal_h
|
||||
#define __kaleid_kernel_io_terminal_h
|
||||
#ifndef _KALKERN_IO_KTERM_H
|
||||
#define _KALKERN_IO_KTERM_H
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
// all available colors
|
||||
enum {
|
||||
KTERM_COLOR_BLACK,
|
||||
KTERM_COLOR_BLUE,
|
||||
KTERM_COLOR_GREEN,
|
||||
KTERM_COLOR_CYAN,
|
||||
KTERM_COLOR_RED,
|
||||
KTERM_COLOR_MAGENTA,
|
||||
KTERM_COLOR_BROWN,
|
||||
KTERM_COLOR_LIGHT_GREY,
|
||||
KTERM_COLOR_DARK_GREY,
|
||||
KTERM_COLOR_LIGHT_BLUE,
|
||||
KTERM_COLOR_LIGHT_GREEN,
|
||||
KTERM_COLOR_LIGHT_CYAN,
|
||||
KTERM_COLOR_LIGHT_RED,
|
||||
KTERM_COLOR_LIGHT_MAGENTA,
|
||||
KTERM_COLOR_LIGHT_BROWN,
|
||||
KTERM_COLOR_WHITE
|
||||
enum kterm_color {
|
||||
KTERM_COLOR_BLACK, KTERM_COLOR_BLUE,
|
||||
KTERM_COLOR_GREEN, KTERM_COLOR_CYAN,
|
||||
KTERM_COLOR_RED, KTERM_COLOR_MAGENTA,
|
||||
KTERM_COLOR_BROWN, KTERM_COLOR_LGREY,
|
||||
KTERM_COLOR_DARK_GREY, KTERM_COLOR_LBLUE,
|
||||
KTERM_COLOR_LGREEN, KTERM_COLOR_LCYAN,
|
||||
KTERM_COLOR_LRED, KTERM_COLOR_LMAGENTA,
|
||||
KTERM_COLOR_LBROWN, KTERM_COLOR_WHITE
|
||||
};
|
||||
|
||||
void kterm_init(void);
|
||||
void kterm_clear(void);
|
||||
void kterm_putchar(char ch);
|
||||
void kterm_print(const char *s);
|
||||
struct kterm {
|
||||
// flags?
|
||||
|
||||
status_t kterm_change_color(uchar color) ERRS(BAD_ARG_RANGE);
|
||||
void *kt_lock;
|
||||
ushort *kt_buffer;
|
||||
|
||||
uchar kt_color;
|
||||
size_t kt_width, kt_height;
|
||||
size_t kt_curr_x, kt_curr_y;
|
||||
|
||||
#ifndef _NO_DEBUG
|
||||
bool kt_init;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
// current "standard" terminal
|
||||
extern struct kterm *kt_stdout;
|
||||
|
||||
void kterm_init(void);
|
||||
status_t kterm_clear(struct kterm *);
|
||||
status_t kterm_putch(struct kterm *, char);
|
||||
status_t kterm_print(struct kterm *, const char *);
|
||||
status_t kterm_change_color(struct kterm *, uchar);
|
||||
|
||||
#ifdef _UNLOCKED_IO
|
||||
void kterm_putch_unlocked(struct kterm *, char ch);
|
||||
#endif
|
||||
|
||||
#define ktclear() kterm_clear(kt_stdout)
|
||||
#define ktputch(c) kterm_putch(kt_stdout,c)
|
||||
#define ktprint(s) kterm_print(kt_stdout,s)
|
||||
#define ktchcol(c) kterm_change_color(kt_stdout, c)
|
||||
|
||||
#define kterm_lock(kt)
|
||||
#define kterm_trylock(kt)
|
||||
#define kterm_unlock(kt)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
ENTRY(kstart)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x4000; /* XXX 0x4000 is temporary */
|
||||
|
||||
.text : AT(ADDR(.text) - 0x4000)
|
||||
{
|
||||
_code = .;
|
||||
*(.text)
|
||||
*(.rodata*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
.data : AT(ADDR(.data) - 0x4000)
|
||||
{
|
||||
_data = .;
|
||||
*(.data)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
.eh_frame : AT(ADDR(.eh_frame) - 0x4000)
|
||||
{
|
||||
_ehframe = .;
|
||||
*(.eh_frame)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
.bss : AT(ADDR(.bss) - 0x4000)
|
||||
{
|
||||
_bss = .;
|
||||
*(.bss)
|
||||
|
||||
/*
|
||||
* You usually need to include generated COMMON symbols
|
||||
* under kernel BSS section or use gcc's -fno-common
|
||||
*/
|
||||
|
||||
*(COMMON)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
_end = .;
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.comment)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue