1
0
mirror of https://gitlab.os-k.eu/os-k-team/os-k.git synced 2023-08-25 14:03:10 +02:00

Merge kaleid to boot

This commit is contained in:
Adrien Bourmault 2018-12-27 09:11:01 +01:00
commit 13d4e41983
37 changed files with 857 additions and 287 deletions

View File

@ -2,10 +2,14 @@
Fully open-source operating system from scratch (WIP), released under the GNU GPL version 3.0 Fully open-source operating system from scratch (WIP), released under the GNU GPL version 3.0
<<<<<<< HEAD
Branch boot : Development focused on the bootloader of OS/K Branch boot : Development focused on the bootloader of OS/K
=======
Branch kaleid : Development focused on the Kaleid Kernel.
>>>>>>> kaleid
For changelog, see src/ChangeLog. For changelog, see src/ChangeLog.
For structure of the sources, see src/project-tree.txt. For structure of the sources, see src/project-tree.txt.
For code conventions, see src/project-style.txt. For code conventions, see src/project-style.txt.

View File

@ -10,7 +10,7 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
2018/10/?? - Started talking about making our own OS 2018/10/?? - Started talking about making our own OS
2018/11/?? - Name decided & creation of gnu-os-k.eu 2018/11/?? - Name decided & creation of os-k.eu
2018/12/06 - Actually started project, began MBR, decided directories organization, created this file and others 2018/12/06 - Actually started project, began MBR, decided directories organization, created this file and others
2018/12/08 - MBR actually supports Long Mode Compatibility Verification 2018/12/08 - MBR actually supports Long Mode Compatibility Verification
- Added A20 line Enabling to MBR - Added A20 line Enabling to MBR

View File

@ -7,13 +7,16 @@
# Desc: Project Makefile # # Desc: Project Makefile #
#----------------------------------------------------------------------------# #----------------------------------------------------------------------------#
CC_NAME="/opt/cross-cc/bin/x86_64-elf-gcc" CCNAME="/opt/cross-cc/bin/x86_64-elf-gcc"
CWARNS=-Wall -Wextra -Werror CC2NAME=gcc # compiler for testing
CLDSCR=-T kernel.ld
CWARNS= -pedantic -Wall -Wextra -Werror
CFLAGS=-nostdlib -ffreestanding -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 CFLAGS=-nostdlib -ffreestanding -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2
CINCLUDES=-I./kaleid CINCLUDES=-I./kaleid
CDEFINES= CDEFINES=
CC=$(CC_NAME) $(CWARNS) $(CFLAGS) $(CDEFINES) $(CINCLUDES) CC=$(CCNAME) $(CWARNS) $(CFLAGS) $(CDEFINES) $(CINCLUDES)
KCC=$(CC) -D_KALEID_KERNEL
ASM=nasm ASM=nasm
ASMFLAGS= ASMFLAGS=
@ -26,6 +29,7 @@ BOOTDIR=boot
COMMDIR=kaleid/common COMMDIR=kaleid/common
KERNDIR=kaleid/kernel KERNDIR=kaleid/kernel
SYSTDIR=kaleid/system SYSTDIR=kaleid/system
LINXDIR=kaleid/linux
all: bootloader all: bootloader
@ -52,76 +56,40 @@ testing: bootloader pseudo_kern
# COMMON MAKEFILE # COMMON MAKEFILE
COBJDIR=$(OBJDIR)/$(COMMDIR) COBJDIR=$(OBJDIR)/$(COMMDIR)
LOBJDIR=$(OBJDIR)/$(LINXDIR)
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 $(COMMDIR)/status.h
COBJECTS=$(COBJDIR)/lib/string.o COMMOBJS=$(COBJDIR)/lib/string.o $(COBJDIR)/lib/status.o
common: common.lib.string.c $(COMM_DEPS) common: $(COMMDEPS) $(COMMDIR)/lib/string.c $(COMMDIR)/lib/status.c
$(KCC) -c $(COMMDIR)/lib/string.c -o $(COBJDIR)/lib/string.o
$(KCC) -c $(COMMDIR)/lib/status.c -o $(COBJDIR)/lib/status.o
common.lib.string.c: $(COMMDIR)/lib/string.c $(COMM_DEPS) CCC=$(CC2NAME) $(CWARNS) $(CDEFINES) $(CINCLUDES)
$(CC) -c $(COMMDIR)/lib/string.c -o $(OBJDIR)/$(COMMDIR)/lib/string.o
common-test:
$(CCC) -c $(COMMDIR)/lib/string.c -o $(COBJDIR)/lib/string.o
$(CCC) -c $(COMMDIR)/lib/status.c -o $(COBJDIR)/lib/status.o
$(CCC) -c $(LINXDIR)/test-common.c -o $(LOBJDIR)/test-common.o
$(CCC) $(COMMOBJS) $(LOBJDIR)/test-common.o -o $(BINDIR)/kaleid-common.elf
#----------------------------------------------------------------------------# #----------------------------------------------------------------------------#
# KERNEL MAKEFILE # KERNEL MAKEFILE
KOBJDIR=$(OBJDIR)/$(KERNDIR) KOBJDIR=$(OBJDIR)/$(KERNDIR)
KERN_DEPS=$(COMM_DEPS) $(KERNDIR)/init.h $(KERNDIR)/io/terminal.h $(KERNDIR)/io/ports.h KERNDEPS=common $(KERNDIR)/init.h $(KERNDIR)/io/terminal.h $(KERNDIR)/io/ports.h $(KERNDIR)/ke/panic.h
KERNSRCS=$(KERNDIR)/init.c $(KERNDIR)/ke/panic.c $(KERNDIR)/io/ports.c $(KERNDIR)/io/terminal.c
kernel: common kernel.io.terminal.c kernel.init.c kernel.io.ports.c KERNOBJS=$(KOBJDIR)/init.o $(KOBJDIR)/ke/panic.o $(KOBJDIR)/io/ports.o $(KOBJDIR)/io/terminal.o
$(CC) -o $(BINDIR)/kaleid-kernel.elf \
$(COBJECTS) $(KOBJDIR)/init.o \
$(KOBJDIR)/io/terminal.o $(KOBJDIR)/io/ports.o
kernel.init.c: $(KERNDIR)/init.c $(KERN_DEPS)
$(CC) -c $(KERNDIR)/init.c -o $(KOBJDIR)/init.o
kernel.io.ports.c: $(KERNDIR)/io/ports.c $(KERN_DEPS)
$(CC) -c $(KERNDIR)/io/ports.c -o $(KOBJDIR)/io/ports.o
kernel.io.terminal.c: $(KERNDIR)/io/terminal.c $(KERN_DEPS)
$(CC) -c $(KERNDIR)/io/terminal.c -o $(KOBJDIR)/io/terminal.o
kernel: common $(KERNSRCS)
$(KCC) -c $(KERNDIR)/init.c -o $(KOBJDIR)/init.o
$(KCC) -c $(KERNDIR)/ke/panic.c -o $(KOBJDIR)/ke/panic.o
$(KCC) -c $(KERNDIR)/io/ports.c -o $(KOBJDIR)/io/ports.o
$(KCC) -c $(KERNDIR)/io/terminal.c -o $(KOBJDIR)/io/terminal.o
$(KCC) $(CLDSCR) $(COMMOBJS) $(KERNOBJS) -o $(BINDIR)/kaleid-kernel.elf
#----------------------------------------------------------------------------#

