add keyboard buffer and shell-like interface

This commit is contained in:
hippoz 2021-06-26 15:00:58 +03:00
parent de59d0d549
commit e5f54a0cfb
Signed by untrusted user who does not match committer: hippoz
GPG key ID: 7C52899193467641
14 changed files with 571 additions and 791 deletions

View file

@ -13,7 +13,7 @@ NASMFLAGS += -felf32
BIN = sysroot/boot/hhhos.bin
ISO = build/HhhOS.iso
DIRS = build build/boot build/std build/drivers build/drivers/terminal build/drivers/idt build/drivers/device build/drivers/keyboard build/drivers/pic build/drivers/ahci build/drivers/ide
DIRS = build build/boot build/std build/drivers build/drivers/terminal build/drivers/idt build/drivers/device build/drivers/keyboard build/drivers/pic build/drivers/ide
OBJS = build/boot/boot.o build/boot/kernel.o build/std/string.o build/drivers/terminal/terminal.o build/drivers/idt/idt.o \
build/drivers/idt/isr.o build/std/util.o build/drivers/device/device.o build/drivers/keyboard/keyboard.o build/drivers/pic/pic.o build/drivers/ide/ide.o

View file

@ -6,28 +6,61 @@
#include <drivers/device/device.h>
#include <drivers/ide/ide.h>
/* Check if the compiler thinks you are targeting the wrong operating system. */
#if defined(__linux__)
#error "You are not using a cross-compiler, you will most certainly run into trouble"
#endif
/* This operating system will only work for the 32-bit ix86 targets. */
#if !defined(__i386__)
#error "This operating system needs to be compiled with a ix86-elf compiler"
#endif
uint8_t is_running = 1;
int keyboard_descriptor = 0;
int terminal_descriptor = 0;
void shell() {
terminal_writestring("hello yes");
while (is_running) {
terminal_writestring("\n> ");
while (true) {
unsigned char scancode = read(keyboard_descriptor, NULL);
if (!scancode) continue;
bool special = true;
bool finished = false;
switch (scancode) {
case 72:
terminal_row--;
break;
case 75:
terminal_column--;
break;
case 77:
terminal_column++;
break;
case 80:
terminal_row++;
break;
case 0x1C:
finished = true;
break;
default:
special = false;
}
if (finished) break;
if (!special) terminal_putchar(keyboard_get_key_from_scancode(scancode));
terminal_updatecursor();
}
}
}
void kmain() {
terminal_initialize();
terminal_writeline("Initializing terminal... done");
terminal_descriptor = terminal_initialize();
terminal_writestring("Initializing terminal... done, descriptor: ");
terminal_writeline(itoa(terminal_descriptor));
terminal_writestring("Preparing interrupts... ");
pic_init();
isr_install();
terminal_writeline("done");
terminal_writestring("Preparing keyboard... ");
int keyboard_descriptor = keyboard_init();
keyboard_descriptor = keyboard_init();
terminal_writestring("done, descriptor: ");
terminal_writeline(itoa(keyboard_descriptor));
@ -41,20 +74,10 @@ void kmain() {
} else {
terminal_writeline("no");
}
terminal_writestring("Is keyboard enabled? ");
if (are_interrupts_enabled() == 1) {
terminal_writeline("yes");
} else {
terminal_writeline("no");
}
terminal_writestring("kmain memory address: ");
terminal_writeline(itoa(kmain));
terminal_writeline("----------");
terminal_writeline("hello yes");
terminal_writestring("> ");
while (is_running);
shell();
}

View file

