Now this should be complete
Added basic shell and fixed various bugs...now iceos should be "complete".
This commit is contained in:
parent
46e213e01c
commit
52bb2609ae
@ -21,12 +21,10 @@ iceOS already have/will have the following features:
|
|||||||
- [x] Bare metal booting;
|
- [x] Bare metal booting;
|
||||||
- [x] VGA driver;
|
- [x] VGA driver;
|
||||||
- [x] Interrupts implementation;
|
- [x] Interrupts implementation;
|
||||||
- [ ] PIC & PIT implementation;
|
- [x] PIC & PIT implementation;
|
||||||
- [ ] PS2 driver;
|
- [x] PS2 driver;
|
||||||
- [x] Support for x86 architecture;
|
- [x] Support for x86 architecture;
|
||||||
- [x] GRUB as bootloader;
|
- [x] GRUB as bootloader;
|
||||||
- [ ] Paging;
|
|
||||||
- [ ] Dynamic memory allocation(heap).
|
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
This project is made with different kind of resources and different kind of knowledges, before starting it i read/studied the following resources:
|
This project is made with different kind of resources and different kind of knowledges, before starting it i read/studied the following resources:
|
||||||
|
4
build.sh
4
build.sh
@ -27,6 +27,10 @@ cp kernel/drivers/*.o obj/
|
|||||||
make -C kernel/libc
|
make -C kernel/libc
|
||||||
cp kernel/libc/*.o obj/
|
cp kernel/libc/*.o obj/
|
||||||
|
|
||||||
|
# Shell
|
||||||
|
make -C kernel/shell
|
||||||
|
cp kernel/shell/*.o obj/
|
||||||
|
|
||||||
# Linking
|
# Linking
|
||||||
i686-elf-ld -melf_i386 -nostdlib -O2 -T link.ld -o isodir/boot/iceOS.bin obj/*.o
|
i686-elf-ld -melf_i386 -nostdlib -O2 -T link.ld -o isodir/boot/iceOS.bin obj/*.o
|
||||||
|
|
||||||
|
@ -63,7 +63,6 @@ void isr_handler(registers_t regs) {
|
|||||||
WHITE,
|
WHITE,
|
||||||
BLACK
|
BLACK
|
||||||
);
|
);
|
||||||
kprint((uint8_t*)"\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,110 @@
|
|||||||
* This device should not exists anymore in any modern computer
|
* This device should not exists anymore in any modern computer
|
||||||
* motherboard; however the CPU(or the motherboard?) should be able to
|
* motherboard; however the CPU(or the motherboard?) should be able to
|
||||||
* simulate it even if we're using some USB keyboard.
|
* simulate it even if we're using some USB keyboard.
|
||||||
|
* Apart of that the keyboard will be listen on IRQ1(33),
|
||||||
|
* so we have to register an ISR for that.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "isr.h"
|
#include "isr.h"
|
||||||
#include "ports.h"
|
#include "ports.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
#include "../libc/string.h"
|
#include "../shell/shell.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libc/stdio.h"
|
||||||
|
|
||||||
|
static void keyboard_callback();
|
||||||
|
|
||||||
|
/* Keyboard scan codes map , layout is: standard US keyboard */
|
||||||
|
uint8_t keyboard_scan_codes[] = {
|
||||||
|
0, (uint8_t)27, (uint8_t)'1', (uint8_t)'2', (uint8_t)'3', (uint8_t)'4', (uint8_t)'5', (uint8_t)'6', (uint8_t)'7', (uint8_t)'8',
|
||||||
|
(uint8_t)'0', (uint8_t)'0', (uint8_t)'-', (uint8_t)'=', (uint8_t)'\b',
|
||||||
|
(uint8_t)'\t',
|
||||||
|
(uint8_t)'q', (uint8_t)'w', (uint8_t)'e', (uint8_t)'r',
|
||||||
|
(uint8_t)'t', (uint8_t)'y', (uint8_t)'u', (uint8_t)'i', (uint8_t)'o', (uint8_t)'p', (uint8_t)'[', (uint8_t)']', (uint8_t)'\n',
|
||||||
|
0,
|
||||||
|
(uint8_t)'a', (uint8_t)'s', (uint8_t)'d', (uint8_t)'f', (uint8_t)'g', (uint8_t)'h', (uint8_t)'j', (uint8_t)'k', (uint8_t)'l', (uint8_t)';',
|
||||||
|
(uint8_t)'\'', (uint8_t)'`', 0,
|
||||||
|
(uint8_t)'\\', (uint8_t)'z', (uint8_t)'x', (uint8_t)'c', (uint8_t)'v', (uint8_t)'b', (uint8_t)'n',
|
||||||
|
(uint8_t)'m', (uint8_t)',', (uint8_t)'.', (uint8_t)'/', 0,
|
||||||
|
(uint8_t)'*',
|
||||||
|
|
||||||
|
0, // Alt
|
||||||
|
(uint8_t)' ', // Spacebar
|
||||||
|
0, // Caps lock
|
||||||
|
0, // 59 - F1 key
|
||||||
|
0, // 59 - F1 key
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, // F10
|
||||||
|
0, // 69 - Num lock
|
||||||
|
0, // Scroll lock
|
||||||
|
0, // Home key
|
||||||
|
0, // Up arrow
|
||||||
|
0, // Page up
|
||||||
|
(uint8_t)'-',
|
||||||
|
0, // Left arrow
|
||||||
|
0,
|
||||||
|
0, // Right arrow
|
||||||
|
(uint8_t)'+',
|
||||||
|
0, // 79 End key
|
||||||
|
0, // Down arrow
|
||||||
|
0, // Page down
|
||||||
|
0, // Insert key
|
||||||
|
0, // Delete key
|
||||||
|
0, 0, 0,
|
||||||
|
0, // F11 key
|
||||||
|
0, // F12 key
|
||||||
|
0 // Others key are undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t command[512]; // Max length of a single command
|
||||||
|
uint8_t temp[512];
|
||||||
|
uint32_t cmd_index = 0;
|
||||||
|
uint32_t shiftdown = 0;
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
for(uint16_t i = 0; i < 512; i++)
|
||||||
|
command[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_tmp(void) {
|
||||||
|
for(uint16_t i = 0; i < 512; i++)
|
||||||
|
command[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_callback() {
|
||||||
|
uint8_t scan_code = inb(KB_DATA_PORT); // Read from keyboard
|
||||||
|
uint8_t keycode = keyboard_scan_codes[scan_code]; // Get ASCII value
|
||||||
|
|
||||||
|
if(scan_code & 0x80) {
|
||||||
|
if(scan_code == 0xAA || scan_code == 0x86)
|
||||||
|
shiftdown = 0;
|
||||||
|
} else {
|
||||||
|
// Handle backspace
|
||||||
|
if(keycode == 0x08) {
|
||||||
|
if(cmd_index <= 0) // If at start of the prompt
|
||||||
|
return; // Do not delete it.
|
||||||
|
cmd_index--; // Otherwise go back
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < cmd_index; ++i)
|
||||||
|
temp[i] = command[i];
|
||||||
|
clear();
|
||||||
|
for(uint32_t i = 0; i < cmd_index; ++i)
|
||||||
|
command[i] = temp[i];
|
||||||
|
clear_tmp();
|
||||||
|
backspace();
|
||||||
|
} else if(keycode == 0x0A) { // Handle Enter
|
||||||
|
processCommand(command);
|
||||||
|
cmd_index = 0;
|
||||||
|
clear();
|
||||||
|
init_prompt();
|
||||||
|
} else {
|
||||||
|
printf("%c", keycode);
|
||||||
|
command[cmd_index] = keycode;
|
||||||
|
cmd_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_keyboard() {
|
||||||
|
register_interrupt_handler(IRQ1, &keyboard_callback);
|
||||||
|
}
|
@ -10,48 +10,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define KB_DATA_PORT 0x60 // Keyboard serial port
|
||||||
|
|
||||||
void init_keyboard();
|
void init_keyboard();
|
||||||
|
|
||||||
/* Keyboard scan codes map */
|
|
||||||
uint8_t *keyboard_scan_codes[] = {
|
|
||||||
0, (uint8_t*)27, (uint8_t*)'1', (uint8_t*)'2', (uint8_t*)'3', (uint8_t*)'4', (uint8_t*)'5', (uint8_t*)'6', (uint8_t*)'7', (uint8_t*)'8',
|
|
||||||
(uint8_t*)'0', (uint8_t*)'0', (uint8_t*)'-', (uint8_t*)'=', (uint8_t*)'\b',
|
|
||||||
(uint8_t*)'\t',
|
|
||||||
(uint8_t*)'q', (uint8_t*)'w', (uint8_t*)'e', (uint8_t*)'r',
|
|
||||||
(uint8_t*)'t', (uint8_t*)'y', (uint8_t*)'u', (uint8_t*)'i', (uint8_t*)'o', (uint8_t*)'p', (uint8_t*)'[', (uint8_t*)']', (uint8_t*)'\n',
|
|
||||||
0,
|
|
||||||
(uint8_t*)'a', (uint8_t*)'s', (uint8_t*)'d', (uint8_t*)'f', (uint8_t*)'g', (uint8_t*)'h', (uint8_t*)'j', (uint8_t*)'k', (uint8_t*)'l', (uint8_t*)';',
|
|
||||||
(uint8_t*)'\'', (uint8_t*)'`', 0,
|
|
||||||
(uint8_t*)'\\', (uint8_t*)'z', (uint8_t*)'x', (uint8_t*)'c', (uint8_t*)'v', (uint8_t*)'b', (uint8_t*)'n',
|
|
||||||
(uint8_t*)'m', (uint8_t*)',', (uint8_t*)'.', (uint8_t*)'/', 0,
|
|
||||||
(uint8_t*)'*',
|
|
||||||
|
|
||||||
0, // Alt
|
|
||||||
(uint8_t*)' ', // Spacebar
|
|
||||||
0, // Caps lock
|
|
||||||
0, // 59 - F1 key
|
|
||||||
0, // 59 - F1 key
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, // F10
|
|
||||||
0, // 69 - Num lock
|
|
||||||
0, // Scroll lock
|
|
||||||
0, // Home key
|
|
||||||
0, // Up arrow
|
|
||||||
0, // Page up
|
|
||||||
(uint8_t*)'-',
|
|
||||||
0, // Left arrow
|
|
||||||
0,
|
|
||||||
0, // Right arrow
|
|
||||||
(uint8_t*)'+',
|
|
||||||
0, // 79 End key
|
|
||||||
0, // Down arrow
|
|
||||||
0, // Page down
|
|
||||||
0, // Insert key
|
|
||||||
0, // Delete key
|
|
||||||
0, 0, 0,
|
|
||||||
0, // F11 key
|
|
||||||
0, // F12 key
|
|
||||||
0 // Others key are undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -8,7 +8,7 @@
|
|||||||
* @param port: Output port to send data to.
|
* @param port: Output port to send data to.
|
||||||
* @param data: The actual data to send to port
|
* @param data: The actual data to send to port
|
||||||
*/
|
*/
|
||||||
void outb(uint16_t port, uint8_t data);
|
void outb(uint16_t port, uint16_t data);
|
||||||
|
|
||||||
/* inb:
|
/* inb:
|
||||||
* Fetch data from a port, return a char
|
* Fetch data from a port, return a char
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
// Also define a 2 byte pointer because cells are 16 bits wide
|
// Also define a 2 byte pointer because cells are 16 bits wide
|
||||||
#define UVGA_PTR ((uint16_t *)VIDEO_MEM_ADDR)
|
#define UVGA_PTR ((uint16_t *)VIDEO_MEM_ADDR)
|
||||||
|
|
||||||
static uint32_t fb_col = 0; // X
|
static uint32_t fb_col = 1; // X
|
||||||
static uint32_t fb_row = 0; // Y
|
static uint32_t fb_row = 0; // Y
|
||||||
|
|
||||||
void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg) {
|
void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg) {
|
||||||
@ -70,12 +70,12 @@ void kprint(uint8_t *buf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init_prompt() {
|
void init_prompt() {
|
||||||
uint8_t *prompt = (uint8_t*)"\nuser@iceOS-$ ";
|
uint8_t *prompt = (uint8_t*)"\nring0@iceOS-$ ";
|
||||||
kprint_c(prompt, strlen(prompt), LIGHT_GREEN, BLACK);
|
kprint_c(prompt, strlen(prompt), LIGHT_RED, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_prompt() {
|
void clear_prompt() {
|
||||||
fb_col = 0;
|
fb_col = 1;
|
||||||
fb_row = 0;
|
fb_row = 0;
|
||||||
|
|
||||||
for(uint32_t i = 0; i < (VGA_WIDTH * VGA_HEIGHT); i++)
|
for(uint32_t i = 0; i < (VGA_WIDTH * VGA_HEIGHT); i++)
|
||||||
@ -100,6 +100,6 @@ void newline() {
|
|||||||
else // Otherwise scroll framebuffer
|
else // Otherwise scroll framebuffer
|
||||||
scroll();
|
scroll();
|
||||||
|
|
||||||
fb_col = 0;
|
fb_col = 1;
|
||||||
move_cursor(fb_col + (fb_row * VGA_WIDTH));
|
move_cursor(fb_col + (fb_row * VGA_WIDTH));
|
||||||
}
|
}
|
@ -9,21 +9,17 @@
|
|||||||
#include "drivers/gdt.h"
|
#include "drivers/gdt.h"
|
||||||
#include "drivers/idt.h"
|
#include "drivers/idt.h"
|
||||||
#include "drivers/timer.h"
|
#include "drivers/timer.h"
|
||||||
#include "libc/stdio.h"
|
#include "drivers/keyboard.h"
|
||||||
|
#include "shell/shell.h"
|
||||||
|
|
||||||
void kernel_main() {
|
void kernel_main() {
|
||||||
gdt_setup(); // Setup Global Descriptor Table
|
gdt_setup(); // Setup Global Descriptor Table
|
||||||
idt_setup(); // Setup Interrupt Descriptor Table
|
idt_setup(); // Setup Interrupt Descriptor Table
|
||||||
|
|
||||||
clear_prompt();
|
clear_prompt();
|
||||||
|
iceos_ascii_logo();
|
||||||
init_prompt(); // Initialize frame buffer
|
init_prompt(); // Initialize frame buffer
|
||||||
//puts("Hello World!");
|
init_keyboard(); // Initialize keyboard driver
|
||||||
init_timer(1);
|
|
||||||
|
|
||||||
/*
|
// init_timer(1); // Only for debug purposes
|
||||||
// Testing some interrupts
|
|
||||||
asm("int $0"); // Division by zero
|
|
||||||
asm("int $4"); // Stack overflow
|
|
||||||
asm("int $1"); // Page fault
|
|
||||||
*/
|
|
||||||
}
|
}
|
@ -32,7 +32,7 @@ int printf(const char *format, ...) {
|
|||||||
kprint(buf);
|
kprint(buf);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
s = va_arg(ap, uint8_t*);
|
c = (uint8_t)va_arg(ap, uint32_t);
|
||||||
kprint_c(&c, 1, WHITE, BLACK);
|
kprint_c(&c, 1, WHITE, BLACK);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
@ -49,6 +49,11 @@ int printf(const char *format, ...) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int printf_color(const char *format, uint8_t fg, uint8_t bg) {
|
||||||
|
kprint_c((uint8_t*)format, strlen((uint8_t*)format), fg, bg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void puts(const char *buf) {
|
void puts(const char *buf) {
|
||||||
printf("%s\n", buf);
|
printf("%s\n", buf);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
int printf(const char *format, ...);
|
int printf(const char *format, ...);
|
||||||
|
int printf_color(const char *format, uint8_t fg, uint8_t bg); // Only for string for now
|
||||||
void puts(const char *buf);
|
void puts(const char *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
10
kernel/shell/Makefile
Normal file
10
kernel/shell/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
OBJS = shell.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 $@
|
87
kernel/shell/shell.c
Normal file
87
kernel/shell/shell.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "shell.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
#include "../drivers/tty.h"
|
||||||
|
#include "../drivers/ports.h"
|
||||||
|
|
||||||
|
void helper() {
|
||||||
|
puts("\nList of available commands:\n"
|
||||||
|
"\nhelp - Print this helper"
|
||||||
|
"\nint - Test some interrupts"
|
||||||
|
"\nbanner - Show banner"
|
||||||
|
"\nclear, cls - Clear the screen"
|
||||||
|
"\nabout - About this kernel"
|
||||||
|
"\nreboot - Reboot the system"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_interrupts() {
|
||||||
|
// Testing some interrupts
|
||||||
|
asm("int $0"); // Division by zero
|
||||||
|
asm("int $4"); // Stack overflow
|
||||||
|
asm("int $1"); // Page fault
|
||||||
|
}
|
||||||
|
|
||||||
|
void about() {
|
||||||
|
printf_color("\n====== IceOS v0.0.1 (c) 2019 Marco 'icebit' Cetica ======\n\n",
|
||||||
|
LIGHT_CYAN, BLACK);
|
||||||
|
printf_color(
|
||||||
|
"iceOS is a x86 monolithic kernel written in C from scratch.\n"
|
||||||
|
"This project doesn't aim to be a fully functional operating system\n"
|
||||||
|
"with tons of drivers and graphical applications,\nit's just a learning tool"
|
||||||
|
"to teach myself concepts like\nOperating Systems, Computer Architecture and Digital Electronics.\n"
|
||||||
|
"\n\n"
|
||||||
|
"iceOS comes with the following features:\n"
|
||||||
|
"- Bare metal booting;\n"
|
||||||
|
"- VGA driver;\n"
|
||||||
|
"- Interrupts implementation;\n"
|
||||||
|
"- PIC & PIT implementation;\n"
|
||||||
|
"- PS2 driver;\n"
|
||||||
|
"- Support for x86 architecture;\n"
|
||||||
|
"- GRUB as bootloader;\n",
|
||||||
|
LIGHT_GREEN, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reboot() {
|
||||||
|
uint8_t tmp;
|
||||||
|
asm("cli"); // First disable all interrupts
|
||||||
|
|
||||||
|
// Clear keyboard buffers
|
||||||
|
do {
|
||||||
|
tmp = inb(0x64); // Keyboard interface
|
||||||
|
if(check_flag(tmp, 0) != 0)
|
||||||
|
inb(0x60); // Clear keyboard data
|
||||||
|
} while(check_flag(tmp, 1) != 0);
|
||||||
|
|
||||||
|
outb(0x64, 0xFE); // Reset the CPU
|
||||||
|
}
|
||||||
|
|
||||||
|
void iceos_ascii_logo() {
|
||||||
|
printf_color(
|
||||||
|
"\n\n### ##### ####### ####### #####\n"
|
||||||
|
" # # # # # # # #\n"
|
||||||
|
" # # # # # # \n"
|
||||||
|
" # # ##### # # ##### \n"
|
||||||
|
" # # # # # # \n"
|
||||||
|
" # # # # # # # # \n"
|
||||||
|
"### ##### ####### ####### ##### \n"
|
||||||
|
"\n (c) Marco Cetica 2019\n",
|
||||||
|
LIGHT_MAGENTA, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void processCommand(uint8_t *cmd) {
|
||||||
|
if(strcmp(cmd, (uint8_t*)"help") == 0)
|
||||||
|
helper();
|
||||||
|
else if(strcmp(cmd, (uint8_t*)"int") == 0)
|
||||||
|
test_interrupts();
|
||||||
|
else if(strcmp(cmd, (uint8_t*)"clear") == 0 || strcmp(cmd, (uint8_t*)"cls") == 0)
|
||||||
|
clear_prompt();
|
||||||
|
else if(strcmp(cmd, (uint8_t*)"about") == 0)
|
||||||
|
about();
|
||||||
|
else if(strcmp(cmd, (uint8_t*)"banner") == 0)
|
||||||
|
iceos_ascii_logo();
|
||||||
|
else if(strcmp(cmd, (uint8_t*)"reboot") == 0)
|
||||||
|
reboot();
|
||||||
|
else
|
||||||
|
puts("\nCommand not found!");
|
||||||
|
}
|
20
kernel/shell/shell.h
Normal file
20
kernel/shell/shell.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/**************************************
|
||||||
|
* iceOS Kernel *
|
||||||
|
* Developed by Marco 'icebit' Cetica *
|
||||||
|
* (c) 2019 *
|
||||||
|
* Released under GPLv3 *
|
||||||
|
* https://github.com/ice-bit/iceOS *
|
||||||
|
***************************************/
|
||||||
|
#ifndef _SHELL_H_
|
||||||
|
#define _SHELL_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define bit(n) (1 << (n))
|
||||||
|
#define check_flag(flags, n) ((flags) & bit(n))
|
||||||
|
|
||||||
|
void helper();
|
||||||
|
void processCommand(uint8_t *cmd);
|
||||||
|
void iceos_ascii_logo();
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user