View File

@ -58,7 +58,8 @@ GDT64:
NULL_SELECTOR: ;; null selector within 64 bits NULL_SELECTOR: ;; null selector within 64 bits
dw GDT_LENGTH ; limit of GDT dw GDT_LENGTH ; limit of GDT
dw GDT64 ; linear address of GDT dw GDT64 ; linear address of GDT
dd 0x0 dd 0x0 ;
CODE_SELECTOR: ;; 32-bit code selector (ring 0) CODE_SELECTOR: ;; 32-bit code selector (ring 0)
dw 0x0FFFF ; Segment Limit dw 0x0FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address db 0x0, 0x0, 0x0 ; Base Address
@ -117,7 +118,7 @@ GDT64:
; | | `---------- DPL !!! 0 for ring 0 ; | | `---------- DPL !!! 0 for ring 0
; | `----------- DPL (2/2) ; | `----------- DPL (2/2)
; `------------ 1 if in physical memory, 0 if page fault ; `------------ 1 if in physical memory, 0 if page fault
db 10101111b ; |7|6|5|4|3|2|1|0| db 10101111b ; |7|6|5|4|3|2|1|0|
; | | | | | | | `----- Limit 16 ; | | | | | | | `----- Limit 16
; | | | | | | `------ Limit 17 ; | | | | | | `------ Limit 17
; | | | | | `------- Limit 18 ; | | | | | `------- Limit 18

View File

@ -5,8 +5,9 @@
; NeoX ; ; NeoX ;
; ; ; ;
; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ; ; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ;
; (x86_64 architecture only) ; ; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=; ;=----------------------------------------------------------------------------=;
[BITS 64] [BITS 64]
clear: clear:
@ -33,7 +34,7 @@ write:
; bl : color code ; ; bl : color code ;
; esi : string address ; ; esi : string address ;
;-----------------------------------------------------------------------; ;-----------------------------------------------------------------------;
mov edi, [NextTRAM] ;TRAM ADDRESS mov edi, [NextTRAM] ; TRAM ADDRESS
push rsi push rsi
push rdi push rdi
.pLoop: .pLoop:
@ -48,7 +49,7 @@ write:
mov al, bl mov al, bl
stosb ; color subpixel stosb ; color subpixel
add qword [NextTRAM], 0x2 ; Cursor moving add qword [NextTRAM], 0x2 ; Cursor moving
add qword [VGA_X], 0x2 ; coord + 2 because 2 subpixels add qword [VGA_X], 0x2 ; coord + 2 because 2 subpixels
jmp .pLoop jmp .pLoop
.pEnd: .pEnd:
pop rdi pop rdi
@ -72,3 +73,4 @@ write:
.scroll: .scroll:
; XXX ; ; XXX ;
jmp .pLoop jmp .pLoop

