Commit b906dff6 authored by Oxynux's avatar Oxynux

switch to CMake and big refactoring

- libk renamed liboxyk
- COM1 output for debuging
- very basic shell (kshell)
- reboot function
parent 834f08ed
*.o
kfs_1.iso
kfs_1
kernel/
\ No newline at end of file
## Covers JetBrains IDE (CLion)
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# CMake
cmake-build-*/
cmake_minimum_required(VERSION 3.10)
set(BINARY oxynux)
project(${BINARY})
set(KERNEL_DIR oxynux_kernel)
set(SCRIPT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/post_build.sh)
set(GRUB_CFG ${CMAKE_CURRENT_SOURCE_DIR}/src/grub.cfg)
set(KERNEL_IMG oxynux.iso)
set(LD_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/linker.ld)
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf32)
enable_language(ASM_NASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -O0 -ffreestanding")
set(CMAKE_NASM_LINK_EXECUTABLE "ld -m elf_i386 -T ${LD_PATH} -o <TARGET> <OBJECTS>")
set(SOURCES_FILES
include/freestanding.h
include/kernel.h
include/liboxyk.h
include/kernel/keyboard.h
include/kernel/vga.h
include/kernel/kshell.h
include/kernel/system.h
include/kernel/com.h
src/liboxyk/strncmp.c
src/liboxyk/memcpy.c
src/liboxyk/isdigit.c
src/liboxyk/isascii.c
src/liboxyk/strlen.c
src/liboxyk/isprint.c
src/liboxyk/isalpha.c
src/liboxyk/memmove.c
src/liboxyk/islower.c
src/liboxyk/memset.c
src/liboxyk/isupper.c
src/liboxyk/inb.c
src/liboxyk/isspace.c
src/liboxyk/isalnum.c
src/liboxyk/outb.c
src/vga/kputchar.c
src/vga/kputstr.c
src/vga/clear_screen.c
src/vga/kputnbr.c
src/vga/write_on_screen.c
src/vga/vga.c
src/keyboard/keyboard.c
src/kmain.c
src/boot.asm
src/system/reboot.c
src/kshell/cmd_parse.c
src/com/com1.c
src/vga/reset_cursor.c include/freestanding.h)
include_directories(include)
add_executable(${BINARY} ${SOURCES_FILES})
set_target_properties(${BINARY} PROPERTIES LINKER_LANGUAGE NASM)
add_custom_command(TARGET ${BINARY} POST_BUILD COMMAND sh ${SCRIPT_PATH} ${KERNEL_DIR} ${GRUB_CFG} ${PROJECT_BINARY_DIR}/${BINARY} ${KERNEL_IMG} ${LD_PATH})
set(RUN_COMMAND -enable-kvm -cdrom ${KERNEL_IMG} -serial file:serial.log)
add_custom_target(run COMMAND qemu-system-i386 ${RUN_COMMAND})
\ No newline at end of file
KERNEL = kfs_1
KERNEL_IMG = kfs_1.iso
KERNEL_DIR = kernel
LIBK_DIR = libk
LIBK = $(LIBK_DIR)/libk.a
CC = gcc
LD = ld
ASM = nasm
WFLAGS = # -Wall -Wextra -Werror
INCLUDES = -I . -I $(LIBK_DIR)
CCFLAGS = -O0 -ffreestanding -m32 -nostdlib -fno-stack-protector $(WFLAGS) $(INCLUDES)
LDFLAGS = -m elf_i386 -T
ASMFLAGS = -f elf32
CC_SRC = kmain.c \
keyboard.c
LD_SRC = link.ld
ASM_SRC = kernel.s
GRUB_CFG = grub.cfg
CC_OBJ = $(CC_SRC:.c=.o)
ASM_OBJ = $(ASM_SRC:.s=.o)
all: $(KERNEL_IMG)
$(KERNEL_IMG): $(KERNEL)
mkdir -p $(KERNEL_DIR)/boot/grub
cp -r $< $(KERNEL_DIR)/boot
cp -r $(GRUB_CFG) $(KERNEL_DIR)/boot/grub
grub-mkrescue -o $@ $(KERNEL_DIR)
$(KERNEL): $(ASM_OBJ) $(CC_OBJ)
$(MAKE) -C $(LIBK_DIR)/
$(LD) $(LDFLAGS) $(LD_SRC) -o $@ $^ $(LIBK)
.c.o:
$(CC) $(CCFLAGS) -c $< -o $@
.s.o:
$(ASM) $(ASMFLAGS) -o $@ $<
clean:
rm -rf $(CC_OBJ)
rm -rf $(ASM_OBJ)
$(MAKE) -C $(LIBK_DIR)/ clean
fclean: clean
rm -rf $(KERNEL_DIR)
rm -rf $(KERNEL_IMG)
rm -rf $(KERNEL)
$(MAKE) -C $(LIBK_DIR)/ fclean
run: $(KERNEL_IMG)
qemu-system-i386 -cdrom $(KERNEL_IMG)
re: fclean all
//
// Created by oxynux on 2/25/19.
//
#ifndef OXYNUX_FREESTANDING_H
#define OXYNUX_FREESTANDING_H
//C89
#include <float.h>
#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
//C99
#include <stdbool.h>
#include <stdint.h>
//C11
#include <stdalign.h>
#include <stdnoreturn.h>
#endif //OXYNUX_FREESTANDING_H
#ifndef KERNEL_H
#define KERNEL_H
#include <stdint.h>
/*
* Video Memory begin
*/
#define VID_MEMORY 0x0b8000
#define VGA_WIDTH 80
/*
* Max Columns and Lines
*/
#define MAX_COLUMNS 80
#define MAX_LINES 25
/*
* Colors
*/
#define BLACK 0x00
#define BLUE 0x01
#define GREEN 0x02
#define CYAN 0x03
#define RED 0x04
#define MAGENTA 0x05
#define BROWN 0x06
#define LIGHT_GREY 0x07
#define DARK_GREY 0x08
#define LIGHT_BLUE 0x09
#define LIGHT_GREEN 0x0a
#define LIGHT_CYAN 0x0b
#define LIGHT_RED 0x0c
#define LIGHT_MAGENTA 0x0d
#define LIGHT_BROWN 0x0e
#define WHITE 0x0f
int getchar(_Bool caps);
void kputchar(int c);
//void init_gdt(void);
//
//struct gdtr {
// uint16_t limite;
// uint32_t base;
//} __attribute__ ((packed));
// Created by oxynux on 2/20/19.
//
//struct gdtdesc {
// uint16_t lim0_15;
// uint16_t base0_15;
// uint8_t base16_23;
// uint8_t acces;
// uint8_t lim16_19:4;
// uint8_t other:4;
// uint8_t base24_31;
//} __attribute__ ((packed));
#define GDTBASE 0x00000800
#ifndef OXYNUX_KERNEL_H
#define OXYNUX_KERNEL_H
#include "liboxyk.h"
#include "kernel/vga.h"
#include "kernel/com.h"
#endif
#endif //OXYNUX_KERNEL_H
//
// Created by oxynux on 2/24/19.
//
#ifndef OXYNUX_COM_H
#define OXYNUX_COM_H
#include "kernel.h"
#define COM1 0x3F8
void init_serial(void);
int is_transmit_empty(void);
void write_serial(char a);
void print_to_serial(char *s);
#endif //OXYNUX_COM_H
//
// Created by oxynux on 2/20/19.
//
#ifndef OXYNUX_KEYBOARD_H
#define OXYNUX_KEYBOARD_H
#include "kernel.h"
#include "kernel/kshell.h"
#include "kernel/com.h"
extern unsigned char kbdus[2][128];
int getchar(bool caps);
void basic_kbd(void);
#endif //OXYNUX_KEYBOARD_H
//
// Created by oxynux on 2/24/19.
//
#ifndef OXYNUX_KSHELL_H
#define OXYNUX_KSHELL_H
#include "kernel.h"
#include "kernel/system.h"
#include "kernel/com.h"
int cmd_parse(char *buf);
#endif //OXYNUX_KSHELL_H
//
// Created by oxynux on 2/24/19.
//
#ifndef OXYNUX_SYSTEM_H
#define OXYNUX_SYSTEM_H
#include "kernel.h"
void reboot(void);
#endif //OXYNUX_SYSTEM_H
//
// Created by oxynux on 2/20/19.
//
#ifndef OXYNUX_VGA_H
#define OXYNUX_VGA_H
#include "kernel.h"
#include "kernel/keyboard.h"
#define VID_MEMORY 0x0b8000
#define VGA_WIDTH 80
#define MAX_COLUMNS 80
#define MAX_LINES 25
#define BLACK 0x00
#define BLUE 0x01
#define GREEN 0x02
#define CYAN 0x03
#define RED 0x04
#define MAGENTA 0x05
#define BROWN 0x06
#define LIGHT_GREY 0x07
#define DARK_GREY 0x08
#define LIGHT_BLUE 0x09
#define LIGHT_GREEN 0x0a
#define LIGHT_CYAN 0x0b
#define LIGHT_RED 0x0c
#define LIGHT_MAGENTA 0x0d
#define LIGHT_BROWN 0x0e
#define WHITE 0x0f
void kputchar(int c);
void kputstr(char *s);
void kputnbr(int n);
void write_on_screen(const char *str, char *vidptr);
void clear_screen(void);
void enable_cursor(uint8_t cursor_start, uint8_t cursor_end);
void update_cursor(int x, int y);
int column(char *video);
int line(char *video);
void enter(char **video);
void del(char **video);
void arrow_up(char **video);
void arrow_down(char **video);
void arrow_right(char **video);
void arrow_left(char **video);
void reset_cursor(void);
#endif //OXYNUX_VGA_H
//
// Created by oxynux on 2/17/19.
// Created by oxynux on 2/20/19.
//
#ifndef KFS_LIBK_H
#define KFS_LIBK_H
#ifndef OXYNUX_LIBOXYK_H
#define OXYNUX_LIBOXYK_H
#include <stddef.h>
#include "freestanding.h"
int memcmp(const void *s1, const void *s2, size_t n);
uint8_t inb(uint16_t port);
void outb(uint16_t port, uint8_t val);
void *memcpy(void *s1, const void *s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);
void *memset(void *b, int c, size_t len);
size_t strlen(const char *str);
int isalnum(int c);
int isalpha(int c);
int isascii(int c);
int isdigit(int c);
int islower(int c);
int isprint(int c);
int isspace(int c);
int isupper(int c);
int strncmp(const char *s1, const char *s2, size_t n);
#endif //KFS_LIBK_H
#endif //OXYNUX_LIBOXYK_H
;;kernel.s
bits 32 ; compile in 32 bits - explicit
section .text ; begin text section, where we'll put all of our code
; multiboot spec
align 4 ; multiboot header must contain 3 fields that are 4 byte aligned namely
dd 0x1BADB002 ; multiboot magic number
dd 0x0 ; architecture 0 - i386 - 32bits
dd - (0x1BADB002 + 0x00) ; the checksum field when added to the fields magic and flags must give zero.
global start ; set symbols from source code - our entry point
extern kmain ; kmain defined in kmain.c
start:
cli ; block interrupts - clear interrupt flag
mov esp, stack_space ; set stack pointer - GRUB does this for us and stack pointer is already set, but just to be sure we allocate some memory in BSS section
call kmain ; call our main function
hlt ; halt the CPU
section .bss align=16
resb 8192 ; 8KB for stack
stack_space:
#include "include/kernel.h"
unsigned char kbdus[2][128] = {{
0, // error
0, // esc
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'-', '=',
253, // backspace
0, // tab
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
255, // enter
0, // left ctrl
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
156, // left shift
'\\', 'z', 'x', 'c', 'v', 'b', 'n',
'm', ',', '.', '/',
157, // right SHIft
'*',
0, // left alt
' ', // space
155, // caps-lock
200, 201, 202, 203, 204, 205, 206, 207, 208, 209, // f1->f10
0, // numlock
0, // scroll lock
0, // home
150, // up
0, // page up
'-',
151, // left
0, // keypad 5
152, // right
'+',
0, // end
153, // down
0, // page down
0, // insert
0, // del
0, // Alt-SysRq ?
0, // Fn?
0, // Cmd/Super?
0, // f11
0, // f12
0, // undefined
},
{
0, // error
0, // esc
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
'_', '+',
253, // backspace
0, // tab
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}',
255, // enter
0, // left ctrl
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\"', '~',
156, // left shift
'|', 'Z', 'X', 'C', 'V', 'B', 'N',
'M', '<', '>', '?',
157, // right shift
'*',
0, // left alt
' ', // space
155, // caps-lock
200, 201, 202, 203, 204, 205, 206, 207, 208, 209, // f1->f10
0, // numlock
0, // scroll lock
0, // home
150, // up
0, // page up
'-',
151, // left
0, // keypad 5
152, // right
'+',
0, // end
153, // down
0, // page down
0, // insert
0, // del
0, // Alt-SysRq ?
0, // Fn?
0, // Cmd/Super?
0, // f11
0, // f12
0, // undefined
} };
void ft_putnbr(int n) // TODO add to lib VGA
{
unsigned int i;
i = n;
if (n < 0)
{
kputchar('-');
i = -n;
}
if (i < 10)
{
if (i == 0)
kputchar('0');
kputchar(kbdus[0][i + 1]);
}
else
{
ft_putnbr(i / 10);
ft_putnbr(i % 10);
}
}
/*
*
* outb: output byte in AL (here it's val and 0x0 in _scancode())
* to I/O port address in DX (here it's port and 0x60 in get_scancode())
*
* a: constraint mean use the A register (in this case AL)
* Nd: constraint mean:
* N: force 8-bit integer constant
* d: use the D register (in this case DX)
*
* x86 OUT (Output to Port) :
* Copies the value from the second operand (source operand)
* to the I/O port specified with the destination operand (first operand).
*
*/
static inline void outb(uint16_t port, uint8_t val)
{
asm volatile ( "outb %0, %1"
:
: "a"(val), "Nd"(port) );
}
/*
*
* inb: take I/O port address in DX (here it's port and 0x60 in get_scancode())
* and return the I/O port value in AL (here ret and c= in get_scancode())
*
* =a: constraint mean use the A register (in this case AL) and copy it to
* ret as output
*
* Nd: constraint mean:
* N: force 8-bit integer constant
* d: use the D register (in this case DX)
*
* x86 IN (Input from Port) :
* Copies the value from the I/O port
* specified with the second operand (source operand)
* to the destination operand (first operand).
*
*/
static inline uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
return ret;
}
static unsigned char get_scancode()
{
unsigned char c = 0;
do {
if(inb(0x64) & 0x01){
c = inb(0x60);
return c;
}
} while(1);
}
int getchar(_Bool caps) {
int c = get_scancode();
if (c > 128)
return (-kbdus[caps][c - 128]);
return kbdus[caps][c];
}
/*
* kmain.c
*/
#include "include/kernel.h"
#include "libk.h"
_Bool caps = 0;
/*
*
* outb: output byte in AL (here it's val and 0x0 in get_scancode())
* to I/O port address in DX (here it's port and 0x60 in get_scancode())
*
* a: constraint mean use the A register (in this case AL)
* Nd: constraint mean:
* N: force 8-bit integer constant
* d: use the D register (in this case DX)
*
* x86 OUT (Output to Port) :
* Copies the value from the second operand (source operand)
* to the I/O port specified with the destination operand (first operand).
*
*/
static inline void outb(uint16_t port, uint8_t val)
{
asm volatile ( "outb %0, %1"
:
: "a"(val), "Nd"(port) );
}
/*
*
* inb: take I/O port address in DX (here it's port and 0x60 in get_scancode())
* and return the I/O port value in AL (here ret and c= in get_scancode())
*
* =a: constraint mean use the A register (in this case AL) and copy it to
* ret as output
*
* Nd: constraint mean:
* N: force 8-bit integer constant
* d: use the D register (in this case DX)
*
* x86 IN (Input from Port) :
* Copies the value from the I/O port
* specified with the second operand (source operand)
* to the destination operand (first operand).
*
*/
static inline uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
return ret;
}
void enable_cursor(uint8_t cursor_start, uint8_t cursor_end)
{
outb(0x3D4, 0x0A);
outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start);
outb(0x3D4, 0x0B);
outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end);
}
void update_cursor(int x, int y)
{
uint16_t pos = y * VGA_WIDTH + x;
outb(0x3D4, 0x0F);
outb(0x3D5, (uint8_t) (pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
}
static void ft_write_on_screen(const char *str, char *vidptr)
{
unsigned int i, j = 0;
/*
* This loop write the string to video memory
*/
while (str[j] != '\0')
{
/* ASCII character */
vidptr[i] = str[j];
/* Color character */
vidptr[i+1] = RED;
/* Next character of our string 'Hello World' */
j++;
/* Next character written on kernel screen on 2 bytes */
i = i + 2;
}
}
static void ft_clear_screen()
{
char *video = (char*)VID_MEMORY;
unsigned int i = 0;
/*
* This loop clears the screen
* There are 25 lines each of 80 colums, each element takes 2 bytes
*/
while (i < MAX_COLUMNS * MAX_LINES * 2)
{
*video++ = ' '; /* Blank character on all screen */
*video++ = LIGHT_GREY; /* Each character on two bytes - character + colors */
i = i + 2;
}
}
int column(char *video)
{
return (((video - (char *)VID_MEMORY) / 2) % 80);
}
int line(char *video)
{
return (((video - (char *)VID_MEMORY) / 2) / 80);
}
void enter(char **video)
{
// if (line(*video) == 25)
// *video = (char *)VID_MEMORY;
// else
*video = (char *)VID_MEMORY + 80 * 2 * (line(*video) + 1);
// update_cursor(((*video-(char *)VID_MEMORY)/2)%80, ((*video-(char *)VID_MEMORY)/2)/80);
}