Espresso 0.0.2a
This commit is contained in:
@ -13,10 +13,10 @@
|
||||
|
||||
elf_executable_t* load_elf32(void* elf_data)
|
||||
{
|
||||
Elf32_Ehdr* ehdr = (Elf32_Ehdr*)elf_data;
|
||||
/*Elf32_Ehdr* ehdr = (Elf32_Ehdr*)elf_data;*/
|
||||
|
||||
/* Check ELF magic */
|
||||
if (memcmp(ehdr->e_ident, (uint8_t*)("\x7F""ELF"), 4) != 0)
|
||||
/*if (memcmp(ehdr->e_ident, (uint8_t*)("\x7F""ELF"), 4) != 0)
|
||||
{
|
||||
printf("Invalid ELF file\n");
|
||||
return NULL;
|
||||
@ -58,6 +58,8 @@ elf_executable_t* load_elf32(void* elf_data)
|
||||
|
||||
elf_executable_t* result = malloc(sizeof(elf_executable_t));
|
||||
result->entry_point = (void*)(uintptr_t)ehdr->e_entry;
|
||||
return result;
|
||||
return result;*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
117
drivers/fs/ssfs.c
Normal file
117
drivers/fs/ssfs.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include <types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <drivers/ide.h>
|
||||
|
||||
#include <fs/ssfs.h>
|
||||
|
||||
|
||||
|
||||
#define SSFS_START_LBA 16
|
||||
#define SSFS_FILE_HEADER_SIZE_BYTES 32
|
||||
|
||||
|
||||
int ssfs_read_file(const char* name, void* buffer, int size)
|
||||
{
|
||||
if (strlen(name) > 15)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t header_buf[512];
|
||||
int r = read_sector(16, header_buf);
|
||||
|
||||
if (r != 0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
ssfs_file_header_t f;
|
||||
memcpy(&f, header_buf, sizeof(f));
|
||||
|
||||
if (strncmp(f.filename, name, 15) != 0)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Clamp read size to actual file size */
|
||||
if (size > (int)f.num_bytes)
|
||||
size = (int)f.num_bytes;
|
||||
|
||||
int total_read = 0;
|
||||
int sector_count = div_round_up(size, 512);
|
||||
uint8_t sector_data[512];
|
||||
|
||||
for (int k = 0; k < sector_count; k++)
|
||||
{
|
||||
r = read_sector(f.start_sector + k, sector_data);
|
||||
|
||||
if (r != 0)
|
||||
{
|
||||
return -4; /* I/O error */
|
||||
}
|
||||
|
||||
int to_copy = size - total_read;
|
||||
|
||||
if (to_copy > 512)
|
||||
{
|
||||
to_copy = 512;
|
||||
}
|
||||
|
||||
memcpy((uint8_t*)buffer + total_read, sector_data, to_copy);
|
||||
total_read += to_copy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* size is number of bytes */
|
||||
int ssfs_write_file(const char* name, void* data, int size)
|
||||
{
|
||||
ssfs_file_header_t* f = (ssfs_file_header_t*) malloc(sizeof(ssfs_file_header_t));
|
||||
memset(f, 0, sizeof(ssfs_file_header_t));
|
||||
|
||||
if (strlen(name) > 15)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(f->filename, name);
|
||||
f->num_sectors = 0;
|
||||
|
||||
int sector_count = div_round_up(size, 512);
|
||||
|
||||
uint8_t* buffer = (uint8_t*) malloc(sector_count * 512);
|
||||
|
||||
memset(buffer, 0, sector_count * 512);
|
||||
memcpy(buffer, data, (size_t) size);
|
||||
|
||||
int r = 0;
|
||||
|
||||
f->start_sector = 32;
|
||||
|
||||
for (int k = 0; k < sector_count; k++)
|
||||
{
|
||||
r = write_sector(f->start_sector + k, buffer + (k * 512));
|
||||
|
||||
if (r != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f->num_sectors = sector_count;
|
||||
f->num_bytes = (uint32_t) size;
|
||||
|
||||
uint8_t header_buf[512];
|
||||
memset(header_buf, 0, 512);
|
||||
memcpy(header_buf, f, sizeof(*f));
|
||||
write_sector(16, header_buf);
|
||||
|
||||
free(buffer);
|
||||
free(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -63,10 +63,16 @@ int32_t ide_identify(uint8_t drive, uint16_t* buffer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ide_initialize(void) {
|
||||
void ide_initialize(void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
printf("[ IDE ] Initializing IDE system...\n");
|
||||
#endif
|
||||
|
||||
outb(ATA_PRIMARY_CTRL, 0x02); /* Disable IRQs from IDE disk controllers TODO: should probably use IRQs soon */
|
||||
|
||||
uint16_t identify_buf[256];
|
||||
volatile uint16_t identify_buf[256];
|
||||
|
||||
if (ide_identify(0, identify_buf) == 0)
|
||||
{
|
||||
char model[41];
|
||||
@ -78,9 +84,18 @@ void ide_initialize(void) {
|
||||
model[40] = 0;
|
||||
printf("Disk model: %s\n", model);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ide_initialize(): ide_identify(0, identify_buf) did NOT return 0!\n");
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
printf("[ IDE ] IDE initialized\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t ide_read48(uint8_t drive, uint64_t lba, uint8_t sector_count, void* buffer) {
|
||||
int32_t ide_read48(uint8_t drive, uint64_t lba, uint8_t sector_count, void* buffer)
|
||||
{
|
||||
if (sector_count == 0)
|
||||
{
|
||||
return -1;
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
#include <stdio.h>
|
||||
#include <drivers/ps2_keyboard.h>
|
||||
#include <drivers/pit.h>
|
||||
#include <port_io.h>
|
||||
|
||||
#include <drivers/irq.h>
|
||||
|
||||
#define NUM_IRQS 0x90
|
||||
|
||||
irq_func_t func_list[NUM_IRQS];
|
||||
irq_func_t aux_func_list[NUM_IRQS];
|
||||
|
||||
|
||||
|
||||
@ -15,9 +15,10 @@ static volatile uint32_t num_irqs_missed = 0;
|
||||
|
||||
void irq_init(void)
|
||||
{
|
||||
memset(func_list, 0x0, NUM_IRQS);
|
||||
memset(aux_func_list, 0x0, NUM_IRQS);
|
||||
|
||||
for (int i = 0; i < NUM_IRQS; i++)
|
||||
{
|
||||
func_list[i] = 0x0;
|
||||
}
|
||||
set_irq_handler(0, (irq_func_t*)pit_handler);
|
||||
set_irq_handler(1, (irq_func_t*)keyboard_handler);
|
||||
}
|
||||
@ -29,10 +30,7 @@ void irq_handler(uint8_t irq_number)
|
||||
if (func_list[irq_number])
|
||||
{
|
||||
func_list[irq_number]();
|
||||
}
|
||||
else if (aux_func_list[irq_number])
|
||||
{
|
||||
aux_func_list[irq_number]();
|
||||
outb(0x20, 0x20); /* Acknowledge the IRQ to PIC */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -48,21 +46,3 @@ void set_irq_handler(uint32_t num, irq_func_t* handler)
|
||||
func_list[num] = (irq_func_t)handler;
|
||||
}
|
||||
}
|
||||
|
||||
void add_irq_handler(uint32_t num, irq_func_t* handler)
|
||||
{
|
||||
if (num < NUM_IRQS)
|
||||
{
|
||||
if (func_list[num] != 0x0)
|
||||
{
|
||||
if (aux_func_list[num] == 0x0)
|
||||
{
|
||||
aux_func_list[num] = (irq_func_t)handler;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
func_list[num] = (irq_func_t)handler;
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,6 +58,18 @@ void pci_config_read_block(uint8_t bus, uint8_t device, uint8_t function, uint8_
|
||||
}
|
||||
}
|
||||
|
||||
void pci_init(void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
printf("[ PCI ] Initializing PCI...\n");
|
||||
#endif
|
||||
|
||||
pci_enumerate();
|
||||
|
||||
#ifdef _DEBUG
|
||||
printf("[ PCI ] PCI initialized\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void pci_enumerate(void)
|
||||
{
|
||||
@ -77,7 +89,7 @@ void pci_enumerate(void)
|
||||
|
||||
if (pre_header.class_code == 0xB)
|
||||
{
|
||||
printf("Processor found on PCI bus, what?!?!\n");
|
||||
printf("Processor found on PCI bus, what?!?!\n"); /* For some stupid reason, processors can be on the PCI bus? */
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -90,6 +102,9 @@ void pci_enumerate(void)
|
||||
{
|
||||
/*configure_ahci_controller(hdr);*/
|
||||
}
|
||||
|
||||
|
||||
/*printf("PCI device: cc: %x sc: %x pi: %x b: %x d: %x f: %x int: %x\n", hdr.class_code, hdr.subclass, hdr.prog_if, bus, device, function, (uint32_t) hdr.interrupt_line);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,11 @@ volatile uint64_t pit_ticks = 0;
|
||||
bool pit_initialized = false;
|
||||
|
||||
void pit_init(void)
|
||||
{
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
printf("[ PIT ] Initializing the PIT...\n");
|
||||
#endif
|
||||
|
||||
uint16_t divisor = (uint16_t)1193;
|
||||
|
||||
/* Send command byte */
|
||||
@ -25,6 +29,10 @@ void pit_init(void)
|
||||
outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF)); /* High byte */
|
||||
|
||||
pit_initialized = true;
|
||||
|
||||
#ifdef _DEBUG
|
||||
printf("[ PIT ] PIT Initialized\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void pit_handler(void)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include <port_io.h>
|
||||
#include <tty.h>
|
||||
#include <stdlib.h>
|
||||
#include <ksymtab.h>
|
||||
|
||||
|
||||
#include <drivers/ps2_keyboard.h>
|
||||
|
||||
@ -29,6 +29,8 @@
|
||||
|
||||
#define KEYBOARD_IRQ 1
|
||||
|
||||
#define RETURN_STI() do { _sti_asm(); return; } while (0)
|
||||
|
||||
bool ps2keyboard_initialized = false;
|
||||
|
||||
/* State for shift key */
|
||||
@ -41,14 +43,25 @@ static bool capslock_pressed = false;
|
||||
static bool extended = false;
|
||||
|
||||
static bool is_new_char = false;
|
||||
static bool is_new_key = false;
|
||||
static bool is_new_key = false;
|
||||
|
||||
static bool gets_called = false;
|
||||
static volatile bool gets_finished = false;
|
||||
|
||||
volatile unsigned char current_char;
|
||||
volatile char* current_string = NULL;
|
||||
volatile char* current_string = NULL;
|
||||
volatile char* gets_string = NULL;
|
||||
volatile int32_t current_length = 0;
|
||||
volatile int32_t capacity = 0;
|
||||
volatile int32_t gets_length = 0;
|
||||
volatile int32_t capacity = 0;
|
||||
volatile int32_t gets_capacity = 0;
|
||||
volatile uint16_t current_key;
|
||||
|
||||
volatile ps2_hook_t* hooks = NULL;
|
||||
volatile int hook_count = 0;
|
||||
|
||||
extern void _cli_asm(void);
|
||||
extern void _sti_asm(void);
|
||||
|
||||
static const char scancode_map[128] = {
|
||||
0, 27, '1','2','3','4','5','6','7','8','9','0','-','=','\b', /* Backspace */
|
||||
@ -69,15 +82,134 @@ static const char scancode_map[128] = {
|
||||
|
||||
void keyboard_init(void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
printf("[ PS/2 KBD ] Initializing the PS/2 keyboard...\n");
|
||||
#endif
|
||||
|
||||
outb(0x64, 0xAE); /* Enable keyboard interface (often optional, but here for safety) */
|
||||
|
||||
hooks = (ps2_hook_t*) malloc(sizeof(ps2_hook_t) * hook_count);
|
||||
|
||||
ps2keyboard_initialized = true;
|
||||
|
||||
#ifdef _DEBUG
|
||||
printf("[ PS/2 KBD ] PS/2 Keyboard initialized\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool setup_hook(ps2_hook_t func)
|
||||
{
|
||||
_cli_asm();
|
||||
|
||||
ps2_hook_t* copy = malloc(sizeof(ps2_hook_t) * hook_count);
|
||||
|
||||
if (hook_count > 0 && copy == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hook_count > 0)
|
||||
{
|
||||
memcpy(copy, hooks, sizeof(ps2_hook_t) * hook_count);
|
||||
}
|
||||
|
||||
free((void*) hooks);
|
||||
|
||||
hooks = malloc(sizeof(ps2_hook_t) * (hook_count + 1));
|
||||
|
||||
if (hooks == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hook_count > 0)
|
||||
{
|
||||
memcpy((void*) hooks, copy, sizeof(ps2_hook_t) * hook_count);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
|
||||
hooks[hook_count] = func;
|
||||
hook_count++;
|
||||
|
||||
_sti_asm();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool remove_hook(ps2_hook_t func)
|
||||
{
|
||||
_cli_asm();
|
||||
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < hook_count; i++)
|
||||
{
|
||||
if (hooks[i] == func)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = index; i < hook_count - 1; i++)
|
||||
{
|
||||
hooks[i] = hooks[i + 1];
|
||||
}
|
||||
|
||||
hook_count--;
|
||||
|
||||
if (hook_count == 0)
|
||||
{
|
||||
free((void*) hooks);
|
||||
hooks = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
ps2_hook_t* smaller = malloc(sizeof(ps2_hook_t) * hook_count);
|
||||
|
||||
if (smaller == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(smaller, (void*) hooks, sizeof(ps2_hook_t) * hook_count);
|
||||
free((void*) hooks);
|
||||
hooks = smaller;
|
||||
|
||||
_sti_asm();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void call_hooks(char c)
|
||||
{
|
||||
_cli_asm();
|
||||
|
||||
if (hook_count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < hook_count; i++)
|
||||
{
|
||||
hooks[i](c);
|
||||
}
|
||||
|
||||
_sti_asm();
|
||||
}
|
||||
|
||||
char get_char(void)
|
||||
{
|
||||
/*
|
||||
ASCII code 5 (Enquiry) is/was used in legacy systems meant for requesting a response from a remote terminal or device.
|
||||
For example, one system might send ENQ (ASCII 5), and the receiver could reply with ACK (ASCII 6) to indicate it’s ready or still online.
|
||||
For example, one system might send ENQ (ASCII 5), and the receiver could reply with ACK (ASCII 6) to indicate it's ready or still online.
|
||||
|
||||
In modern computing, ENQ is largely obsolete:
|
||||
|
||||
@ -87,16 +219,13 @@ char get_char(void)
|
||||
|
||||
- It may still appear in legacy systems, embedded devices, or proprietary serial protocols, but that's niche.
|
||||
*/
|
||||
char temp = 5;
|
||||
|
||||
if (is_new_char)
|
||||
if (!is_new_char)
|
||||
{
|
||||
temp = current_char;
|
||||
return 5;
|
||||
}
|
||||
|
||||
|
||||
is_new_char = false;
|
||||
|
||||
return temp;
|
||||
return current_char;
|
||||
}
|
||||
|
||||
uint16_t get_key(void)
|
||||
@ -122,39 +251,184 @@ char* get_string(void)
|
||||
return current_string;
|
||||
}
|
||||
|
||||
static void append_char(char c)
|
||||
char* kbd_gets(void)
|
||||
{
|
||||
gets_called = true;
|
||||
gets_finished = false;
|
||||
|
||||
while (gets_finished != true)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
char* result = strdup(gets_string); /* Could be NULL, that is checked below */
|
||||
|
||||
free(gets_string);
|
||||
|
||||
gets_string = NULL;
|
||||
gets_capacity = 0;
|
||||
gets_length = 0;
|
||||
gets_called = false;
|
||||
|
||||
return result == NULL ? "" : result;
|
||||
}
|
||||
|
||||
void gets_append_char(unsigned char c)
|
||||
{
|
||||
_cli_asm();
|
||||
|
||||
if (!gets_string && gets_capacity > 0)
|
||||
{
|
||||
printf("[keyboard] ERROR: gets_string is NULL but capacity > 0!\n");
|
||||
RETURN_STI();
|
||||
}
|
||||
|
||||
|
||||
if (c == KEY_ARROW_UP || c == KEY_ARROW_DOWN || c == KEY_ARROW_RIGHT || c == KEY_ARROW_LEFT)
|
||||
{
|
||||
gets_string[1] = '\0';
|
||||
|
||||
char tc = '\0';
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case KEY_ARROW_UP:
|
||||
tc = KEY_UP;
|
||||
break;
|
||||
case KEY_ARROW_DOWN:
|
||||
tc = KEY_DOWN;
|
||||
break;
|
||||
case KEY_ARROW_RIGHT:
|
||||
tc = KEY_RIGHT;
|
||||
break;
|
||||
case KEY_ARROW_LEFT:
|
||||
tc = KEY_LEFT;
|
||||
break;
|
||||
default:
|
||||
tc = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
gets_string[0] = tc;
|
||||
|
||||
gets_finished = true;
|
||||
|
||||
RETURN_STI();
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
/* The returned string must/will not have newlines in it, so we return here after setting gets_finished to 'true'. */
|
||||
|
||||
gets_finished = true;
|
||||
|
||||
printf("\n");
|
||||
|
||||
RETURN_STI();
|
||||
}
|
||||
else if (c == 27) /* ASCII escape, here it's used to cancel input. */
|
||||
{
|
||||
gets_finished = true;
|
||||
gets_string[0] = '\0';
|
||||
|
||||
RETURN_STI();
|
||||
}
|
||||
else if (c == '\b')
|
||||
{
|
||||
if (gets_length < 1)
|
||||
{
|
||||
RETURN_STI();
|
||||
}
|
||||
|
||||
gets_length--;
|
||||
gets_string[gets_length] = '\0';
|
||||
|
||||
printf("\b \b");
|
||||
|
||||
RETURN_STI();
|
||||
}
|
||||
|
||||
if ((gets_length) >= gets_capacity)
|
||||
{
|
||||
int new_capacity = (gets_capacity == 0) ? 64 : gets_capacity * 2;
|
||||
|
||||
char* new_str = (char*) malloc(new_capacity);
|
||||
|
||||
if (!new_str)
|
||||
{
|
||||
RETURN_STI();
|
||||
}
|
||||
|
||||
if (gets_string)
|
||||
{
|
||||
for (int i = 0; i < gets_length; i++)
|
||||
{
|
||||
new_str[i] = gets_string[i];
|
||||
}
|
||||
|
||||
new_str[gets_length] = '\0';
|
||||
|
||||
free(gets_string);
|
||||
}
|
||||
|
||||
gets_string = new_str;
|
||||
gets_capacity = new_capacity;
|
||||
}
|
||||
|
||||
if (!gets_string)
|
||||
{
|
||||
RETURN_STI();
|
||||
}
|
||||
|
||||
gets_string[gets_length] = (char) c;
|
||||
gets_length++;
|
||||
gets_string[gets_length] = '\0';
|
||||
|
||||
printf("%c", c);
|
||||
|
||||
RETURN_STI();
|
||||
}
|
||||
|
||||
void append_char(char c)
|
||||
{
|
||||
_cli_asm();
|
||||
|
||||
if (current_length + 1 >= capacity)
|
||||
{
|
||||
/* Need more space (+1 for the null zero) */
|
||||
int new_capacity = (capacity == 0) ? 16 : capacity * 2;
|
||||
|
||||
char* new_str = (char*)malloc(new_capacity);
|
||||
if (!new_str) {
|
||||
char* new_str = (char*) malloc(new_capacity);
|
||||
|
||||
if (!new_str)
|
||||
{
|
||||
printf("[keyboard] ERROR: malloc failed for new input buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (current_string)
|
||||
{
|
||||
memcpy(new_str, current_string, current_length);
|
||||
free(current_string);
|
||||
}
|
||||
|
||||
if (!current_string)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
current_string = new_str;
|
||||
capacity = new_capacity;
|
||||
}
|
||||
|
||||
if (!current_string)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
current_string[current_length] = c;
|
||||
current_length++;
|
||||
current_string[current_length] = '\0'; /* Maintain null terminator */
|
||||
current_string[current_length] = '\0';
|
||||
|
||||
_sti_asm();
|
||||
}
|
||||
|
||||
static void free_current_string(void)
|
||||
|
||||
void free_current_string(void)
|
||||
{
|
||||
if (current_string)
|
||||
{
|
||||
@ -198,8 +472,8 @@ void keyboard_handler(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t c = (uint16_t)scancode_map[scancode];
|
||||
if ((shift_pressed ^ capslock_pressed) && ((char)c >= 'a') && ((char)c <= 'z'))
|
||||
uint16_t c = (uint16_t) scancode_map[scancode];
|
||||
if ((shift_pressed ^ capslock_pressed) && ((char) c >= 'a') && ((char) c <= 'z'))
|
||||
{
|
||||
c -= 32; /* Convert to uppercase */
|
||||
}
|
||||
@ -208,11 +482,10 @@ void keyboard_handler(void)
|
||||
c = (uint16_t) terminal_get_shifted((unsigned char) c);
|
||||
}
|
||||
|
||||
/*if (scancode == 0x1C) {
|
||||
printf("\n");
|
||||
return;
|
||||
}*/
|
||||
|
||||
if (hook_count > 0)
|
||||
{
|
||||
call_hooks(c);
|
||||
}
|
||||
|
||||
if (extended)
|
||||
{
|
||||
@ -235,6 +508,13 @@ void keyboard_handler(void)
|
||||
break;
|
||||
}
|
||||
|
||||
if (gets_called)
|
||||
{
|
||||
gets_append_char(c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
current_key = c;
|
||||
|
||||
is_new_key = true;
|
||||
@ -242,20 +522,35 @@ void keyboard_handler(void)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (gets_called)
|
||||
{
|
||||
gets_append_char(c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (c)
|
||||
{
|
||||
if (c != '\n')
|
||||
{
|
||||
append_char(c);
|
||||
}
|
||||
|
||||
current_char = c;
|
||||
|
||||
is_new_char = true;
|
||||
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
/*append_char(c);
|
||||
current_char = c;
|
||||
is_new_char = true;*/
|
||||
|
||||
free_current_string();
|
||||
}
|
||||
|
||||
append_char(c);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
88
drivers/serio.c
Normal file
88
drivers/serio.c
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
/*
|
||||
Driver for serial output.
|
||||
Mostly useful for debug output because QEMU allows the redirection of serial output to either stdio or a file on the host computer.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <port_io.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <drivers/serio.h>
|
||||
|
||||
|
||||
#define COM1_IO_ADDR 0x3F8
|
||||
#define COM2_IO_ADDR 0x2F8
|
||||
|
||||
#define COM1_IRQ 0x4
|
||||
#define COM2_IRQ 0x3
|
||||
|
||||
#define COM1_LCR (COM1_IO_ADDR + 3)
|
||||
#define COM2_LCR (COM2_IO_ADDR + 3)
|
||||
|
||||
#define BAUD 57600
|
||||
#define DIVISOR 2
|
||||
|
||||
|
||||
int serial_init(void)
|
||||
{
|
||||
/* The following is taken from https://wiki.osdev.org/Serial_Ports */
|
||||
|
||||
outb(COM1_IO_ADDR + 1, 0x00); // Disable all interrupts
|
||||
outb(COM1_IO_ADDR + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
outb(COM1_IO_ADDR + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||
outb(COM1_IO_ADDR + 1, 0x00); // (hi byte)
|
||||
outb(COM1_IO_ADDR + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
outb(COM1_IO_ADDR + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||
outb(COM1_IO_ADDR + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
outb(COM1_IO_ADDR + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||
outb(COM1_IO_ADDR + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||
|
||||
// Check if serial is faulty (i.e: not same byte as sent)
|
||||
if(inb(COM1_IO_ADDR + 0) != 0xAE)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If serial is not faulty set it in normal operation mode
|
||||
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||
outb(COM1_IO_ADDR + 4, 0x0F);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_transmit_empty(void)
|
||||
{
|
||||
return inb(COM1_IO_ADDR + 5) & 0x20;
|
||||
}
|
||||
|
||||
static int serial_received(void)
|
||||
{
|
||||
return inb(COM1_IO_ADDR + 5) & 1;
|
||||
}
|
||||
|
||||
void serial_write(char a)
|
||||
{
|
||||
while (is_transmit_empty() == 0);
|
||||
|
||||
outb(COM1_IO_ADDR, a);
|
||||
}
|
||||
|
||||
void serial_puts(const char* s)
|
||||
{
|
||||
for (int i = 0; i < (int) strlen(s); i++)
|
||||
{
|
||||
serial_write(s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
char serial_read(void)
|
||||
{
|
||||
while (serial_received() == 0);
|
||||
|
||||
return inb(COM1_IO_ADDR);
|
||||
}
|
||||
|
||||
bool use_serial(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
109
drivers/tty.c
109
drivers/tty.c
@ -1,16 +1,21 @@
|
||||
#include <string.h>
|
||||
#include <vga/vga.h>
|
||||
#include <stdio.h>
|
||||
#include <port_io.h>
|
||||
|
||||
#include <tty.h>
|
||||
|
||||
static size_t terminal_row;
|
||||
static size_t terminal_column;
|
||||
static uint8_t terminal_color;
|
||||
static uint16_t* terminal_buffer;
|
||||
size_t terminal_row;
|
||||
size_t terminal_column;
|
||||
uint8_t terminal_color;
|
||||
uint16_t* terminal_buffer;
|
||||
|
||||
|
||||
void terminal_initialize(void)
|
||||
{
|
||||
terminal_initializec(0x00);
|
||||
|
||||
terminal_update_cursor();
|
||||
}
|
||||
|
||||
void terminal_initializec(uint8_t color)
|
||||
@ -22,11 +27,13 @@ void terminal_initializec(uint8_t color)
|
||||
{
|
||||
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
terminal_color = color;
|
||||
}
|
||||
|
||||
terminal_buffer = VGA_MEMORY;
|
||||
|
||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||
{
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
@ -55,6 +62,7 @@ void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y)
|
||||
|
||||
void terminal_putchar(const char c)
|
||||
{
|
||||
|
||||
unsigned char uc = c;
|
||||
|
||||
if (uc == '\n')
|
||||
@ -62,9 +70,21 @@ void terminal_putchar(const char c)
|
||||
terminal_column = 0;
|
||||
if (++terminal_row == VGA_HEIGHT)
|
||||
{
|
||||
terminal_scroll();
|
||||
terminal_row = VGA_HEIGHT - 1;
|
||||
if (1)
|
||||
{
|
||||
terminal_scroll();
|
||||
terminal_row = VGA_HEIGHT - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
terminal_clear();
|
||||
terminal_row = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
terminal_update_cursor();
|
||||
|
||||
return;
|
||||
}
|
||||
else if (uc == '\t')
|
||||
@ -76,28 +96,35 @@ void terminal_putchar(const char c)
|
||||
terminal_putchar('\n');
|
||||
}
|
||||
|
||||
terminal_update_cursor();
|
||||
|
||||
return;
|
||||
}
|
||||
else if (uc == '\b')
|
||||
{
|
||||
if (terminal_column == 0)
|
||||
{
|
||||
terminal_row -= 1;
|
||||
|
||||
if (terminal_row == (size_t)-1)
|
||||
if (terminal_row > 0)
|
||||
{
|
||||
terminal_row = 0;
|
||||
terminal_row--;
|
||||
terminal_column = VGA_WIDTH - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
terminal_update_cursor(); /* For good measure */
|
||||
|
||||
terminal_column = VGA_WIDTH;
|
||||
|
||||
terminal_putentryat(' ', terminal_getcolor(), (size_t)terminal_column, (size_t)terminal_row);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
terminal_putentryat(' ', terminal_getcolor(), (size_t)--terminal_column, (size_t)terminal_row);
|
||||
terminal_column--;
|
||||
}
|
||||
|
||||
terminal_putentryat(' ', terminal_color, terminal_column, terminal_row);
|
||||
|
||||
terminal_update_cursor();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -110,9 +137,10 @@ void terminal_putchar(const char c)
|
||||
if (++terminal_row == VGA_HEIGHT)
|
||||
{
|
||||
terminal_scroll();
|
||||
terminal_row = VGA_HEIGHT - 1;
|
||||
}
|
||||
}
|
||||
|
||||
terminal_update_cursor();
|
||||
}
|
||||
|
||||
void terminal_write(const char* data, size_t size)
|
||||
@ -157,7 +185,7 @@ void terminal_clear(void)
|
||||
|
||||
void terminal_clearl(size_t num_lines)
|
||||
{
|
||||
if (num_lines == (size_t)-1)
|
||||
if (num_lines == (size_t) -1)
|
||||
{
|
||||
terminal_initializec(terminal_getcolor());
|
||||
}
|
||||
@ -182,20 +210,18 @@ void terminal_clearl(size_t num_lines)
|
||||
|
||||
void terminal_scroll(void)
|
||||
{
|
||||
for (size_t y = 1; y < VGA_HEIGHT; y++)
|
||||
|
||||
memmove(
|
||||
terminal_buffer,
|
||||
terminal_buffer + VGA_WIDTH,
|
||||
sizeof(uint16_t) * VGA_WIDTH * (VGA_HEIGHT/* + 1*/)
|
||||
);
|
||||
|
||||
terminal_row = VGA_HEIGHT - 1;
|
||||
|
||||
for (int32_t k = 0; k < (int32_t)VGA_WIDTH; k++)
|
||||
{
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
{
|
||||
const size_t src_index = y * VGA_WIDTH + x;
|
||||
const size_t dst_index = (y - 1) * VGA_WIDTH + x;
|
||||
terminal_buffer[dst_index] = terminal_buffer[src_index];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
{
|
||||
const size_t index = (VGA_HEIGHT - 1) * VGA_WIDTH + x;
|
||||
terminal_buffer[index] = (terminal_color << 8) | ' ';
|
||||
terminal_putentryat((unsigned char)' ', terminal_getcolor(), (size_t)terminal_row, (size_t)k);
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +234,7 @@ unsigned char terminal_get_shifted(unsigned char uc)
|
||||
unsigned char syms1[] = { ',', '.', '/', ';', '\'', '[', ']', '`', '-', '=', '\\', '\0' };
|
||||
unsigned char syms2[] = { '<', '>', '?', ':', '\"', '{', '}', '~', '_', '+', '|', '\0' };
|
||||
|
||||
for (int32_t i = 0; i < (int32_t)(strlen((char*)lowerc)); ++i)
|
||||
for (int32_t i = 0; i < (int32_t) (strlen((char*)lowerc)); ++i)
|
||||
{
|
||||
if (uc == lowerc[i])
|
||||
{
|
||||
@ -220,7 +246,7 @@ unsigned char terminal_get_shifted(unsigned char uc)
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < (int32_t)(strlen((char*)nums)); ++i)
|
||||
for (int32_t i = 0; i < (int32_t) (strlen((char*)nums)); ++i)
|
||||
{
|
||||
if (uc == nums[i])
|
||||
{
|
||||
@ -232,7 +258,7 @@ unsigned char terminal_get_shifted(unsigned char uc)
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < (int32_t)(strlen((char*)syms1)); ++i)
|
||||
for (int32_t i = 0; i < (int32_t) (strlen((char*) syms1)); ++i)
|
||||
{
|
||||
if (uc == syms1[i])
|
||||
{
|
||||
@ -251,7 +277,20 @@ void terminal_set_cursor(uint16_t row, uint16_t column)
|
||||
{
|
||||
if (row < VGA_HEIGHT && column < VGA_WIDTH)
|
||||
{
|
||||
terminal_row = (size_t)row;
|
||||
terminal_column = (size_t)column;
|
||||
terminal_row = (size_t) row;
|
||||
terminal_column = (size_t) column;
|
||||
}
|
||||
|
||||
terminal_update_cursor();
|
||||
}
|
||||
|
||||
void terminal_update_cursor(void)
|
||||
{
|
||||
uint16_t pos = terminal_row * VGA_WIDTH + terminal_column;
|
||||
|
||||
outb(0x3D4, 0x0F);
|
||||
outb(0x3D5, (uint8_t) (pos & 0xFF));
|
||||
outb(0x3D4, 0x0E);
|
||||
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user