View File

@ -34,7 +34,7 @@ read_clusters:
add ax, word [UserData] ; add the UserData add ax, word [UserData] ; add the UserData
xor ch, ch xor ch, ch
mov cl, byte [sectorsPerCluster] ; Sectors to read mov cl, byte [sectorsPerCluster] ; Sectors to read
call read_sectors ; Read the sectors call read_sectors ; Read the sectors
pop ax ; Current cluster number pop ax ; Current cluster number
xor dx, dx xor dx, dx
;; Calculate next sector for FAT16 (cluster * 2) ;; Calculate next sector for FAT16 (cluster * 2)

View File

@ -79,8 +79,8 @@ go:
;; INIT STACK ;; INIT STACK
cli cli
mov ax, STACK_SEG ; Init the staaaaaack mov ax, STACK_SEG ; Init the stack
mov ss, ax ; Continue init the staaaaaaaack mov ss, ax ; Continue init the stack
mov sp, STACK_OFF ; Ok man, the stack is in 4K :O mov sp, STACK_OFF ; Ok man, the stack is in 4K :O
sti sti
mov bp, (0x7c0-STACK_SEG) << 4 ; Correct bp (the disk description table) mov bp, (0x7c0-STACK_SEG) << 4 ; Correct bp (the disk description table)
@ -88,7 +88,7 @@ go:
;; INITIALIZE BOOT DISK ;; INITIALIZE BOOT DISK
or dl, dl ; Verifying dl points actually to the boot drive or dl, dl ; Verifying dl points actually to the boot drive
jz load_root jz load_root
mov byte [Bootdrv], dl ; Another soul (the disk) saved ! mov byte [Bootdrv], dl ; Another soul (the disk) saved!
mov ah, 0x08 mov ah, 0x08
int 0x13 ; int 0x13 : read drive parameters/geom int 0x13 ; int 0x13 : read drive parameters/geom
jc load_root jc load_root
@ -97,7 +97,7 @@ go:
mov dl, dh ; Convert the maximum head number to a word with another vaudou magical trip mov dl, dh ; Convert the maximum head number to a word with another vaudou magical trip
xor dh, dh xor dh, dh
inc dx ; because head numbers start at zero inc dx ; because head numbers start at zero
mov word [heads], dx ; Another soul (the heads number) saved ! mov word [heads], dx ; Another soul (the heads number) saved!
;; LOAD THE ROOT DIRECTORY FROM DISK ;; LOAD THE ROOT DIRECTORY FROM DISK
@ -117,7 +117,7 @@ load_root:
mov di, BUFFER_SEG ; Set the extra segment to the disk buffer mov di, BUFFER_SEG ; Set the extra segment to the disk buffer
mov es, di mov es, di
mov di, BUFFER_OFF ; Set es:di and load the root directory into the disk buffer 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 ;; FIND THE SECOND STAGE LOADER
mov di, BUFFER_OFF ; Set es:di to the disk buffer mov di, BUFFER_OFF ; Set es:di to the disk buffer
@ -128,7 +128,7 @@ search_root:
mov si, filename ; Load the filename mov si, filename ; Load the filename
mov cx, 11 ; Compare first 11 bytes mov cx, 11 ; Compare first 11 bytes
rep cmpsb ; Compare si and di cx times 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 add ax, 32 ; File entry offset
mov di, BUFFER_OFF ; Point back to the start of the entry mov di, BUFFER_OFF ; Point back to the start of the entry
add di, ax ; Add the offset to point to the next entry add di, ax ; Add the offset to point to the next entry
@ -150,14 +150,14 @@ load_fat:
mov cx, ax ; Store in cx mov cx, ax ; Store in cx
mov ax, word [reservedSectors] ; Convert the first fat on the disk 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 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 ;; LOAD THE CLUSTERS OF THE LOADER AND JUMP
mov di, LOAD_SEG mov di, LOAD_SEG
mov es, di ; Set es:bx to where the file will load mov es, di ; Set es:bx to where the file will load
mov di, LOAD_OFF mov di, LOAD_OFF
pop ax ; File cluster restored pop ax ; File cluster restored
call read_clusters ; Read clusters from the file call read_clusters ; Read clusters from the file
mov dl, byte [Bootdrv] ; Pass the boot Bootdrv into dl mov dl, byte [Bootdrv] ; Pass the boot Bootdrv into dl
jmp LOAD_SEG:LOAD_OFF ; Jump to the file loaded! jmp LOAD_SEG:LOAD_OFF ; Jump to the file loaded!

