Added:
- TTY driver - VGA driver - kernel's main function - Makefiles *NOTE*: iceOS not works at this stage.
This commit is contained in:
parent
bb59c7532f
commit
bec03e3d1b
10
Makefile
10
Makefile
@ -0,0 +1,10 @@
|
|||||||
|
iso:
|
||||||
|
grub-mkrescue iso_root -o iceOS.iso
|
||||||
|
|
||||||
|
run:
|
||||||
|
qemu-system-x86_64 -cdrom iceOS.iso
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf obj/ kernel/*.o kernel/cpu/*.o iso_root/boot/kernel.elf
|
||||||
|
rm -rf kernel/drivers/*.o kernel/libc/*.o
|
||||||
|
rm -rf PyramidKernel.iso bochslog.txt commands
|
30
build.sh
Normal file → Executable file
30
build.sh
Normal file → Executable file
@ -0,0 +1,30 @@
|
|||||||
|
# grub config file
|
||||||
|
mkdir -p iso_root/boot/grub/
|
||||||
|
cat iso_root/boot/grub/grub.cfg <<EOF
|
||||||
|
set timeout = 0
|
||||||
|
set default = 0
|
||||||
|
|
||||||
|
menuentry "iceOS" {
|
||||||
|
multiboot2 /boot/kernel.elf
|
||||||
|
boot
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# CPU
|
||||||
|
mkdir -p obj/
|
||||||
|
make -C kernel/cpu
|
||||||
|
cp kernel/cpu*.o obj/
|
||||||
|
|
||||||
|
# Kernel
|
||||||
|
make -C kernel/
|
||||||
|
cp kernel/*.o obj/
|
||||||
|
|
||||||
|
# Drivers
|
||||||
|
make -C kernel/drivers/
|
||||||
|
cp kernel/drivers/*.o obj/
|
||||||
|
|
||||||
|
# Libc
|
||||||
|
make -C kernel/libc
|
||||||
|
cp kernel/libc/*.o obj/
|
||||||
|
|
||||||
|
i686-elf-ld -melf_i386 -nostdlib -O2 -T link.ld -o iso_root/boot/kernel.elf obj/*.o
|
@ -0,0 +1,10 @@
|
|||||||
|
OBJS = kernel_main.o
|
||||||
|
|
||||||
|
CC = i686-elf-gcc # cross-compiler
|
||||||
|
CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
|
||||||
|
|
||||||
|
|
||||||
|
all:${OBJS}
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
@ -6,14 +6,14 @@
|
|||||||
; https://github.com/ice-bit/iceOS ;
|
; https://github.com/ice-bit/iceOS ;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
global kernel_loader
|
global kernel_load
|
||||||
extern main
|
extern kernel_main
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
kernel_loader:
|
kernel_loader:
|
||||||
mov esp, kernel_stack + KERNEL_STACK_SZ ; Stack pointer
|
mov esp, kernel_stack + KERNEL_STACK_SZ ; Stack pointer
|
||||||
push ebx
|
push ebx
|
||||||
call main ; jump to kernel's main function
|
call kernel_main ; jump to kernel's main function
|
||||||
.loop:
|
.loop:
|
||||||
jmp .loop ; endless loop
|
jmp .loop ; endless loop
|
||||||
|
|
||||||
|
10
kernel/drivers/Makefile
Normal file
10
kernel/drivers/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
OBJS = tty.o
|
||||||
|
|
||||||
|
CC = i686-elf-gcc # cross-compiler
|
||||||
|
CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
|
||||||
|
|
||||||
|
|
||||||
|
all:${OBJS}
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
20
kernel/drivers/ports.h
Normal file
20
kernel/drivers/ports.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef _PORTS_H
|
||||||
|
#define _PORTS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* outb:
|
||||||
|
* Redirect data to port(high level interface for ports.asm)
|
||||||
|
* @param port: Output port to send data to.
|
||||||
|
* @param data: The actual data to send to port
|
||||||
|
*/
|
||||||
|
void outb(uint16_t port, uint8_t data);
|
||||||
|
|
||||||
|
/* inb:
|
||||||
|
* Fetch data from a port, return a char
|
||||||
|
* @param port: Input port to read data from.
|
||||||
|
*/
|
||||||
|
uint8_t inb(uint16_t port);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
109
kernel/drivers/tty.c
Normal file
109
kernel/drivers/tty.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#include "tty.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
#include "ports.h"
|
||||||
|
|
||||||
|
#define VGA_PTR ((uint8_t*) VIDEO_MEM_ADDR) // Pointer to frame buffer
|
||||||
|
// Also define a 2 byte pointer because cells are 16 bits wide
|
||||||
|
#define UVGA_PTR ((uint16_t *)VIDEO_MEM_ADDR)
|
||||||
|
|
||||||
|
static uint32_t fb_col = 0; // X
|
||||||
|
static uint32_t fb_row = 0; // Y
|
||||||
|
|
||||||
|
void write_cell(int16_t i, int8_t c, uint8_t fg, uint8_t bg) {
|
||||||
|
uint8_t *fb = VGA_PTR;
|
||||||
|
fb[i*2] = c;
|
||||||
|
fb[i*2 + 1] = ((bg & 0x0F) << 4) | (fg | 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_cursor(uint16_t pos) {
|
||||||
|
outb(VGA_CMD_PORT, VGA_HIGH_BYTE);
|
||||||
|
outb(VGA_DATA_PORT, ((pos >> 8) & 0x00FF));
|
||||||
|
outb(VGA_CMD_PORT, VGA_LOW_BYTE);
|
||||||
|
outb(VGA_DATA_PORT, pos & 0x00FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cursor_adv() {
|
||||||
|
if(fb_col < VGA_WIDTH - 1)
|
||||||
|
fb_col--;
|
||||||
|
else
|
||||||
|
newline();
|
||||||
|
|
||||||
|
move_cursor(fb_col + (fb_row * VGA_WIDTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cursor_prev() {
|
||||||
|
if(fb_col == 0) {
|
||||||
|
if(fb_row == 0)
|
||||||
|
return; // If first row do not do anything
|
||||||
|
fb_col = VGA_WIDTH - 1;
|
||||||
|
fb_row--;
|
||||||
|
} else
|
||||||
|
fb_col--;
|
||||||
|
move_cursor(fb_col + (fb_row * VGA_WIDTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
void backspace() {
|
||||||
|
uint16_t pos;
|
||||||
|
uint8_t c = ' ';
|
||||||
|
|
||||||
|
fb_col--;
|
||||||
|
pos = fb_col + (fb_row * VGA_WIDTH);
|
||||||
|
write_cell(pos, c, WHITE, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg) {
|
||||||
|
uint16_t pos;
|
||||||
|
for(uint32_t i = 0; i < len; i++) {
|
||||||
|
uint8_t c = buf[i];
|
||||||
|
if(c == '\n' || c == '\r')
|
||||||
|
newline();
|
||||||
|
else if(c == '\t') {
|
||||||
|
pos = fb_col + (fb_row * VGA_WIDTH);
|
||||||
|
write_cell(pos, " ", fg, bg);
|
||||||
|
cursor_adv();
|
||||||
|
} else {
|
||||||
|
pos = fb_col + (fb_row * VGA_WIDTH);
|
||||||
|
write_cell(pos, c, fg, bg);
|
||||||
|
cursor_adv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kprint(uint8_t *buf) {
|
||||||
|
kprint_c(buf, strlen(buf), WHITE, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_prompt() {
|
||||||
|
const uint8_t *prompt = "\nuser@iceOS-$";
|
||||||
|
kprint_c(prompt, strlen(prompt), GREEN, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_prompt() {
|
||||||
|
fb_col = 0;
|
||||||
|
fb_row = 0;
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < (VGA_WIDTH * VGA_HEIGHT); i++)
|
||||||
|
write_cell(i, ' ', WHITE, BLACK);
|
||||||
|
move_cursor(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_row(uint8_t row) {
|
||||||
|
for(size_t i = 0; i < VGA_WIDTH; i++)
|
||||||
|
write_cell((row*VGA_WIDTH)+i, ' ', WHITE, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scroll() {
|
||||||
|
uint16_t *fb = UVGA_PTR;
|
||||||
|
memmove(fb, fb+VGA_WIDTH, VGA_WIDTH*2*(VGA_HEIGHT*2-1));
|
||||||
|
clear_row(VGA_HEIGHT - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void newline() {
|
||||||
|
if(fb_row < VGA_HEIGHT - 1) // If there's at least one cell add it
|
||||||
|
fb_row++;
|
||||||
|
else // Otherwise scroll framebuffer
|
||||||
|
scroll();
|
||||||
|
|
||||||
|
fb_col = 0;
|
||||||
|
move_cursor(fb_col + (fb_row * VGA_WIDTH));
|
||||||
|
}
|
60
kernel/drivers/tty.h
Normal file
60
kernel/drivers/tty.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/**************************************
|
||||||
|
* iceOS Kernel *
|
||||||
|
* Developed by Marco 'icebit' Cetica *
|
||||||
|
* (c) 2019 *
|
||||||
|
* Released under GPLv3 *
|
||||||
|
* https://github.com/ice-bit/iceOS *
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
#ifndef _TTY_H_
|
||||||
|
#define _TTY_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// VGA colors
|
||||||
|
enum TTY_COLORS {
|
||||||
|
BLACK, // 0
|
||||||
|
BLUE,
|
||||||
|
GREEN,
|
||||||
|
CYAN,
|
||||||
|
RED,
|
||||||
|
MAGENTA,
|
||||||
|
BROWN,
|
||||||
|
LIGHT_GREY,
|
||||||
|
DARK_GREY,
|
||||||
|
LIGHT_BLUE,
|
||||||
|
LIGHT_GREEN,
|
||||||
|
LIGHT_CYAN,
|
||||||
|
LIGHT_RED,
|
||||||
|
LIGHT_MAGENTA,
|
||||||
|
LIGHT_BROWN,
|
||||||
|
WHITE // 15
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Framebuffer properties */
|
||||||
|
#define VIDEO_MEM_ADDR 0x000B8000 // frame buffer address
|
||||||
|
#define VGA_WIDTH 80
|
||||||
|
#define VGA_HEIGHT 25
|
||||||
|
|
||||||
|
/* VGA I/O ports */
|
||||||
|
#define VGA_CMD_PORT 0x3D4
|
||||||
|
#define VGA_DATA_PORT 0x3D5
|
||||||
|
|
||||||
|
/* VGA I/O ports commands */
|
||||||
|
#define VGA_HIGH_BYTE 14
|
||||||
|
#define VGA_LOW_BYTE 15
|
||||||
|
|
||||||
|
/* Kernel's VGA API */
|
||||||
|
void write_cell(int16_t i, int8_t c, uint8_t fg, uint8_t bg);
|
||||||
|
void move_cursor(uint16_t pos);
|
||||||
|
void cursor_adv();
|
||||||
|
void backspace();
|
||||||
|
void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg);
|
||||||
|
void kprint(uint8_t *buf);
|
||||||
|
void init_prompt();
|
||||||
|
void clear_prompt();
|
||||||
|
void clear_row(uint8_t row);
|
||||||
|
void scroll(); // Scroll one row
|
||||||
|
void newline();
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,9 @@
|
|||||||
|
#include "drivers/tty.h"
|
||||||
|
#include "libc/stdio.h"
|
||||||
|
|
||||||
|
void kernel_main() {
|
||||||
|
clear_prompt();
|
||||||
|
init_prompt();
|
||||||
|
|
||||||
|
puts("Hello World!");
|
||||||
|
}
|
10
kernel/libc/Makefile
Normal file
10
kernel/libc/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
OBJS = stdio.o string.o
|
||||||
|
|
||||||
|
CC = i686-elf-gcc # cross-compiler
|
||||||
|
CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
|
||||||
|
|
||||||
|
|
||||||
|
all:${OBJS}
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
@ -1,7 +1,6 @@
|
|||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "drivers/shell.h"
|
#include "../drivers/tty.h"
|
||||||
|
|
||||||
|
|
||||||
int printf(const char *format, ...) {
|
int printf(const char *format, ...) {
|
||||||
char buf[20],c,*s;
|
char buf[20],c,*s;
|
||||||
@ -20,32 +19,36 @@ int printf(const char *format, ...) {
|
|||||||
case 'i':
|
case 'i':
|
||||||
val = va_arg(ap, int);
|
val = va_arg(ap, int);
|
||||||
itoa(val, buf, 10);
|
itoa(val, buf, 10);
|
||||||
printk(buf);
|
kprint(buf);
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
uval = va_arg(ap, uint32_t);
|
uval = va_arg(ap, uint32_t);
|
||||||
uitoa(uval, buf, 16);
|
uitoa(uval, buf, 16);
|
||||||
printk(buf);
|
kprint(buf);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
uval = va_arg(ap, uint32_t);
|
uval = va_arg(ap, uint32_t);
|
||||||
uitoa(uval, buf, 10);
|
uitoa(uval, buf, 10);
|
||||||
printk(buf);
|
kprint(buf);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
s = va_arg(ap, char*);
|
s = va_arg(ap, char*);
|
||||||
printk_c(&c, 1);
|
kprint_c(&c, 1, WHITE, BLACK);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
s = va_arg(ap, char*);
|
s = va_arg(ap, char*);
|
||||||
printk(s);
|
kprint(s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk_c((char*)format+1, 1);
|
kprint_c((char*)format+1, 1, WHITE, BLACK);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
printk_c((char*)format+1, 1);
|
kprint_c((char*)format+1, 1, WHITE, BLACK);
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void puts(int8_t *buf) {
|
||||||
|
printf("%s\n", buf);
|
||||||
|
}
|
@ -1,10 +1,19 @@
|
|||||||
|
/**************************************
|
||||||
|
* iceOS Kernel *
|
||||||
|
* Developed by Marco 'icebit' Cetica *
|
||||||
|
* (c) 2019 *
|
||||||
|
* Released under GPLv3 *
|
||||||
|
* https://github.com/ice-bit/iceOS *
|
||||||
|
***************************************/
|
||||||
|
|
||||||
#ifndef _STDIO_H_
|
#ifndef _STDIO_H_
|
||||||
#define _STDIO_H
|
#define _STDIO_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
int printf(const char *format, ...);
|
int printf(const char *format, ...);
|
||||||
|
void puts(uint8_t *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user