@ -1,213 +0,0 @@
#include <stdint.h>
#include <drivers/ahci/ahci.h>
#include <drivers/terminal/terminal.h>
#include <std/util.h>
#include <std/string.h>
#include <std/inline.h>
// AHCI driver, source: https://wiki.osdev.org/AHCI
static void trace_ahci(const char* message, int i) {
terminal_writestring(message);
terminal_writeline(itoa(i));
}
// Check device type
static int check_type(HBA_PORT *port) {
uint32_t ssts = port->ssts;
uint8_t ipm = (ssts >> 8) & 0x0F;
uint8_t det = ssts & 0x0F;
if (det != HBA_PORT_DET_PRESENT) // Check drive status
return AHCI_DEV_NULL;
if (ipm != HBA_PORT_IPM_ACTIVE)
return AHCI_DEV_NULL;
switch (port->sig)
{
case SATA_SIG_ATAPI:
return AHCI_DEV_SATAPI;
case SATA_SIG_SEMB:
return AHCI_DEV_SEMB;
case SATA_SIG_PM:
return AHCI_DEV_PM;
default:
return AHCI_DEV_SATA;
}
}
void probe_port(HBA_MEM *abar) {
// Search disk in implemented ports
uint32_t pi = abar->pi;
int i = 0;
while (i<32)
{
if (pi & 1)
{
int dt = check_type(&abar->ports[i]);
if (dt == AHCI_DEV_SATA)
{
trace_ahci("SATA drive found at port: ", i);
}
else if (dt == AHCI_DEV_SATAPI)
{
trace_ahci("SATAPI drive found at port: ", i);
}
else if (dt == AHCI_DEV_SEMB)
{
trace_ahci("SEMB drive found at port: ", i);
}
else if (dt == AHCI_DEV_PM)
{
trace_ahci("PM drive found at port: ", i);
}
else
{
//trace_ahci("No drive found at port: ", i);
}
}
pi >>= 1;
i ++;
}
}
uint32_t pci_config_read_word(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
uint32_t address;
uint32_t lbus = (uint32_t)bus;
uint32_t lslot = (uint32_t)slot;
uint32_t lfunc = (uint32_t)func;
uint64_t tmp = 0;
/* create configuration address as per Figure 1 */
address = (uint32_t)((lbus << 16) | (lslot << 11) |
(lfunc << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
/* write out the address */
outportl(0xCF8, address);
/* read in the data */
/* (offset & 2) * 8) = 0 will choose the first word of the 32 bits register */
if (offset == 0x24)
tmp = inportb(0xCFC) ;
else
tmp = (uint16_t)( (inportb(0xCFC) >> ((offset & 2) * 8) ) & 0xffff);
return (tmp);
}
uint16_t get_vendor_id(uint8_t bus, uint8_t slot)
{
return pci_config_read_word(bus, slot, 0, 0);
}
uint16_t get_device_id(uint8_t bus, uint8_t slot)
{
return pci_config_read_word(bus, slot, 0, 2);
}
uint64_t check_device(uint8_t bus, uint8_t device) {
//uint8_t function = 0;
uint16_t vendorID = get_vendor_id(bus, device);
if(vendorID == 0xFFFF) return 0; // Device doesn't exist
uint16_t deviceID = get_device_id(bus, device);
return pci_config_read_word(bus, device, 0, 0x24);
return 0;
}
uint64_t check_all_buses(void)
{
uint16_t bus;
uint8_t device;
uint64_t bar5;
for(bus = 0; bus < 256; bus++)
{
for(device = 0; device < 32; device++)
{
bar5 = check_device(bus, device);
if (bar5 == 0) return 0;
probe_port((HBA_MEM*)bar5);
return bar5;
}
}
return 0;
}
// Start command engine
void start_cmd(HBA_PORT *port)
{
// Wait until CR (bit15) is cleared
while (port->cmd & HBA_PxCMD_CR);
// Set FRE (bit4) and ST (bit0)
port->cmd |= HBA_PxCMD_FRE;
port->cmd |= HBA_PxCMD_ST;
}
// Stop command engine
void stop_cmd(HBA_PORT *port)
{
// Clear ST (bit0)
port->cmd &= ~HBA_PxCMD_ST;
// Clear FRE (bit4)
port->cmd &= ~HBA_PxCMD_FRE;
// Wait until FR (bit14), CR (bit15) are cleared
while(1)
{
if (port->cmd & HBA_PxCMD_FR)
continue;
if (port->cmd & HBA_PxCMD_CR)
continue;
break;
}
}
void port_rebase(HBA_PORT *port, int portno)
{
stop_cmd(port); // Stop command engine
// Command list offset: 1K*portno
// Command list entry size = 32
// Command list entry maxim count = 32
// Command list maxim size = 32*32 = 1K per port
port->clb = AHCI_BASE + (portno<<10);
port->clbu = 0;
memset((void*)(port->clb), 0, 1024);
// FIS offset: 32K+256*portno
// FIS entry size = 256 bytes per port
port->fb = AHCI_BASE + (32<<10) + (portno<<8);
port->fbu = 0;
memset((void*)(port->fb), 0, 256);
// Command table offset: 40K + 8K*portno
// Command table size = 256*32 = 8K per port
HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*)(port->clb);
for (int i=0; i<32; i++)
{
cmdheader[i].prdtl = 8; // 8 prdt entries per command table
// 256 bytes per command table, 64+16+48+16*8
// Command table offset: 40K + 8K*portno + cmdheader_index*256
cmdheader[i].ctba = AHCI_BASE + (40<<10) + (portno<<13) + (i<<8);
cmdheader[i].ctbau = 0;
memset((void*)cmdheader[i].ctba, 0, 256);
}
start_cmd(port); // Start command engine
}
void ahci_init(void) {
uint64_t bar5 = check_all_buses();
if (bar5 == 0) {
terminal_writeline("Error: Could not find AHCI device");
return;
}
terminal_writestring("Found AHCI device at: ");
terminal_writeline(itoa(bar5));
}

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,8 @@
#include <drivers/keyboard/keyboard.h>
#include <drivers/device/device.h>
unsigned char kbdbuf[KBD_BUF_SIZE];
unsigned char kbdus[128] = {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
'9', '0', '-', '=', '\b', /* Backspace */
@ -45,6 +47,18 @@ unsigned char kbdus[128] = {
uint8_t lastkey = 0;
uint8_t __kbd_enabled = 0;
void keyboard_buffer_push_key(unsigned char scancode) {
kbdbuf[lastkey++] = scancode;
}
unsigned char keyboard_buffer_pop_key() {
uint8_t index = lastkey--;
unsigned char scancode = kbdbuf[index];
kbdbuf[index] = 0;
return scancode;
}
unsigned char keyboard_get_key_from_scancode(unsigned char scancode) {
return kbdus[scancode];
}
@ -52,34 +66,14 @@ unsigned char keyboard_get_key_from_scancode(unsigned char scancode) {
__attribute__((interrupt)) static void keyboard_irq(struct interrupt_frame* frame) {
unsigned char scancode = inportb(0x60);
bool special = true;
switch (scancode) {
case 72:
terminal_row--;
break;
case 75:
terminal_column--;
break;
case 77:
terminal_column++;
break;
case 80:
terminal_row++;
break;
default:
special = false;
}
if (scancode & 128) {
// This is a release scancode, just ignore it
pic_send_eoi(1);
return;
}
if (!special) terminal_putchar(keyboard_get_key_from_scancode(scancode));
terminal_updatecursor();
pic_send_eoi(1);
keyboard_buffer_push_key(scancode);
pic_send_eoi(1);
}
uint8_t keyboard_enabled(void) {
@ -87,11 +81,7 @@ uint8_t keyboard_enabled(void) {
}
void* keyboard_read(void* data) {
if (inportb(0x64) & 1) {
return keyboard_get_key_from_scancode(inportb(0x60));
} else {
return -1;
}
return keyboard_buffer_pop_key();
}
void* keyboard_write(void* data) {
@ -109,7 +99,5 @@ int keyboard_init(void) {
read: &keyboard_read
};
int keyboard_descriptor = push_device(keyboard_device);
return keyboard_descriptor;
return push_device(keyboard_device);
}

View file

@ -0,0 +1,18 @@
#include <drivers/tar/tar.h>
#include <std/util.h>
#include <drivers/device/device.h>
struct tar_header* tar_seek(int fd, char filename[100]) {
unsigned int i;
unsigned int addr;
for (i = 0; ; i++)
{
struct tar_header *header = (struct tar_header *)read(fd, addr);
if (header->filename == filename) return header;
unsigned int size = getsize(header->size);
addr += ((size / 512) + 1);
if (size % 512) addr++;
}
}

View file

@ -1,4 +1,5 @@
#include <drivers/terminal/terminal.h>
#include <drivers/device/device.h>
size_t terminal_row;
size_t terminal_column;
@ -14,12 +15,39 @@ void terminal_clear(void) {
}
}
void terminal_initialize(void) {
/*
static inline void terminal_writestring(const char* data) {
terminal_write(data, strlen(data));
}
static inline void terminal_writeline(const char* data) {
terminal_writestring(data);
terminal_putchar('\n');
}
*/
void* terminal_devread(void* data) {
return NULL;
}
void* terminal_devwrite(void* data) {
terminal_putchar(*((char*)data));
return NULL;
}
int terminal_initialize(void) {
terminal_row = 0;
terminal_column = 0;
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
terminal_buffer = (uint16_t*) 0xB8000;
terminal_clear();
struct device terminal_device = {
write: &terminal_devwrite,
read: &terminal_devread
};
return push_device(terminal_device);
}
void terminal_setcolor(uint8_t color) {

View file

@ -36,4 +36,16 @@ char* itoa(int res) {
}
return ret;
}
unsigned int atoi(const char *in)
{
unsigned int size = 0;
unsigned int j;
unsigned int count = 1;
for (j = 11; j > 0; j--, count *= 8)
size += ((in[j - 1] - '0') * count);
return size;
}

View file

View file

@ -104,7 +104,6 @@ extern "C" {
void ide_init();
#ifdef __cplusplus
}
#endif

View file

@ -10,6 +10,8 @@
extern "C" {
#endif
#define KBD_BUF_SIZE 256
int keyboard_init(void);
uint8_t keyboard_enabled(void);

27
include/drivers/tar/tar.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef _TAR_H
#define _TAR_H 1
#ifdef __cplusplus
extern "C" {
#endif
struct tar_header
{
char filename[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag[1];
char padding[355];
};
struct tar_header* tar_seek(int fd, char filename[100]);
#ifdef __cplusplus
}
#endif
#endif /* _TAR_H */

View file

@ -47,7 +47,7 @@ extern uint8_t terminal_color;
extern uint16_t* terminal_buffer;
void terminal_clear(void);
void terminal_initialize(void);
int terminal_initialize(void);
void terminal_setcolor(uint8_t color);
void terminal_clearline(size_t line);
void terminal_clearlines(size_t from, size_t to);

View file

@ -15,6 +15,7 @@ void* malloc(size_t amount);
int rand(void);
void srand(size_t seed);
char* itoa(int res);
unsigned int atoi(const char *in);
#ifdef __cplusplus
}