View File

@ -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

View File

@ -7,28 +7,45 @@
// Desc: Assertions // // Desc: Assertions //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef __kaleid_assert_h #ifndef _KALCOMM_ASSERT_H
#define __kaleid_assert_h #define _KALCOMM_ASSERT_H
#ifndef _KALCOMM_COMMON_H
#error "don't include common/types.h without common/common.h"
#endif
#ifdef _OSK_SOURCE
#if !defined(_NO_DEBUG) && !defined(NDEBUG)
// uses panic() in kernel, abort() in system
noreturn void ___assert_handler(const char *, const char *, int, const char *);
#define assert(x) do{if(unlikely(!(x)))___assert_handler(#x, __FILE__, __LINE__, __func__);}while(0);
#else // not debugging
#if !defined(NDEBUG) #if !defined(NDEBUG)
#define NDEBUG 1
#endif
extern const char *panicstr; #if !defined(_NO_DEBUG)
extern void panic(const char *) __dead; #define _NO_DEBUG 1
#endif
#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_used_once(x) do{static bool __anu_##x; assert(__anu_##x == TRUE);} while(0);
#else // NDEBUG
#define assert(x) #define assert(x)
#define assert_never_used(x)
#define assert_used_once(x) #endif
#endif // NDEBUG #else // !defined(_OSK_SOURCE)
#if defined(_NO_DEBUG) && !defined(NDEBUG)
#define NDEBUG 1
#endif
#include <assert.h>
#endif
#endif #endif

View File

@ -7,14 +7,23 @@
// Desc: Atomic stuff // // Desc: Atomic stuff //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef __kaleid_atomic_h #ifndef _KALCOMM_ATOMIC_H
#define __kaleid_atomic_h #define _KALCOMM_ATOMIC_H
#ifndef _KALCOMM_COMMON_H
#error "don't include common/types.h without common/common.h"
#endif
// atomic_t defined in common/types.h // atomic_t defined in common/types.h
#define cli() // XXX #ifdef _KALEID_KERNEL
#define sti() // XXX
#define hlt() // XXX // only available in the kernel
#define cli() asm volatile ("cli")
#define sti() asm volatile ("sti")
#define hlt() asm volatile ("hlt")
#endif
#endif #endif

View File

@ -7,25 +7,39 @@
// Desc: Standard include file for both kernel/ and system/ // // Desc: Standard include file for both kernel/ and system/ //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef _KALCOMM_COMMON_H
#define _KALCOMM_COMMON_H
#ifndef __kaleid_common_h #if !defined(_OSK_SOURCE) && (defined(_KALEID_KERNEL) || defined(_KALEID_SYSTEM))
#define __kaleid_common_h #define _OSK_SOURCE 1
#endif
#define true 1 #if !defined(TRUE) && !defined(FALSE)
#define TRUE 1 # define TRUE 1
#define YES 1 # define FALSE 0
#endif
#define false 0 #ifdef _OSK_SOURCE
#define FALSE 0 # define YES 1
#define NO 0 # define NO 0
#endif
#define NULL ((void*)0) #ifndef NULL
# define NULL ((void*)0)
#endif
#define PACKED __attribute__((packed)) #ifndef PACKED
#define __dead __attribute__((noreturn)) # define PACKED __attribute__((packed))
#endif
#define THROWS(...) #ifndef noreturn
#define ERRS(...) # define noreturn __attribute__((noreturn))
#endif
#if !defined(likely) && !defined(unlikely)
# define likely(x) __builtin_expect((x), 1)
# define unlikely(x) __builtin_expect((x), 0)
#endif
#include "common/types.h" #include "common/types.h"
#include "common/config.h" #include "common/config.h"

View File

@ -13,18 +13,29 @@
// We may do a script that generates "config.h" for the user, asking about // We may do a script that generates "config.h" for the user, asking about
// the different configuration choices in the terminal. // the different configuration choices in the terminal.
#ifndef __kaleid_config_h #ifndef _KALCOMM_CONFIG_H
#define __kaleid_config_h #define _KALCOMM_CONFIG_H
//------------------------------------------// //------------------------------------------//
// General configuration choices // // General configuration choices //
//------------------------------------------// //------------------------------------------//
// Enable multiprocessor support? //
// Right now this has to be left to NO // Enable/disable multiprocessor support
//
#define MULTIPROCESSOR NO #define MULTIPROCESSOR NO
// etc... //
// Enable/disable preemptivity
//
#define PREEMPTIVE YES
//
// Size of a tabulation in spaces
// Default: 4 spaces/tab
//
#define TABSIZE 4
// this file is to be progressively filled // this file is to be progressively filled
#endif #endif

