Espresso 0.0.2a
This commit is contained in:
5
Makefile
5
Makefile
@ -6,10 +6,10 @@ AS := i686-elf-as
|
|||||||
NASM := nasm
|
NASM := nasm
|
||||||
QEMU_MKE_IMG := qemu-img create -f raw espresso.img 64M
|
QEMU_MKE_IMG := qemu-img create -f raw espresso.img 64M
|
||||||
MKFS_VFAT := sudo mkfs.vfat
|
MKFS_VFAT := sudo mkfs.vfat
|
||||||
MKFS_FLAGS := -F 32 -S 512
|
MKFS_FLAGS := -F 16 -S 512
|
||||||
NASMFLAGS := -f elf32
|
NASMFLAGS := -f elf32
|
||||||
WNOFLAGS := -Wno-discarded-qualifiers
|
WNOFLAGS := -Wno-discarded-qualifiers
|
||||||
CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse $(WNOFLAGS) -nostdlib -nostartfiles -include kincl.h
|
CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse $(WNOFLAGS) -nostdlib -nostartfiles -include include/kincl.h
|
||||||
LDFLAGS := -T linker.ld -ffreestanding -O2 -nostdlib -nostartfiles
|
LDFLAGS := -T linker.ld -ffreestanding -O2 -nostdlib -nostartfiles
|
||||||
QEMUFLAGS := -boot d -cdrom $(ISO) -drive file=espresso.img,format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse4.1
|
QEMUFLAGS := -boot d -cdrom $(ISO) -drive file=espresso.img,format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse4.1
|
||||||
QEMUFLGS_EXT := -vga std -d int,cpu_reset -D qemu.log -no-reboot #-singlestep
|
QEMUFLGS_EXT := -vga std -d int,cpu_reset -D qemu.log -no-reboot #-singlestep
|
||||||
@ -81,6 +81,7 @@ run: iso
|
|||||||
@if [ ! -f espresso.img ]; then \
|
@if [ ! -f espresso.img ]; then \
|
||||||
$(QEMU_MKE_IMG); \
|
$(QEMU_MKE_IMG); \
|
||||||
fi
|
fi
|
||||||
|
sudo mkfs.fat $(MKFS_FLAGS) espresso.img
|
||||||
@echo
|
@echo
|
||||||
qemu-system-i386 $(QEMUFLAGS) $(QEMUFLGS_EXT) $(MOR_QEMUFLGS)
|
qemu-system-i386 $(QEMUFLAGS) $(QEMUFLGS_EXT) $(MOR_QEMUFLGS)
|
||||||
|
|
||||||
|
|||||||
@ -1,44 +1,51 @@
|
|||||||
.global get_cpu_brand_string
|
global get_cpu_brand_string
|
||||||
|
|
||||||
.type get_cpu_brand_string, @function
|
section .text
|
||||||
|
|
||||||
|
; void get_cpu_brand_string(char* buffer)
|
||||||
|
|
||||||
get_cpu_brand_string:
|
get_cpu_brand_string:
|
||||||
pushad # Save all general-purpose registers
|
pushad ; Save registers
|
||||||
|
|
||||||
mov ebx, eax # Save buffer pointer to ebx
|
mov edi, eax ; EAX = pointer to output buffer
|
||||||
|
|
||||||
mov eax, 0x80000000
|
mov eax, 0x80000000
|
||||||
cpuid
|
cpuid
|
||||||
cmp eax, 0x80000004 # Check if brand string is supported
|
cmp eax, 0x80000004
|
||||||
jb .not_supported
|
jb .not_supported
|
||||||
|
|
||||||
mov esi, ebx # Copy address to ESI
|
mov esi, edi ; Buffer pointer → ESI
|
||||||
|
|
||||||
|
; ---- CPUID leaf 0x80000002 ----
|
||||||
mov eax, 0x80000002
|
mov eax, 0x80000002
|
||||||
cpuid
|
cpuid
|
||||||
mov [esi], eax
|
mov [esi], eax
|
||||||
mov [esi + 4], ebx
|
mov [esi+4], ebx
|
||||||
mov [esi + 8], ecx
|
mov [esi+8], ecx
|
||||||
mov [esi + 12], edx
|
mov [esi+12], edx
|
||||||
|
|
||||||
|
; ---- CPUID leaf 0x80000003 ----
|
||||||
mov eax, 0x80000003
|
mov eax, 0x80000003
|
||||||
cpuid
|
cpuid
|
||||||
mov [esi + 16], eax
|
mov [esi+16], eax
|
||||||
mov [esi + 20], ebx
|
mov [esi+20], ebx
|
||||||
mov [esi + 24], ecx
|
mov [esi+24], ecx
|
||||||
mov [esi + 28], edx
|
mov [esi+28], edx
|
||||||
|
|
||||||
|
; ---- CPUID leaf 0x80000004 ----
|
||||||
mov eax, 0x80000004
|
mov eax, 0x80000004
|
||||||
cpuid
|
cpuid
|
||||||
mov [esi + 32], eax
|
mov [esi+32], eax
|
||||||
mov [esi + 36], ebx
|
mov [esi+36], ebx
|
||||||
mov [esi + 40], ecx
|
mov [esi+40], ecx
|
||||||
mov [esi + 44], edx
|
mov [esi+44], edx
|
||||||
|
|
||||||
|
mov byte [esi+48], 0 ; Null terminator
|
||||||
|
|
||||||
jmp .done
|
jmp .done
|
||||||
|
|
||||||
.not_supported:
|
.not_supported:
|
||||||
mov byte [ebx], 0 # Null-terminate if not supported
|
mov byte [edi], 0
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
popad
|
popad
|
||||||
|
|||||||
@ -19,8 +19,8 @@ void irq_init(void)
|
|||||||
{
|
{
|
||||||
func_list[i] = 0x0;
|
func_list[i] = 0x0;
|
||||||
}
|
}
|
||||||
set_irq_handler(0, (irq_func_t*)pit_handler);
|
set_irq_handler(0, (irq_func_t*) pit_handler);
|
||||||
set_irq_handler(1, (irq_func_t*)keyboard_handler);
|
set_irq_handler(1, (irq_func_t*) keyboard_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_handler(uint8_t irq_number)
|
void irq_handler(uint8_t irq_number)
|
||||||
|
|||||||
@ -48,4 +48,3 @@ void pit_sleep(uint64_t ms)
|
|||||||
asm volatile ("hlt");
|
asm volatile ("hlt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,14 @@
|
|||||||
|
|
||||||
#define RETURN_STI() do { _sti_asm(); return; } while (0)
|
#define RETURN_STI() do { _sti_asm(); return; } while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#define GETS_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
static char gets_buffer[GETS_BUFFER_SIZE];
|
||||||
|
volatile char* gets_string = gets_buffer;
|
||||||
|
volatile int32_t gets_capacity = GETS_BUFFER_SIZE;
|
||||||
|
volatile int32_t gets_length = 0;
|
||||||
|
|
||||||
bool ps2keyboard_initialized = false;
|
bool ps2keyboard_initialized = false;
|
||||||
|
|
||||||
/* State for shift key */
|
/* State for shift key */
|
||||||
@ -50,11 +58,8 @@ static volatile bool gets_finished = false;
|
|||||||
|
|
||||||
volatile unsigned char current_char;
|
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 current_length = 0;
|
||||||
volatile int32_t gets_length = 0;
|
|
||||||
volatile int32_t capacity = 0;
|
volatile int32_t capacity = 0;
|
||||||
volatile int32_t gets_capacity = 0;
|
|
||||||
volatile uint16_t current_key;
|
volatile uint16_t current_key;
|
||||||
|
|
||||||
volatile ps2_hook_t* hooks = NULL;
|
volatile ps2_hook_t* hooks = NULL;
|
||||||
@ -88,7 +93,7 @@ void keyboard_init(void)
|
|||||||
|
|
||||||
outb(0x64, 0xAE); /* Enable keyboard interface (often optional, but here for safety) */
|
outb(0x64, 0xAE); /* Enable keyboard interface (often optional, but here for safety) */
|
||||||
|
|
||||||
hooks = (ps2_hook_t*) malloc(sizeof(ps2_hook_t) * hook_count);
|
hooks = NULL;
|
||||||
|
|
||||||
ps2keyboard_initialized = true;
|
ps2keyboard_initialized = true;
|
||||||
|
|
||||||
@ -251,143 +256,95 @@ char* get_string(void)
|
|||||||
return current_string;
|
return current_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void print_(void)
|
||||||
|
{
|
||||||
|
static char ch = 'a';
|
||||||
|
|
||||||
|
int r = 0, c = 0;
|
||||||
|
|
||||||
|
terminal_get_cursor(&r, &c);
|
||||||
|
terminal_set_cursor((uint16_t) 30, (uint16_t) 0);
|
||||||
|
printf("%c", ch);
|
||||||
|
terminal_set_cursor((uint16_t) r, (uint16_t) c);
|
||||||
|
|
||||||
|
ch++;
|
||||||
|
}
|
||||||
|
|
||||||
char* kbd_gets(void)
|
char* kbd_gets(void)
|
||||||
{
|
{
|
||||||
gets_called = true;
|
gets_called = true;
|
||||||
gets_finished = false;
|
gets_finished = false;
|
||||||
|
gets_length = 0;
|
||||||
while (gets_finished != true)
|
gets_string[0] = '\0';
|
||||||
|
|
||||||
|
while (!gets_finished)
|
||||||
{
|
{
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* result = strdup(gets_string); /* Could be NULL, that is checked below */
|
_cli_asm();
|
||||||
|
|
||||||
free(gets_string);
|
char* result = strdup((char*) gets_string);
|
||||||
|
|
||||||
gets_string = NULL;
|
|
||||||
gets_capacity = 0;
|
|
||||||
gets_length = 0;
|
gets_length = 0;
|
||||||
|
gets_string[0] = '\0';
|
||||||
gets_called = false;
|
gets_called = false;
|
||||||
|
|
||||||
return result == NULL ? "" : result;
|
_sti_asm();
|
||||||
|
|
||||||
|
return result ? result : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void gets_append_char(unsigned char c)
|
void gets_append_char(unsigned char c)
|
||||||
{
|
{
|
||||||
_cli_asm();
|
if (!gets_called)
|
||||||
|
|
||||||
if (!gets_string && gets_capacity > 0)
|
|
||||||
{
|
{
|
||||||
printf("[keyboard] ERROR: gets_string is NULL but capacity > 0!\n");
|
return;
|
||||||
RETURN_STI();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (c == KEY_ARROW_UP || c == KEY_ARROW_DOWN || c == KEY_ARROW_RIGHT || c == KEY_ARROW_LEFT)
|
if (c == KEY_ARROW_UP || c == KEY_ARROW_DOWN || c == KEY_ARROW_RIGHT || c == KEY_ARROW_LEFT)
|
||||||
{
|
{
|
||||||
gets_string[1] = '\0';
|
if (GETS_BUFFER_SIZE >= 2)
|
||||||
|
|
||||||
char tc = '\0';
|
|
||||||
|
|
||||||
switch (c)
|
|
||||||
{
|
{
|
||||||
case KEY_ARROW_UP:
|
gets_string[0] = (char)c;
|
||||||
tc = KEY_UP;
|
gets_string[1] = '\0';
|
||||||
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;
|
gets_finished = true;
|
||||||
|
return;
|
||||||
RETURN_STI();
|
|
||||||
}
|
}
|
||||||
else if (c == '\n')
|
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;
|
gets_finished = true;
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
return;
|
||||||
RETURN_STI();
|
|
||||||
}
|
}
|
||||||
else if (c == 27) /* ASCII escape, here it's used to cancel input. */
|
else if (c == 27)
|
||||||
{
|
{
|
||||||
gets_finished = true;
|
|
||||||
gets_string[0] = '\0';
|
gets_string[0] = '\0';
|
||||||
|
gets_finished = true;
|
||||||
RETURN_STI();
|
return;
|
||||||
}
|
}
|
||||||
else if (c == '\b')
|
else if (c == '\b')
|
||||||
{
|
{
|
||||||
if (gets_length < 1)
|
if (gets_length > 0)
|
||||||
{
|
{
|
||||||
RETURN_STI();
|
gets_length--;
|
||||||
|
gets_string[gets_length] = '\0';
|
||||||
|
printf("\b \b");
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gets_length--;
|
if (gets_length < GETS_BUFFER_SIZE - 1)
|
||||||
|
{
|
||||||
|
gets_string[gets_length++] = (char)c;
|
||||||
gets_string[gets_length] = '\0';
|
gets_string[gets_length] = '\0';
|
||||||
|
printf("%c", c);
|
||||||
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)
|
void append_char(char c)
|
||||||
{
|
{
|
||||||
_cli_asm();
|
_cli_asm();
|
||||||
|
|||||||
@ -18,6 +18,12 @@ void terminal_initialize(void)
|
|||||||
terminal_update_cursor();
|
terminal_update_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void terminal_get_cursor(int* row, int* column)
|
||||||
|
{
|
||||||
|
*row = (int) terminal_row;
|
||||||
|
*column = (int) terminal_column;
|
||||||
|
}
|
||||||
|
|
||||||
void terminal_initializec(uint8_t color)
|
void terminal_initializec(uint8_t color)
|
||||||
{
|
{
|
||||||
terminal_row = 0;
|
terminal_row = 0;
|
||||||
@ -170,12 +176,15 @@ void terminal_writeline(const char* data)
|
|||||||
|
|
||||||
void terminal_writechar_r(const char ch)
|
void terminal_writechar_r(const char ch)
|
||||||
{
|
{
|
||||||
unsigned char uch = ch;
|
size_t saved_row = terminal_row;
|
||||||
|
size_t saved_col = terminal_column;
|
||||||
|
|
||||||
for (size_t i = 0; i < VGA_WIDTH; i++)
|
for (size_t i = 0; i < VGA_WIDTH; i++)
|
||||||
{
|
{
|
||||||
terminal_putchar(uch);
|
terminal_putentryat(ch, terminal_color, i, saved_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminal_set_cursor(saved_row, saved_col);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_clear(void)
|
void terminal_clear(void)
|
||||||
@ -185,46 +194,49 @@ void terminal_clear(void)
|
|||||||
|
|
||||||
void terminal_clearl(size_t num_lines)
|
void terminal_clearl(size_t num_lines)
|
||||||
{
|
{
|
||||||
if (num_lines == (size_t) -1)
|
if (num_lines == (size_t)-1)
|
||||||
{
|
{
|
||||||
terminal_initializec(terminal_getcolor());
|
terminal_initializec(terminal_getcolor());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* XXX note to self: VGA_HEIGHT is 25, and VGA_WIDTH is 80 XXX */
|
if (num_lines > VGA_HEIGHT)
|
||||||
/* static size_t terminal_row; static size_t terminal_column; */
|
|
||||||
|
|
||||||
terminal_row = VGA_HEIGHT;
|
|
||||||
terminal_column = 0;
|
|
||||||
|
|
||||||
while (terminal_row < num_lines)
|
|
||||||
{
|
{
|
||||||
for (int32_t k = 0; k < (int32_t)VGA_WIDTH; k++)
|
num_lines = VGA_HEIGHT;
|
||||||
{
|
|
||||||
terminal_putentryat((unsigned char)' ', terminal_getcolor(), (size_t)terminal_row, (size_t)k);
|
|
||||||
}
|
|
||||||
terminal_row -= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t start = VGA_HEIGHT - num_lines;
|
||||||
|
for (size_t y = start; y < VGA_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||||
|
{
|
||||||
|
terminal_putentryat(' ', terminal_getcolor(), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal_set_cursor(start, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_scroll(void)
|
void terminal_scroll(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
memmove(
|
memmove(
|
||||||
terminal_buffer,
|
terminal_buffer,
|
||||||
terminal_buffer + VGA_WIDTH,
|
terminal_buffer + VGA_WIDTH,
|
||||||
sizeof(uint16_t) * VGA_WIDTH * (VGA_HEIGHT/* + 1*/)
|
sizeof(uint16_t) * VGA_WIDTH * (VGA_HEIGHT - 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
terminal_row = VGA_HEIGHT - 1;
|
terminal_row = VGA_HEIGHT - 1;
|
||||||
|
for (int32_t x = 0; x < (int32_t)VGA_WIDTH; x++)
|
||||||
for (int32_t k = 0; k < (int32_t)VGA_WIDTH; k++)
|
|
||||||
{
|
{
|
||||||
terminal_putentryat((unsigned char)' ', terminal_getcolor(), (size_t)terminal_row, (size_t)k);
|
terminal_putentryat(' ', terminal_getcolor(), (size_t)x, (size_t)terminal_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminal_column = 0;
|
||||||
|
terminal_update_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned char terminal_get_shifted(unsigned char uc)
|
unsigned char terminal_get_shifted(unsigned char uc)
|
||||||
{
|
{
|
||||||
unsigned char lowerc[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\0' };
|
unsigned char lowerc[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\0' };
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <vga/vga.h>
|
#include <vga/vga.h>
|
||||||
|
|
||||||
uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
|
uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg)
|
||||||
return fg | bg << 4;
|
{
|
||||||
|
return fg | bg << 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t vga_entry(unsigned char uc, uint8_t color) {
|
uint16_t vga_entry(unsigned char uc, uint8_t color)
|
||||||
return (uint16_t) uc | (uint16_t) color << 8;
|
{
|
||||||
|
return (uint16_t) uc | (uint16_t) color << 8;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,9 @@
|
|||||||
#define ATA_SR_DRQ 0x08
|
#define ATA_SR_DRQ 0x08
|
||||||
#define ATA_SR_ERR 0x01
|
#define ATA_SR_ERR 0x01
|
||||||
|
|
||||||
|
|
||||||
|
#define SECTOR_SIZE 512
|
||||||
|
|
||||||
void ide_initialize(void);
|
void ide_initialize(void);
|
||||||
|
|
||||||
int32_t ide_identify(uint8_t drive, uint16_t* buffer);
|
int32_t ide_identify(uint8_t drive, uint16_t* buffer);
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
#define _KERNEL_VARIABLES_H
|
#define _KERNEL_VARIABLES_H
|
||||||
|
|
||||||
|
|
||||||
|
#define KERNEL_VARIABLES_SIZE 4096 /* in bytes (note: it take up a whole page, yes.) */
|
||||||
|
|
||||||
void init_vars(void);
|
void init_vars(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,6 +1,21 @@
|
|||||||
#ifndef _KERNEL_INCLUDES_H
|
#ifndef _KERNEL_INCLUDES_H
|
||||||
#define _KERNEL_INCLUDES_H
|
#define _KERNEL_INCLUDES_H
|
||||||
|
|
||||||
#define KERNEL_VERSION "0.0.1e"
|
#define ESPRESSO_KERNEL_
|
||||||
|
|
||||||
|
#define KERNEL_VERSION "0.0.2a"
|
||||||
|
|
||||||
|
#define _STATE_NORMAL 0
|
||||||
|
#define _STATE_HANDLED 1
|
||||||
|
#define _STATE_INTERRUPT -1
|
||||||
|
#define _STATE_EXCEPTION -2
|
||||||
|
#define _STATE_CRASH -555
|
||||||
|
|
||||||
|
|
||||||
|
#define __always_inline inline __attribute__((always_inline))
|
||||||
|
#define __hot __attribute__((hot))
|
||||||
|
#define __cold __attribute__((cold))
|
||||||
|
#define __noreturn __attribute__((noreturn))
|
||||||
|
#define __section(x) __attribute__((section(x)))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -10,12 +10,12 @@ static inline uint32_t inl(uint16_t port)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void outl(uint16_t port, uint32_t data)
|
static inline __attribute__((always_inline)) void outl(uint16_t port, uint32_t data)
|
||||||
{
|
{
|
||||||
asm volatile ("outl %%eax, %%dx" : : "dN" (port), "a" (data));
|
asm volatile ("outl %%eax, %%dx" : : "dN" (port), "a" (data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void outb(uint16_t port, uint8_t val)
|
static inline __attribute__((always_inline)) void outb(uint16_t port, uint8_t val)
|
||||||
{
|
{
|
||||||
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) : "memory");
|
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) : "memory");
|
||||||
}
|
}
|
||||||
@ -30,17 +30,19 @@ static inline uint8_t inb(uint16_t port)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void io_wait()
|
static inline __attribute__((always_inline)) void io_wait()
|
||||||
{
|
{
|
||||||
outb(0x80, 0);
|
outb(0x80, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void insw(uint16_t port, void* addr, uint32_t count) {
|
static inline __attribute__((always_inline)) void insw(uint16_t port, void* addr, uint32_t count)
|
||||||
__asm__ volatile ("rep insw" : "+D"(addr), "+c"(count) : "d"(port) : "memory");
|
{
|
||||||
|
asm volatile ("rep insw" : "+D"(addr), "+c"(count) : "d"(port) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void outsw(uint16_t port, const void* addr, uint32_t count) {
|
static inline __attribute__((always_inline)) void outsw(uint16_t port, const void* addr, uint32_t count)
|
||||||
__asm__ volatile ("rep outsw" : "+S"(addr), "+c"(count) : "d"(port));
|
{
|
||||||
|
asm volatile ("rep outsw" : "+S"(addr), "+c"(count) : "d"(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -17,6 +17,9 @@ char* strdup(const char* s);
|
|||||||
char* strtok(char* str, const char* delim);
|
char* strtok(char* str, const char* delim);
|
||||||
char* strchr(const char* s, int c);
|
char* strchr(const char* s, int c);
|
||||||
|
|
||||||
|
/* this function is NOT in the standard C library */
|
||||||
|
int num_strchr(const char* s, int c);
|
||||||
|
|
||||||
void lowers(char* str);
|
void lowers(char* str);
|
||||||
void uppers(char* str);
|
void uppers(char* str);
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,9 @@ void terminal_write(const char* data, size_t size);
|
|||||||
void terminal_writestring(const char* data);
|
void terminal_writestring(const char* data);
|
||||||
void terminal_debug_writestring(const char* data);
|
void terminal_debug_writestring(const char* data);
|
||||||
|
|
||||||
|
void terminal_writeline(const char* data);
|
||||||
|
void terminal_writechar_r(const char ch);
|
||||||
|
|
||||||
void terminal_setcolor(uint8_t color);
|
void terminal_setcolor(uint8_t color);
|
||||||
uint8_t terminal_getcolor(void);
|
uint8_t terminal_getcolor(void);
|
||||||
|
|
||||||
@ -26,6 +29,7 @@ void terminal_scroll(void);
|
|||||||
unsigned char terminal_get_shifted(unsigned char uc);
|
unsigned char terminal_get_shifted(unsigned char uc);
|
||||||
|
|
||||||
void terminal_set_cursor(uint16_t row, uint16_t column);
|
void terminal_set_cursor(uint16_t row, uint16_t column);
|
||||||
|
void terminal_get_cursor(int* row, int* column);
|
||||||
void terminal_update_cursor(void);
|
void terminal_update_cursor(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -21,7 +21,7 @@ void *sse2_memcpy(void *dst, const void *src, uint32_t n);
|
|||||||
void double_vector_to_int_vector(const double *src, int32_t *dst);
|
void double_vector_to_int_vector(const double *src, int32_t *dst);
|
||||||
void int_vector_to_double_vector(const int32_t *src, double *dst);
|
void int_vector_to_double_vector(const int32_t *src, double *dst);
|
||||||
|
|
||||||
void *memclr_sse2(const void *const m_start, const size_t m_count);
|
void* memclr_sse2(void *m_start, size_t m_count);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
/* Hardware text mode color constants. */
|
/* Hardware text mode color constants. */
|
||||||
enum vga_color {
|
enum vga_color {
|
||||||
VGA_COLOR_BLACK = 0,
|
VGA_COLOR_BLACK = 0,
|
||||||
VGA_COLOR_BLUE = 1,
|
VGA_COLOR_BLUE = 1,
|
||||||
VGA_COLOR_GREEN = 2,
|
VGA_COLOR_GREEN = 2,
|
||||||
VGA_COLOR_CYAN = 3,
|
VGA_COLOR_CYAN = 3,
|
||||||
VGA_COLOR_RED = 4,
|
VGA_COLOR_RED = 4,
|
||||||
VGA_COLOR_MAGENTA = 5,
|
VGA_COLOR_MAGENTA = 5,
|
||||||
VGA_COLOR_BROWN = 6,
|
VGA_COLOR_BROWN = 6,
|
||||||
VGA_COLOR_LIGHT_GREY = 7,
|
VGA_COLOR_LIGHT_GREY = 7,
|
||||||
VGA_COLOR_DARK_GREY = 8,
|
VGA_COLOR_DARK_GREY = 8,
|
||||||
VGA_COLOR_LIGHT_BLUE = 9,
|
VGA_COLOR_LIGHT_BLUE = 9,
|
||||||
VGA_COLOR_LIGHT_GREEN = 10,
|
VGA_COLOR_LIGHT_GREEN = 10,
|
||||||
VGA_COLOR_LIGHT_CYAN = 11,
|
VGA_COLOR_LIGHT_CYAN = 11,
|
||||||
VGA_COLOR_LIGHT_RED = 12,
|
VGA_COLOR_LIGHT_RED = 12,
|
||||||
VGA_COLOR_LIGHT_MAGENTA = 13,
|
VGA_COLOR_LIGHT_MAGENTA = 13,
|
||||||
VGA_COLOR_LIGHT_BROWN = 14,
|
VGA_COLOR_LIGHT_BROWN = 14,
|
||||||
VGA_COLOR_WHITE = 15,
|
VGA_COLOR_WHITE = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg);
|
uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg);
|
||||||
|
|||||||
@ -38,7 +38,7 @@ char* get_cpu_vendor_string(void)
|
|||||||
return strdup(vendor);
|
return strdup(vendor);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* get_cpu_brand_string(void)
|
/*char* get_cpu_brand_string(void)
|
||||||
{
|
{
|
||||||
unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
|
unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||||
|
|
||||||
@ -63,4 +63,4 @@ char* get_cpu_brand_string(void)
|
|||||||
|
|
||||||
brand[48] = '\0';
|
brand[48] = '\0';
|
||||||
return strdup(brand);
|
return strdup(brand);
|
||||||
}
|
}*/
|
||||||
|
|||||||
@ -136,10 +136,6 @@ void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
|||||||
|
|
||||||
terminal_setcolor(VGA_COLOR_LIGHT_GREEN);
|
terminal_setcolor(VGA_COLOR_LIGHT_GREEN);
|
||||||
|
|
||||||
|
|
||||||
/*pit_sleep(4000);
|
|
||||||
begin_anim(kernel_version);*/
|
|
||||||
|
|
||||||
printf("Guten tag and welcome to Espresso %s\n", kernel_version);
|
printf("Guten tag and welcome to Espresso %s\n", kernel_version);
|
||||||
|
|
||||||
sleep(1000);
|
sleep(1000);
|
||||||
|
|||||||
285
kernel/kshell.c
285
kernel/kshell.c
@ -4,6 +4,9 @@
|
|||||||
#include <drivers/ps2_keyboard.h>
|
#include <drivers/ps2_keyboard.h>
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
#include <kernel/ksh_debug.h>
|
#include <kernel/ksh_debug.h>
|
||||||
|
#include <arch/x86/intrin.h>
|
||||||
|
|
||||||
|
#include <fs/fat16.h>
|
||||||
|
|
||||||
#include <kernel/kshell.h>
|
#include <kernel/kshell.h>
|
||||||
|
|
||||||
@ -27,29 +30,20 @@ static void print_intro(void)
|
|||||||
|
|
||||||
printf("\nSSE level: ");
|
printf("\nSSE level: ");
|
||||||
|
|
||||||
command = 0;
|
command = 1;
|
||||||
|
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
extern char* get_cpu_vendor_string(void);
|
extern char* get_cpu_vendor_string(void);
|
||||||
extern char* get_cpu_brand_string(void);
|
extern char* get_cpu_brand_string(void);
|
||||||
|
|
||||||
|
/* XXX: NOTE: these do not need freeing. */
|
||||||
char* temp_ = get_cpu_vendor_string();
|
char* temp_ = get_cpu_vendor_string();
|
||||||
char* _temp = get_cpu_brand_string();
|
char* _temp = get_cpu_brand_string();
|
||||||
|
|
||||||
printf("CPU: %s\n", _temp == NULL ? "No info" : _temp);
|
printf("CPU: %s\n", _temp == NULL ? "No info" : _temp);
|
||||||
printf("CPU vendor: %s\n", temp_ == NULL ? "No info" : temp_);
|
printf("CPU vendor: %s\n", temp_ == NULL ? "No info" : temp_);
|
||||||
|
|
||||||
if (temp_)
|
|
||||||
{
|
|
||||||
free(temp_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_temp)
|
|
||||||
{
|
|
||||||
free(_temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nCopyright 2025 David J Goeke\n");
|
printf("\nCopyright 2025 David J Goeke\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +58,33 @@ static void parse_opts(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char* commands[] = {
|
||||||
|
"kinfo",
|
||||||
|
"sseinfo",
|
||||||
|
"kernelmem",
|
||||||
|
"sectionmem",
|
||||||
|
|
||||||
|
"enable_debug",
|
||||||
|
"disable_debug",
|
||||||
|
"toggle_debug",
|
||||||
|
"get_debug",
|
||||||
|
|
||||||
|
"dumpregs",
|
||||||
|
"dumpgprs",
|
||||||
|
|
||||||
|
"testascii",
|
||||||
|
|
||||||
|
"printrandom",
|
||||||
|
|
||||||
|
"acm", /* ACcess Memory */
|
||||||
|
|
||||||
|
"testfat16",
|
||||||
|
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_COMMANDS 15 /* Yes, including the NULL */
|
||||||
|
|
||||||
int kshell_start(int argc, char** argv)
|
int kshell_start(int argc, char** argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
@ -73,8 +94,6 @@ int kshell_start(int argc, char** argv)
|
|||||||
|
|
||||||
char* i = NULL;
|
char* i = NULL;
|
||||||
|
|
||||||
terminal_setcolor(VGA_COLOR_LIGHT_BLUE);
|
|
||||||
|
|
||||||
print_intro();
|
print_intro();
|
||||||
|
|
||||||
command = -1;
|
command = -1;
|
||||||
@ -95,59 +114,36 @@ int kshell_start(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (strcmp(i, "sseinfo") == 0)
|
|
||||||
|
for (int j = 0; j < NUM_COMMANDS; j++)
|
||||||
{
|
{
|
||||||
command = 0;
|
if (strcmp(i, commands[j]) == 0)
|
||||||
|
{
|
||||||
|
command = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(i, "kinfo") == 0)
|
|
||||||
{
|
if (command == -1)
|
||||||
command = 1;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "enable_debug") == 0)
|
|
||||||
{
|
|
||||||
_debug = true;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "disable_debug") == 0)
|
|
||||||
{
|
|
||||||
_debug = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "toggle_debug") == 0)
|
|
||||||
{
|
|
||||||
_debug = !_debug;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "get_debug") == 0)
|
|
||||||
{
|
|
||||||
printf("Debugging: %s\n", _debug == true ? "On" : "Off");
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "dumpregs") == 0)
|
|
||||||
{
|
|
||||||
command = 2;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "dumpgprs") == 0)
|
|
||||||
{
|
|
||||||
command = 3;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "kernelmem") == 0)
|
|
||||||
{
|
|
||||||
command = 4;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "sectionmem") == 0)
|
|
||||||
{
|
|
||||||
command = 5;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "testascii") == 0)
|
|
||||||
{
|
|
||||||
command = 6;
|
|
||||||
}
|
|
||||||
else if (strcmp(i, "asciitype") == 0)
|
|
||||||
{
|
|
||||||
command = 7;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
printf("Unknown command %s len %i\n", i, strlen(i));
|
printf("Unknown command %s len %i\n", i, strlen(i));
|
||||||
}
|
}
|
||||||
|
else if (command == 4)
|
||||||
|
{
|
||||||
|
_debug = true;
|
||||||
|
}
|
||||||
|
else if (command == 5)
|
||||||
|
{
|
||||||
|
_debug = false;
|
||||||
|
}
|
||||||
|
else if (command == 6)
|
||||||
|
{
|
||||||
|
_debug = !_debug;
|
||||||
|
}
|
||||||
|
else if (command == 7)
|
||||||
|
{
|
||||||
|
printf("Debugging: %s\n", _debug == true ? "On" : "Off");
|
||||||
|
}
|
||||||
|
|
||||||
if (_debug)
|
if (_debug)
|
||||||
{
|
{
|
||||||
@ -163,23 +159,63 @@ int kshell_start(int argc, char** argv)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("C: %s; %i\n", commands[command], command);
|
||||||
|
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
free(i);
|
if (i != NULL)
|
||||||
|
{
|
||||||
|
free(i);
|
||||||
|
}
|
||||||
|
|
||||||
printf("Goodbye\n");
|
printf("Goodbye!\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static char* commands[] = {
|
||||||
|
"kinfo",
|
||||||
|
"sseinfo",
|
||||||
|
"kernelmem",
|
||||||
|
"sectionmem",
|
||||||
|
|
||||||
|
"enable_debug",
|
||||||
|
"disable_debug",
|
||||||
|
"toggle_debug",
|
||||||
|
"get_debug",
|
||||||
|
|
||||||
|
"dumpregs",
|
||||||
|
"dumpgprs",
|
||||||
|
|
||||||
|
"testascii",
|
||||||
|
|
||||||
|
"printrandom",
|
||||||
|
|
||||||
|
"acm",
|
||||||
|
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
int execute(void)
|
int execute(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
case 0: {
|
case 0: {
|
||||||
|
printf("Espresso %s ", KERNEL_VERSION);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("DEBUG BUILD");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
extern int sse_initialized;
|
extern int sse_initialized;
|
||||||
|
|
||||||
switch (sse_initialized)
|
switch (sse_initialized)
|
||||||
@ -214,20 +250,7 @@ int execute(void)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: {
|
|
||||||
printf("Espresso %s\n", KERNEL_VERSION);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
case 2: {
|
||||||
print_all_regs();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
print_gprs();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: {
|
|
||||||
extern uint8_t __kernel_start;
|
extern uint8_t __kernel_start;
|
||||||
extern uint8_t __kernel_end;
|
extern uint8_t __kernel_end;
|
||||||
size_t kernel_size = (size_t)&__kernel_end - (size_t)&__kernel_start;
|
size_t kernel_size = (size_t)&__kernel_end - (size_t)&__kernel_start;
|
||||||
@ -240,7 +263,7 @@ int execute(void)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5: {
|
case 3: {
|
||||||
extern uint8_t __kernel_text_start;
|
extern uint8_t __kernel_text_start;
|
||||||
extern uint8_t __kernel_text_end;
|
extern uint8_t __kernel_text_end;
|
||||||
extern uint8_t __kernel_rodata_start;
|
extern uint8_t __kernel_rodata_start;
|
||||||
@ -255,7 +278,15 @@ int execute(void)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6: {
|
case 8: {
|
||||||
|
print_all_regs();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 9: {
|
||||||
|
print_gprs();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 10: {
|
||||||
/*extern void terminal_clear(void);*/
|
/*extern void terminal_clear(void);*/
|
||||||
|
|
||||||
terminal_clear();
|
terminal_clear();
|
||||||
@ -271,14 +302,106 @@ int execute(void)
|
|||||||
printf("%c", (char) i);
|
printf("%c", (char) i);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\nCool ASCII art\n%c%c\n%c%c\n", 0xDA, 0xBF, 0xC0, 0xD9);
|
printf("\n\n\\/ Cool ASCII art \\/\n%c%c\n%c%c\n", 0xDA, 0xBF, 0xC0, 0xD9);
|
||||||
|
|
||||||
gets();
|
gets();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: {
|
case 11: {
|
||||||
|
extern void seed_rand(uint32_t seed);
|
||||||
|
extern uint32_t ulrand(void);
|
||||||
|
|
||||||
|
uint64_t v = rdtsc();
|
||||||
|
|
||||||
|
seed_rand((uint32_t) v);
|
||||||
|
|
||||||
|
printf("%ull\n", ulrand());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 12: {
|
||||||
|
printf("Enter hexadecimal address to access: ");
|
||||||
|
char* g = gets();
|
||||||
|
|
||||||
|
int val = atoi(g);
|
||||||
|
|
||||||
|
if (val == 0)
|
||||||
|
{
|
||||||
|
printf("Improper/Malformed string entered\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (val < 0x100000)
|
||||||
|
{
|
||||||
|
printf("Invalid address, must be higher than 0x100000\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int val_ = *((int*) val);
|
||||||
|
|
||||||
|
printf("value at %u: %i\n", val, val_);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 13: {
|
||||||
|
int retv = fat16_mount(0);
|
||||||
|
|
||||||
|
if (retv != 0)
|
||||||
|
{
|
||||||
|
printf("There was an error while mounting volume 0.\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Volume 0 mounted successfully.\n");
|
||||||
|
|
||||||
|
char fat_name[12];
|
||||||
|
fat16_file_t file;
|
||||||
|
|
||||||
|
filename_to_83("test.txt", fat_name);
|
||||||
|
|
||||||
|
retv = fat16_create_file(fat_name, &file);
|
||||||
|
|
||||||
|
if (retv != 0)
|
||||||
|
{
|
||||||
|
printf("There was an error while creating a file on volume 0.\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t buf[512];
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
strcpy((char*) buf, "fg");
|
||||||
|
|
||||||
|
retv = fat16_write_file(&file, buf, (strlen((char*) buf)));
|
||||||
|
|
||||||
|
if (retv != 0)
|
||||||
|
{
|
||||||
|
printf("There was an error while writing to a file on volume 0.\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rbuf[512];
|
||||||
|
memset(rbuf, 0, sizeof(rbuf));
|
||||||
|
|
||||||
|
retv = fat16_read_file(&file, rbuf);
|
||||||
|
|
||||||
|
if (retv != 0)
|
||||||
|
{
|
||||||
|
printf("There was an error while reading from a file on volume 0.\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("The data read should be: %s\n", (char*) buf);
|
||||||
|
printf("Read data: %s\n", (char*) rbuf);
|
||||||
|
printf("Deleting test file\n");
|
||||||
|
|
||||||
|
fat16_delete_file(fat_name);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,13 +4,22 @@
|
|||||||
|
|
||||||
#include <kernel/vars.h>
|
#include <kernel/vars.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Number of bytes in kernel variable space: 4096 (4KiB)
|
||||||
|
Number of bits in kernel variable space: 32768 (32Mib)
|
||||||
|
*/
|
||||||
|
|
||||||
static uint8_t* vars_start = NULL;
|
uint8_t vars[KERNEL_VARIABLES_SIZE];
|
||||||
|
|
||||||
static int num_bytes_used = 0;
|
|
||||||
|
|
||||||
void init_vars(void)
|
void init_vars(void)
|
||||||
{
|
{
|
||||||
vars_start = (uint8_t*) malloc(8 * 1024); /* 1 KiB */
|
memset(vars, 0, KERNEL_VARIABLES_SIZE);
|
||||||
memclr(vars_start, (size_t) 1024);
|
}
|
||||||
|
|
||||||
|
/* bo = bit offset */
|
||||||
|
void set_bit_bo(uint32_t offset, uint8_t val)
|
||||||
|
{
|
||||||
|
/* First, extract the byte offset. (round down to a multiple of 8, and divide by 8. */
|
||||||
|
(void) offset;
|
||||||
|
(void) val;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -301,14 +301,14 @@ void print_lint(int64_t value)
|
|||||||
void print_hex(uint32_t value, int width, bool uppercase)
|
void print_hex(uint32_t value, int width, bool uppercase)
|
||||||
{
|
{
|
||||||
const char* hex_chars = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
|
const char* hex_chars = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||||
char buffer[9]; // 8 hex digits max for 32-bit
|
char buffer[9]; /* 8 hex digits max for 32-bit */
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
buffer[i++] = hex_chars[value & 0xF];
|
buffer[i++] = hex_chars[value & 0xF];
|
||||||
value >>= 4;
|
value >>= 4;
|
||||||
} while (value || i < width); // ensure at least 'width' digits
|
} while (value || i < width); /* ensure at least 'width' digits */
|
||||||
|
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
|
|||||||
24
lib/string.c
24
lib/string.c
@ -172,9 +172,9 @@ char* strchr(const char* s, int c)
|
|||||||
{
|
{
|
||||||
while (*s)
|
while (*s)
|
||||||
{
|
{
|
||||||
if (*s == (char)c)
|
if (*s == (char) c)
|
||||||
{
|
{
|
||||||
return (char*)s;
|
return (char*) s;
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
@ -182,6 +182,22 @@ char* strchr(const char* s, int c)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int num_strchr(const char* s, int c)
|
||||||
|
{
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
if (*s == (char) c)
|
||||||
|
{
|
||||||
|
rv++;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void* memset(void* dst, int c, size_t n)
|
void* memset(void* dst, int c, size_t n)
|
||||||
{
|
{
|
||||||
@ -201,10 +217,10 @@ void* memset(void* dst, int c, size_t n)
|
|||||||
|
|
||||||
void* memcpy(void *dst, const void *src, uint32_t n)
|
void* memcpy(void *dst, const void *src, uint32_t n)
|
||||||
{
|
{
|
||||||
/*if (sse_initialized > 1)
|
if (sse_initialized > 1)
|
||||||
{
|
{
|
||||||
return sse2_memcpy(dst, src, n);
|
return sse2_memcpy(dst, src, n);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
char *d = dst;
|
char *d = dst;
|
||||||
const char *s = src;
|
const char *s = src;
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <emmintrin.h> /* SSE2 intrinsics, TODO: use these in all functions, currently only used in memclr_sse2 */
|
||||||
|
|
||||||
#include <vector_extensions/sse.h>
|
#include <vector_extensions/sse.h>
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +22,7 @@ void enable_sse(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Basic SSE test: add two arrays of 4 floats using xmm registers */
|
/* Basic SSE test: add two arrays of 4 floats using xmm registers */
|
||||||
__attribute__((force_align_arg_pointer))
|
__attribute__((force_align_arg_pointer, target("sse2")))
|
||||||
int32_t test_sse(void)
|
int32_t test_sse(void)
|
||||||
{
|
{
|
||||||
float a[4] __attribute__((aligned(16))) = {1.0f, 2.0f, 3.0f, 4.0f};
|
float a[4] __attribute__((aligned(16))) = {1.0f, 2.0f, 3.0f, 4.0f};
|
||||||
@ -45,7 +47,7 @@ int32_t test_sse(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((force_align_arg_pointer))
|
__attribute__((force_align_arg_pointer, target("sse2")))
|
||||||
void sse2_add_double_arrays(double *dst, const double *a, const double *b, size_t count)
|
void sse2_add_double_arrays(double *dst, const double *a, const double *b, size_t count)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < count; i += 2)
|
for (size_t i = 0; i < count; i += 2)
|
||||||
@ -62,7 +64,7 @@ void sse2_add_double_arrays(double *dst, const double *a, const double *b, size_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((force_align_arg_pointer))
|
__attribute__((force_align_arg_pointer, target("sse2")))
|
||||||
void sse2_add_int64_arrays(int64_t *dst, const int64_t *a, const int64_t *b, size_t count)
|
void sse2_add_int64_arrays(int64_t *dst, const int64_t *a, const int64_t *b, size_t count)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < count; i += 2)
|
for (size_t i = 0; i < count; i += 2)
|
||||||
@ -79,7 +81,7 @@ void sse2_add_int64_arrays(int64_t *dst, const int64_t *a, const int64_t *b, siz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((force_align_arg_pointer))
|
__attribute__((force_align_arg_pointer, target("sse2")))
|
||||||
void sse2_add_int32_arrays(int32_t *dst, const int32_t *a, const int32_t *b, size_t count)
|
void sse2_add_int32_arrays(int32_t *dst, const int32_t *a, const int32_t *b, size_t count)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < count; i += 4)
|
for (size_t i = 0; i < count; i += 4)
|
||||||
@ -96,7 +98,7 @@ void sse2_add_int32_arrays(int32_t *dst, const int32_t *a, const int32_t *b, siz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((force_align_arg_pointer))
|
__attribute__((force_align_arg_pointer, target("sse2")))
|
||||||
void *sse2_memcpy(void *dst, const void *src, uint32_t n)
|
void *sse2_memcpy(void *dst, const void *src, uint32_t n)
|
||||||
{
|
{
|
||||||
uint8_t *d = (uint8_t *)dst;
|
uint8_t *d = (uint8_t *)dst;
|
||||||
@ -136,7 +138,7 @@ void *sse2_memcpy(void *dst, const void *src, uint32_t n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__attribute__((force_align_arg_pointer))
|
__attribute__((force_align_arg_pointer, target("sse2")))
|
||||||
char *sse2_strncpy(char *dest, const char *src, uint32_t n)
|
char *sse2_strncpy(char *dest, const char *src, uint32_t n)
|
||||||
{
|
{
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
@ -218,48 +220,31 @@ void int_vector_to_double_vector(const int32_t *src, double *dst)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void * memclr_sse2(const void * const m_start, const size_t m_count)
|
__attribute__((force_align_arg_pointer, target("sse2")))
|
||||||
|
void* memclr_sse2(void *m_start, size_t m_count)
|
||||||
{
|
{
|
||||||
|
unsigned char *dst = m_start;
|
||||||
/* "i" is our counter of how many bytes we've cleared */
|
size_t i = 0;
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/* find out if "m_start" is aligned on a SSE_XMM_SIZE boundary */
|
while ((uintptr_t)(dst + i) & 15 && i < m_count)
|
||||||
if ((size_t)m_start & (SSE_XMM_SIZE - 1))
|
|
||||||
{
|
{
|
||||||
i = 0;
|
dst[i++] = 0;
|
||||||
|
|
||||||
/* we need to clear byte-by-byte until "m_start" is aligned on an SSE_XMM_SIZE boundary */
|
|
||||||
/* ... and lets make sure we don't copy 'too' many bytes (i < m_count) */
|
|
||||||
while (((size_t)m_start + i) & (SSE_XMM_SIZE - 1) && i < m_count)
|
|
||||||
{
|
|
||||||
asm volatile ("stosb;" :: "D"((size_t)m_start + i), "a"(0));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
__m128i zero = _mm_setzero_si128();
|
||||||
|
|
||||||
|
for (; i + 64 <= m_count; i += 64)
|
||||||
{
|
{
|
||||||
/* if "m_start" was aligned, set our count to 0 */
|
_mm_store_si128((__m128i *)(dst + i + 0), zero);
|
||||||
i = 0;
|
_mm_store_si128((__m128i *)(dst + i + 16), zero);
|
||||||
|
_mm_store_si128((__m128i *)(dst + i + 32), zero);
|
||||||
|
_mm_store_si128((__m128i *)(dst + i + 48), zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
asm volatile ("pxor %%xmm0,%%xmm0"::); /* zero out XMM0 */
|
for (; i < m_count; ++i)
|
||||||
/* clear 64-byte chunks of memory (4 16-byte operations) */
|
|
||||||
for(; i + 64 <= m_count; i += 64)
|
|
||||||
{
|
{
|
||||||
asm volatile (" movdqa %%xmm0, 0(%0); " /* move 16 bytes from XMM0 to %0 + 0 */
|
dst[i] = 0;
|
||||||
" movdqa %%xmm0, 16(%0); "
|
|
||||||
" movdqa %%xmm0, 32(%0); "
|
|
||||||
" movdqa %%xmm0, 48(%0); "
|
|
||||||
:: "r"((size_t)m_start + i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the remaining bytes (if any) */
|
return m_start;
|
||||||
asm volatile (" rep stosb; " :: "a"((size_t)(0)), "D"(((size_t)m_start) + i), "c"(m_count - i));
|
|
||||||
|
|
||||||
/* "i" will contain the total amount of bytes that were actually transfered */
|
|
||||||
i += m_count - i;
|
|
||||||
|
|
||||||
/* we return "m_start" + the amount of bytes that were transfered */
|
|
||||||
return (void *)(((size_t)m_start) + i);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@ -1,5 +0,0 @@
|
|||||||
Loading Espresso 0.0.2a...
|
|
||||||
[ DEBUG ] Testing SSE...
|
|
||||||
[ DEBUG ] SSE test passed
|
|
||||||
Disk model: QEMU HARDDISK
|
|
||||||
Guten tag and welcome to Espresso 0.0.2a
|
|
||||||
Reference in New Issue
Block a user