View File

@ -13,18 +13,29 @@
// We may do a script that generates "config.h" for the user, asking about // We may do a script that generates "config.h" for the user, asking about
// the different configuration choices in the terminal. // the different configuration choices in the terminal.
#ifndef __kaleid_config_h #ifndef _KALCOMM_CONFIG_H
#define __kaleid_config_h #define _KALCOMM_CONFIG_H
//------------------------------------------// //------------------------------------------//
// General configuration choices // // General configuration choices //
//------------------------------------------// //------------------------------------------//
// Enable multiprocessor support? //
// Right now this has to be left to NO // Enable/disable multiprocessor support
//
#define MULTIPROCESSOR NO #define MULTIPROCESSOR NO
// etc... //
// Enable/disable preemptivity
//
#define PREEMPTIVE YES
//
// Size of a tabulation in spaces
// Default: 4 spaces/tab
//
#define TABSIZE 4
// this file is to be progressively filled // this file is to be progressively filled
#endif #endif

View File

@ -0,0 +1,24 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Conversion utilities //
//----------------------------------------------------------------------------//
#ifndef _KALCOMM_CONVERT_H
#define _KALCOMM_CONVERT_H
#ifndef _KALCOMM_COMMON_H
#include "common/common.h"
#endif
#ifndef _OSK_SOURCE
# define itoa _osk_itoa
# define atoi _osk_atoi
#endif
char *itoa(int, char *, int);
#endif

View File

@ -0,0 +1,52 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Conversion utilities //
//----------------------------------------------------------------------------//
#include "common/convert.h"
//
// Digits table for bases <=36
//
static const char digits[36] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//
// Integer to string in any base between 2 and 36 (included)
//
char *itoa(int i, char *str, int base)
{
int neg = 0;
char *orig = str;
if (base < 2 || base > 36)
return NULL;
// deal with negatives
if (i < 0) {
neg = 1;
i = -i;
}
// deal with zero separatly
if (i == 0) {
*str++ = '0';
}
// compute digits... in reverse order
while (i > 0) {
*str++ = digits[i % base];
i /= base;
}
if (neg) *str++ = '-';
*str = '\0';
return reverse(orig);
}

View File

@ -0,0 +1,11 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: mem*() functions //
//----------------------------------------------------------------------------//
#include "common/memory.h"

View File

@ -0,0 +1,69 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: sprintf()-related functions //
//----------------------------------------------------------------------------//
#include "common/string.h"
//
// Format str according to fmt using ellipsed arguments
//
int sprintf(char *str, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap);
ret = vsnprintf(str, SIZE_T_MAX, fmt, ap);
va_end(ap);
return ret;
}
int vsprintf(char *str, const char *fmt, va_list ap)
{
return vsnprintf(str, SIZE_T_MAX, fmt, ap);
}
//
// (v)sprintf() but with a size limit: no more than n bytes are written in str
// XXX null termination behavior?
//
int snprintf(char *str, size_t n, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap);
ret = vsnprintf(str, n, fmt, ap)
va_end(ap);
return ret;
}
int vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
{
int ret = 0;
while (*fmt && ret < n) {
if (*fmt != '%') {
*str++ = *fmt++;
ret++;
continue;
}
switch (*fmt) {
case 'd':
default:
break;
}
}
return ret;
}

View File

@ -0,0 +1,31 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Implementation of describe_status() //
//----------------------------------------------------------------------------//
#include "common/common.h"
static const char *descriptions[] = {
[-SUCCESS] = "Success",
[-FAILED] = "Failed (no precision)",
[-NOT_PERMITTED] = "Operation not permitted",
[-ACCESS_DENIED] = "Access denied",
[-BAD_ARGUMENT] = "Bad argument",
[-BAD_ARG_RANGE] = "Bad argument (not in range)",
[-BAD_ARG_NULL] = "Bad argument (null pointer)",
};
const char *describe_status(status_t status)
{
(void)descriptions;
(void)status;
// XXX
return "";
}

View File

@ -4,28 +4,64 @@
// Authors: spectral` // // Authors: spectral` //
// NeoX // // NeoX //
// // // //
// Desc: strlen() function // // Desc: String-related functions //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#include "common/string.h" #include "common/string.h"
// XXX several of these should be re-wrote in assembly // TODO multibyte, assembly
size_t strlen(const char *s) //
// Returns str's length
//
size_t strlen(const char *str)
{
const char *base = str;
while (*str++);
return (str - base - 1);
}
//
// Copy the string src into dest
//
char *strcpy(char *dest, const char *src)
{
char *base = dest;
while ((*dest++ = *src++));
return base;
}
//
// strcpy() but safer
//
char *strncpy(char *dest, const char *src, size_t n)
{ {
size_t i; size_t i;
for (i = 0; s; s++, i++); for (i = 0; i < n && src[i]; i++) {
dest[i] = src[i];
}
return i; while (i < n) dest[i++] = 0;
return dest;
} }
/*size_t wcslen(const wchar_t *s); //
// Reverses a string
//
char *reverse(char *str)
{ {
int i; char ch, *orig = str;
size_t n = strlen(str);
for (i = 0; s; s++, i++); char *temp = str + n - 1;
return s;
}*/
while (temp > str) {
ch = *temp;
*temp-- = *str;
*str++ = ch;
}
return orig;
}

View File

@ -0,0 +1,18 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: mem*() functions //
//----------------------------------------------------------------------------//
#ifndef _KALCOMM_MEMORY_H
#define _KALCOMM_MEMORY_H
#ifndef _KALCOMM_COMMON_H
#include "common/common.h"
#endif
#endif

View File

@ -7,9 +7,19 @@
// Desc: Values for status_t // // Desc: Values for status_t //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef _KALCOMM_STATUS_H
#define _KALCOMM_STATUS_H
#ifndef __kaleid_status_h #ifndef _KALCOMM_COMMON_H
#define __kaleid_status_h #error "don't include common/types.h without common/common.h"
#endif
#ifndef _OSK_SOURCE
# define describe_status _osk_describe_status
#endif
// see in common/lib/status.c for status messages
const char *describe_status(status_t);
#define STATUS_FAILED(x) ((x) < 0)) #define STATUS_FAILED(x) ((x) < 0))
#define STATUS_SUCCESS(x) (!STATUS_FAILED(x)) #define STATUS_SUCCESS(x) (!STATUS_FAILED(x))
@ -23,8 +33,9 @@
#define BAD_ARGUMENT (-4) // invalid arguments, can't be more precise #define BAD_ARGUMENT (-4) // invalid arguments, can't be more precise
#define BAD_ARG_RANGE (-5) // arguments out of range #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 #endif

View File

@ -8,12 +8,36 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef __kaleid_string_h #ifndef _KALCOMM_STRING_H
#define __kaleid_string_h #define _KALCOMM_STRING_H
#ifndef _KALCOMM_COMMON_H
#include "common/common.h" #include "common/common.h"
#endif
size_t strlen(const char *s); #ifndef _OSK_SOURCE
# define strlen _osk_strlen
# define strcpy _osk_strcpy
# define strncpy _osk_strncpy
# define reverse _osk_reverse
# define sprintf _osk_sprintf
# define snprintf _osk_snprintf
# define vsprintf _osk_vsprintf
# define vsnprintf _osk_vsnprintf
#endif
size_t strlen(const char *);
char *strcpy(char *, const char *);
char *strncpy(char *, const char *, size_t);
char *reverse(char *);
int sprintf(char *, const char *, ...);
int snprintf(char *, size_t, const char *, ...);
int vsprintf(char *, const char *, va_list);
int vsnprintf(char *, size_t, const char *, va_list);
#endif #endif

View File

@ -8,25 +8,34 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef __kaleid_types_h #ifndef _KALCOMM_TYPES_H
#define __kaleid_types_h #define _KALCOMM_TYPES_H
typedef _Bool bool; #ifndef _KALCOMM_COMMON_H
typedef unsigned char uchar; #error "don't include common/types.h without common/common.h"
typedef unsigned short ushort; #endif
typedef unsigned int uint;
typedef unsigned long ulong;
typedef long double ldouble;
typedef short status_t;
typedef short port_t;
typedef uint wchar_t;
typedef ulong size_t;
typedef long ssize_t;
#ifndef KEEP_KALCOMM_TYPES_MINIMAL
typedef _Bool bool;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef long long llong;
typedef unsigned long long ullong;
typedef long double ldouble;
typedef uint wchar_t;
typedef ullong size_t;
typedef llong ssize_t;
typedef size_t off_t;
typedef int atomic_t;
typedef ulong pid_t;
typedef void *va_list;
#endif
// XXX typedef short port_t;
typedef int atomic_t; typedef short status_t;
typedef ulong pid_t; // etc... // XXX limits
#endif #endif

View File

@ -8,13 +8,15 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#include "kernel/init.h" #include "kernel/init.h"
#include "kernel/ke/panic.h"
#include "kernel/io/terminal.h" #include "kernel/io/terminal.h"
void _start(void) //
{ // Entry point of kaleid-kernel.elf
assert(strlen("test") == 4); //
void kstart(void)
{
kterm_init(); kterm_init();
kterm_print("Hello World!"); panic("Goodbye World :(");
} }

View File

@ -7,11 +7,10 @@
// Desc: Include file for init.c // // Desc: Include file for init.c //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef __kaleid_kernel_init_h #ifndef _KALKERN_INIT_H
#define __kaleid_kernel_init_h #define _KALKERN_INIT_H
#include "common/common.h" #include "common/common.h"
#include "common/string.h"
// kernel entry point // kernel entry point
void kstart(void); void kstart(void);

View File

@ -7,15 +7,15 @@
// Desc: Ports I/O // // Desc: Ports I/O //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef __kaleid_kernel_io_ports_h #ifndef _KALKERN_IO_PORTS_H
#define __kaleid_kernel_io_ports_h #define _KALKERN_IO_PORTS_H
#include "common/common.h" #include "common/common.h"
#define outb(port,val) asm volatile ("outb %1, %0" : : "dN" (port), "a" (value)) #define outb(port,val) asm volatile ("outb %1, %0" : : "dN" (port), "a" (value))
uchar inb(port_t port); uchar inb(port_t);
ushort inw(port_t port); ushort inw(port_t);
#endif #endif

View File

@ -9,139 +9,178 @@
#include "kernel/io/terminal.h" #include "kernel/io/terminal.h"
// VGA buffer size //
static const size_t kterm_width = 80; // VGA-related macros
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;
#define ComputeColorCode(fg, bg) ((fg) | (bg) << 4) #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) #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) void kterm_init(void)
{ {
assert_never_used(kterm_init); assert(!kt_stdout && !_kt_vga.kt_init && "kterm_init() called twice");
#ifndef _NO_DEBUG
_kt_vga.kt_init = TRUE;
#endif
kterm_change_color(ComputeColorCode(KTERM_COLOR_LIGHT_GREY, KTERM_COLOR_BLACK)); // to be switched to VESA
kterm_clear(); 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++) { assert(kt->kt_init && "kterm_clear called before initialization");
for (y = 0; y < kterm_height; y++) {
const size_t offset = ComputeEntryOffset(x,y); kterm_lock(kt);
buffer[offset] = ComputeEntry(' ', current_color);
} 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 kt->kt_curr_x = kt->kt_curr_y = 0;
current_row = current_col = 0;
// XXX cursor update kterm_unlock(kt);
return SUCCESS;
} }
status_t kterm_change_color(uchar color) //
// Change the color code
//
status_t kterm_change_color(struct kterm *kt, uchar color)
{ {
if (color > KTERM_COLOR_WHITE) if (color > KTERM_COLOR_WHITE)
return BAD_ARG_RANGE; return BAD_ARG_RANGE;
current_color = color; if (kt == NULL)
return BAD_ARG_NULL;
kterm_lock(kt);
kt->kt_color = color;
kterm_unlock(kt);
return SUCCESS; return SUCCESS;
} }
void kterm_putchar(char ch) //
// 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; int i;
size_t prev; size_t prev_row;
assert_used_once(kterm_init);
// carriage return takes us back to the beginning of the line // carriage return takes us back to the beginning of the line
// no further test should be necessary // 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 // line feed first takes us to the very end of the line
// later in this function we actually do the line feed // 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 // tabulations account for 4 spaces
else if (ch == '\t') { else if (ch == '\t') {
prev = current_row; prev_row = kt->kt_curr_y;
// compiler will optimize this away // compiler will optimize this away
for (i = 0; i < 4; i++) { for (i = 0; i < TABSIZE; i++) {
// tabulations can't spread over two lines // tabulations can't spread over two lines
if (current_row != prev) return; if (kt->kt_curr_y == prev_row) {
kterm_putch_unlocked(kt, ' ');
kterm_putchar(' '); }
} }
} }
// XXX check whether we were given a writable character // XXX check whether we were given a writable character
else { else {
const size_t offset = ComputeEntryOffset(current_col, current_row); const size_t offset = ComputeEntryOffset(kt, kt->kt_curr_x, kt->kt_curr_y);
buffer[offset] = ComputeEntry(ch, current_color); kt->kt_buffer[offset] = ComputeEntry(ch, kt->kt_color);
} }
// end of line? // end of line?
if (++current_col == kterm_width) { if (++kt->kt_curr_x == kt->kt_width) {
current_col = 0; kt->kt_curr_x = 0;
// end of buffer? // line feed + end of buffer?
if (++current_row == kterm_height) { if (++kt->kt_curr_y == kt->kt_height) {
current_row = 0; kt->kt_curr_y = 0;
// XXX save previous buffer(?) and clear
} }
} }
} }
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) { if (kt == NULL)
kterm_putchar(*s); return BAD_ARG_NULL;
s++;
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++);
} }
} kterm_unlock(kt);
void panic(const char *s)
{
cli();
panicstr = s;
kterm_clear();
kterm_print("panic! - ");
kterm_print(s);
while (1) hlt();
__builtin_unreachable(); return SUCCESS;
} }

View File

@ -7,37 +7,58 @@
// Desc: Early terminal functions // // Desc: Early terminal functions //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifndef __kaleid_kernel_io_terminal_h #ifndef _KALKERN_IO_KTERM_H
#define __kaleid_kernel_io_terminal_h #define _KALKERN_IO_KTERM_H
#include "common/common.h" #include "common/common.h"
// all available colors // all available colors
enum { enum kterm_color {
KTERM_COLOR_BLACK, KTERM_COLOR_BLACK, KTERM_COLOR_BLUE,
KTERM_COLOR_BLUE, KTERM_COLOR_GREEN, KTERM_COLOR_CYAN,
KTERM_COLOR_GREEN, KTERM_COLOR_RED, KTERM_COLOR_MAGENTA,
KTERM_COLOR_CYAN, KTERM_COLOR_BROWN, KTERM_COLOR_LGREY,
KTERM_COLOR_RED, KTERM_COLOR_DARK_GREY, KTERM_COLOR_LBLUE,
KTERM_COLOR_MAGENTA, KTERM_COLOR_LGREEN, KTERM_COLOR_LCYAN,
KTERM_COLOR_BROWN, KTERM_COLOR_LRED, KTERM_COLOR_LMAGENTA,
KTERM_COLOR_LIGHT_GREY, KTERM_COLOR_LBROWN, KTERM_COLOR_WHITE
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
}; };
void kterm_init(void); struct kterm {
void kterm_clear(void); void *kt_lock;
void kterm_putchar(char ch); ushort *kt_buffer;
void kterm_print(const char *s); uchar kt_color;
size_t kt_width;
size_t kt_height;
off_t kt_curr_x;
off_t kt_curr_y;
#ifndef _NO_DEBUG
bool kt_init;
#endif
};
status_t kterm_change_color(uchar color) ERRS(BAD_ARG_RANGE); // 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);
#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 #endif

View File

@ -0,0 +1,59 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: How NOT to panic 101 //
//----------------------------------------------------------------------------//
#include "kernel/ke/panic.h"
//
// Panic message
//
const char *panicstr = NULL;
//
// Failed assert() handler
//
noreturn void ___assert_handler(const char *msg, const char *file, int line, const char *func)
{
// not getting out of here
cli();
(void)file; (void)line; (void)func;
// XXX sprintf() to create a proper panicstr
panic(msg);
}
//
// Your best boy panic()
//
void panic(const char *str)
{
cli();
ktclear();
if (str == NULL) {
str = "(no message given)";
}
if (panicstr) {
// shouldn't be possible
ktprint("double panic!\n");
hlt();
}
panicstr = str;
ktprint("panic! - ");
ktprint(str);
while (TRUE) {
hlt();
}
}

View File

@ -0,0 +1,18 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Looking to create some panic? Look no further! //
//----------------------------------------------------------------------------//
#ifndef _KALKERN_KE_PANIC_H
#define _KALKERN_KE_PANIC_H
#include "kernel/io/terminal.h"
extern const char *panicstr;
noreturn void panic(const char *);
#endif

View File

@ -0,0 +1,12 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Memory allocation routines //
// Only exists to trigger Neox //
//----------------------------------------------------------------------------//
#include "kernel/mm/malloc.h"

View File

@ -0,0 +1,16 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Memory allocation routines //
//----------------------------------------------------------------------------//
#ifndef _KALKERN_MM_MALLOC_H
#define _KALKERN_MM_MALLOC_H
#include "common/common.h"
#endif

View File

@ -0,0 +1,44 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Test file for common/ //
//----------------------------------------------------------------------------//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define KEEP_KALCOMM_TYPES_MINIMAL
#include "common/common.h"
#include "common/string.h"
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
const char *test1 = "test string\n";
char *test2 = malloc(strlen(test1));
char *test3 = malloc(strlen(test1));
printf("1\n");
#undef strlen
assert(strlen("test string") == _osk_strlen("test string"));
#undef strcpy
assert(strcmp(strcpy(test2, test1), _osk_strcpy(test3, test1)) == 0);
// tests done
printf("2\n");
free(test2);
free(test3);
return 0;
}

49
src/kernel.ld Normal file
View File

@ -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)
}
}

View File

View File

@ -7,6 +7,8 @@
// Desc: Project Tree // // Desc: Project Tree //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
// XXX *not* up to date
src/ src/
| |
+ boot/ + boot/

View File

@ -1,4 +0,0 @@
make
cp ../bin/bootloader.bin "~/Documents/GNU OSK/bin/bootloader.bin"
qemu-system-x86_64 -hda "~/Documents/GNU OSK/bin/bootloader.bin"
qemu-system-i386 -hda "~/Documents/GNU OSK/bin/bootloader.bin"