Espresso 0.0.2a
This commit is contained in:
@ -1,21 +0,0 @@
|
|||||||
Modules and Drivers API
|
|
||||||
|
|
||||||
|
|
||||||
This file contains documentation for the Module/Driver API.
|
|
||||||
|
|
||||||
|
|
||||||
The kernel symtab is always at 0xC0101000, and can go up to 0xC0101000 + 0x8086 ( See what I did there?)
|
|
||||||
|
|
||||||
|
|
||||||
ID number -- Function -- Returns -- Arguments
|
|
||||||
0 -- get_kinfo -- kinfo_t -- uint32_t leaf
|
|
||||||
1 -- make_kfunc -- kfunc_t -- void* addr, bool module, uint16_t module_id, uint32_t function_id
|
|
||||||
2 -- add_kfunc -- uint32_t -- void* addr, bool module, uint16_t module_id, uint32_t function_id
|
|
||||||
3 -- printf -- void -- const char* format, ...
|
|
||||||
4 -- malloc -- void* -- size_t size
|
|
||||||
5 -- free -- void -- void* ptr
|
|
||||||
6 -- calloc -- void* -- size_t nmemb, size_t size
|
|
||||||
7 -- realloc -- void* -- void* ptr, size_t size
|
|
||||||
8 -- get_key -- uint16_t -- void
|
|
||||||
9 -- get_string -- char* -- void
|
|
||||||
10 --
|
|
||||||
25
Makefile
25
Makefile
@ -4,15 +4,16 @@ ISO := boot/espresso.iso
|
|||||||
CC := i686-elf-gcc
|
CC := i686-elf-gcc
|
||||||
AS := i686-elf-as
|
AS := i686-elf-as
|
||||||
NASM := nasm
|
NASM := nasm
|
||||||
QEMU_MKE_IMG := qemu-img create -f raw espresso.img 256M
|
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 32 -S 512
|
||||||
NASMFLAGS := -f elf32
|
NASMFLAGS := -f elf32
|
||||||
WNOFLAGS := -Wno-discarded-qualifiers
|
WNOFLAGS := -Wno-discarded-qualifiers
|
||||||
CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse4 $(WNOFLAGS)
|
CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse $(WNOFLAGS) -nostdlib -nostartfiles -include kincl.h
|
||||||
LDFLAGS := -T linker.ld -ffreestanding -O2 -nostdlib
|
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 := -net none -netdev user,id=n0 -device rtl8139,netdev=n0 -vga std #-singlestep
|
QEMUFLGS_EXT := -vga std -d int,cpu_reset -D qemu.log -no-reboot #-singlestep
|
||||||
|
MOR_QEMUFLGS := -net none -netdev user,id=n0 -device rtl8139,netdev=n0 -serial file:serial.log
|
||||||
SRC_DIRS := kernel drivers lib
|
SRC_DIRS := kernel drivers lib
|
||||||
INCLUDE_DIRS := include
|
INCLUDE_DIRS := include
|
||||||
ARCH_DIR := arch
|
ARCH_DIR := arch
|
||||||
@ -46,6 +47,10 @@ buildc: all iso run clean
|
|||||||
# === Default target ===
|
# === Default target ===
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
|
# === Debug build ===
|
||||||
|
debug:
|
||||||
|
$(MAKE) clean
|
||||||
|
$(MAKE) CFLAGS="$(CFLAGS) -D_DEBUG" $(TARGET)
|
||||||
|
|
||||||
# === Linking ===
|
# === Linking ===
|
||||||
$(TARGET): ./arch/x86/boot/boot.o $(filter-out boot.o, $(OBJ_LINK_LIST))
|
$(TARGET): ./arch/x86/boot/boot.o $(filter-out boot.o, $(OBJ_LINK_LIST))
|
||||||
@ -73,10 +78,11 @@ iso: $(TARGET)
|
|||||||
|
|
||||||
# === Run in QEMU ===
|
# === Run in QEMU ===
|
||||||
run: iso
|
run: iso
|
||||||
$(QEMU_MKE_IMG)
|
@if [ ! -f espresso.img ]; then \
|
||||||
echo "\n"
|
$(QEMU_MKE_IMG); \
|
||||||
$(MKFS_VFAT) $(MKFS_FLAGS) espresso.img
|
fi
|
||||||
qemu-system-i386 $(QEMUFLAGS) $(QEMUFLGS_EXT)
|
@echo
|
||||||
|
qemu-system-i386 $(QEMUFLAGS) $(QEMUFLGS_EXT) $(MOR_QEMUFLGS)
|
||||||
|
|
||||||
|
|
||||||
# === Clean all build artifacts ===
|
# === Clean all build artifacts ===
|
||||||
@ -85,5 +91,4 @@ clean:
|
|||||||
rm -rf $(ISO_DIR)
|
rm -rf $(ISO_DIR)
|
||||||
rm -f espresso.img
|
rm -f espresso.img
|
||||||
|
|
||||||
.PHONY: all clean iso run
|
.PHONY: all clean iso run debug build buildc
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ forced to be within the first 8 KiB of the kernel file.
|
|||||||
/*
|
/*
|
||||||
The multiboot standard does not define the value of the stack pointer register
|
The multiboot standard does not define the value of the stack pointer register
|
||||||
(esp) and it is up to the kernel to provide a stack. This allocates room for a
|
(esp) and it is up to the kernel to provide a stack. This allocates room for a
|
||||||
small stack by creating a symbol at the bottom of it, then allocating 16384
|
small stack by creating a symbol at the bottom of it, then allocating 65536
|
||||||
bytes for it, and finally creating a symbol at the top. The stack grows
|
bytes for it, and finally creating a symbol at the top. The stack grows
|
||||||
downwards on x86. The stack is in its own section so it can be marked nobits,
|
downwards on x86. The stack is in its own section so it can be marked nobits,
|
||||||
which means the kernel file is smaller because it does not contain an
|
which means the kernel file is smaller because it does not contain an
|
||||||
@ -30,10 +30,10 @@ System V ABI standard and de-facto extensions. The compiler will assume the
|
|||||||
stack is properly aligned and failure to align the stack will result in
|
stack is properly aligned and failure to align the stack will result in
|
||||||
undefined behavior.
|
undefined behavior.
|
||||||
*/
|
*/
|
||||||
.section .bss
|
.section .stack
|
||||||
.align 16
|
.align 16
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
.skip 16384 # 16 KiB
|
.skip 65536 # 64 KiB
|
||||||
stack_top:
|
stack_top:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -183,7 +183,6 @@ _start:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Call _kernel_early, early low-level initialization will happen there.
|
Call _kernel_early, early low-level initialization will happen there.
|
||||||
NOTE: I don't use 'jmp' because it doesn't work. Nice try.
|
|
||||||
*/
|
*/
|
||||||
call _kernel_early
|
call _kernel_early
|
||||||
|
|
||||||
|
|||||||
57
arch/x86/cpuid.s
Normal file
57
arch/x86/cpuid.s
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Just a bunch of CPUID stuff.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.extern sse_initialized
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
|
||||||
|
_init_cpuid:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
pushf
|
||||||
|
pop %eax
|
||||||
|
mov %eax, %ecx
|
||||||
|
xor $0x200000, %eax
|
||||||
|
push %eax
|
||||||
|
popf
|
||||||
|
/*pushf*/
|
||||||
|
pop %eax
|
||||||
|
xor %ecx, %eax
|
||||||
|
jz .no_cpuid
|
||||||
|
|
||||||
|
lea _has_cpuid, %edi
|
||||||
|
movl $1, (%edi)
|
||||||
|
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.no_cpuid:
|
||||||
|
lea _has_cpuid, %edi
|
||||||
|
movl $0, (%edi)
|
||||||
|
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.done:
|
||||||
|
popa
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
_sse_level:
|
||||||
|
lea _has_sse, %edi
|
||||||
|
lea sse_initialized, %esi
|
||||||
|
|
||||||
|
movl (%esi), %eax
|
||||||
|
|
||||||
|
movl %eax, (%edi)
|
||||||
|
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
|
.global _has_cpuid
|
||||||
|
|
||||||
|
_has_cpuid: .int 0
|
||||||
|
_has_sse: .int 0
|
||||||
|
_has_mmx: .int 0
|
||||||
46
arch/x86/cpuid_asm.asm
Normal file
46
arch/x86/cpuid_asm.asm
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
.global get_cpu_brand_string
|
||||||
|
|
||||||
|
.type get_cpu_brand_string, @function
|
||||||
|
|
||||||
|
get_cpu_brand_string:
|
||||||
|
pushad # Save all general-purpose registers
|
||||||
|
|
||||||
|
mov ebx, eax # Save buffer pointer to ebx
|
||||||
|
|
||||||
|
mov eax, 0x80000000
|
||||||
|
cpuid
|
||||||
|
cmp eax, 0x80000004 # Check if brand string is supported
|
||||||
|
jb .not_supported
|
||||||
|
|
||||||
|
mov esi, ebx # Copy address to ESI
|
||||||
|
|
||||||
|
mov eax, 0x80000002
|
||||||
|
cpuid
|
||||||
|
mov [esi], eax
|
||||||
|
mov [esi + 4], ebx
|
||||||
|
mov [esi + 8], ecx
|
||||||
|
mov [esi + 12], edx
|
||||||
|
|
||||||
|
mov eax, 0x80000003
|
||||||
|
cpuid
|
||||||
|
mov [esi + 16], eax
|
||||||
|
mov [esi + 20], ebx
|
||||||
|
mov [esi + 24], ecx
|
||||||
|
mov [esi + 28], edx
|
||||||
|
|
||||||
|
mov eax, 0x80000004
|
||||||
|
cpuid
|
||||||
|
mov [esi + 32], eax
|
||||||
|
mov [esi + 36], ebx
|
||||||
|
mov [esi + 40], ecx
|
||||||
|
mov [esi + 44], edx
|
||||||
|
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.not_supported:
|
||||||
|
mov byte [ebx], 0 # Null-terminate if not supported
|
||||||
|
|
||||||
|
.done:
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
|
||||||
0
arch/x86/cpuid_asm.s
Normal file
0
arch/x86/cpuid_asm.s
Normal file
@ -3,25 +3,16 @@
|
|||||||
Mostly so I could get more experience in assembler.
|
Mostly so I could get more experience in assembler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
DO NOT USE "pusha" AND/OR "popa"!!!
|
|
||||||
THEY ARE DEPRECATED (or something like that)
|
|
||||||
AND SHOULD NOT BE USED!!!
|
|
||||||
INSTEAD PUSH/POP REGISTERS ON/OFF THE STACK INDIVIDUALLY!!!
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
||||||
.global _enable_paging_asm
|
.global _enable_paging_asm
|
||||||
|
|
||||||
.global _push_regs
|
|
||||||
.global _pop_regs
|
|
||||||
|
|
||||||
.global _hang_asm
|
.global _hang_asm
|
||||||
.global _halt_asm
|
.global _halt_asm
|
||||||
|
|
||||||
.global _sti_asm
|
.global _sti_asm
|
||||||
|
.global _cli_asm
|
||||||
|
|
||||||
|
|
||||||
_enable_paging_asm:
|
_enable_paging_asm:
|
||||||
@ -35,30 +26,6 @@ _enable_paging_asm:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
_push_regs:
|
|
||||||
push %eax
|
|
||||||
push %ebx
|
|
||||||
push %ecx
|
|
||||||
push %edx
|
|
||||||
push %esi
|
|
||||||
push %edi
|
|
||||||
push %esp
|
|
||||||
push %ebp
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
_pop_regs:
|
|
||||||
pop %ebp
|
|
||||||
pop %esp
|
|
||||||
pop %edi
|
|
||||||
pop %esi
|
|
||||||
pop %edx
|
|
||||||
pop %ecx
|
|
||||||
pop %ebx
|
|
||||||
pop %eax
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
_hang_asm:
|
_hang_asm:
|
||||||
hlt
|
hlt
|
||||||
jmp _hang_asm
|
jmp _hang_asm
|
||||||
@ -71,4 +38,6 @@ _sti_asm:
|
|||||||
sti
|
sti
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.section .data
|
_cli_asm:
|
||||||
|
cli
|
||||||
|
ret
|
||||||
|
|||||||
6
dev_notes/memory_mapping.txt
Normal file
6
dev_notes/memory_mapping.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
so far, heap starts at 0xC2000000, and is (8 * 1024 * 1024) (0x80000) or (8MiB) bytes, and ends at 0xC2080000
|
||||||
|
|
||||||
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
Notes about the PS/2 keyboard driver.
|
|
||||||
|
|
||||||
|
|
||||||
the actual key-codes are not what you might expect.
|
|
||||||
what I mean is, what does 0x3F mean? what key was pressed?
|
|
||||||
The keyset used by Espresso is pretty much the ASCII code set.
|
|
||||||
Minus a few codes, some are replaced with other functions.
|
|
||||||
@ -13,10 +13,10 @@
|
|||||||
|
|
||||||
elf_executable_t* load_elf32(void* elf_data)
|
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 */
|
/* 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");
|
printf("Invalid ELF file\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -58,6 +58,8 @@ elf_executable_t* load_elf32(void* elf_data)
|
|||||||
|
|
||||||
elf_executable_t* result = malloc(sizeof(elf_executable_t));
|
elf_executable_t* result = malloc(sizeof(elf_executable_t));
|
||||||
result->entry_point = (void*)(uintptr_t)ehdr->e_entry;
|
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;
|
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 */
|
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)
|
if (ide_identify(0, identify_buf) == 0)
|
||||||
{
|
{
|
||||||
char model[41];
|
char model[41];
|
||||||
@ -78,9 +84,18 @@ void ide_initialize(void) {
|
|||||||
model[40] = 0;
|
model[40] = 0;
|
||||||
printf("Disk model: %s\n", model);
|
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)
|
if (sector_count == 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <drivers/ps2_keyboard.h>
|
#include <drivers/ps2_keyboard.h>
|
||||||
#include <drivers/pit.h>
|
#include <drivers/pit.h>
|
||||||
|
#include <port_io.h>
|
||||||
|
|
||||||
#include <drivers/irq.h>
|
#include <drivers/irq.h>
|
||||||
|
|
||||||
#define NUM_IRQS 0x90
|
#define NUM_IRQS 0x90
|
||||||
|
|
||||||
irq_func_t func_list[NUM_IRQS];
|
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)
|
void irq_init(void)
|
||||||
{
|
{
|
||||||
memset(func_list, 0x0, NUM_IRQS);
|
for (int i = 0; i < NUM_IRQS; i++)
|
||||||
memset(aux_func_list, 0x0, NUM_IRQS);
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
@ -29,10 +30,7 @@ void irq_handler(uint8_t irq_number)
|
|||||||
if (func_list[irq_number])
|
if (func_list[irq_number])
|
||||||
{
|
{
|
||||||
func_list[irq_number]();
|
func_list[irq_number]();
|
||||||
}
|
outb(0x20, 0x20); /* Acknowledge the IRQ to PIC */
|
||||||
else if (aux_func_list[irq_number])
|
|
||||||
{
|
|
||||||
aux_func_list[irq_number]();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -48,21 +46,3 @@ void set_irq_handler(uint32_t num, irq_func_t* handler)
|
|||||||
func_list[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)
|
void pci_enumerate(void)
|
||||||
{
|
{
|
||||||
@ -77,7 +89,7 @@ void pci_enumerate(void)
|
|||||||
|
|
||||||
if (pre_header.class_code == 0xB)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +102,9 @@ void pci_enumerate(void)
|
|||||||
{
|
{
|
||||||
/*configure_ahci_controller(hdr);*/
|
/*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);*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,10 @@ bool pit_initialized = false;
|
|||||||
|
|
||||||
void pit_init(void)
|
void pit_init(void)
|
||||||
{
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("[ PIT ] Initializing the PIT...\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
uint16_t divisor = (uint16_t)1193;
|
uint16_t divisor = (uint16_t)1193;
|
||||||
|
|
||||||
/* Send command byte */
|
/* Send command byte */
|
||||||
@ -25,6 +29,10 @@ void pit_init(void)
|
|||||||
outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF)); /* High byte */
|
outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF)); /* High byte */
|
||||||
|
|
||||||
pit_initialized = true;
|
pit_initialized = true;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("[ PIT ] PIT Initialized\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void pit_handler(void)
|
void pit_handler(void)
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
#include <port_io.h>
|
#include <port_io.h>
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ksymtab.h>
|
|
||||||
|
|
||||||
#include <drivers/ps2_keyboard.h>
|
#include <drivers/ps2_keyboard.h>
|
||||||
|
|
||||||
@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#define KEYBOARD_IRQ 1
|
#define KEYBOARD_IRQ 1
|
||||||
|
|
||||||
|
#define RETURN_STI() do { _sti_asm(); return; } while (0)
|
||||||
|
|
||||||
bool ps2keyboard_initialized = false;
|
bool ps2keyboard_initialized = false;
|
||||||
|
|
||||||
/* State for shift key */
|
/* State for shift key */
|
||||||
@ -43,12 +45,23 @@ static bool extended = false;
|
|||||||
static bool is_new_char = 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 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 int hook_count = 0;
|
||||||
|
|
||||||
|
extern void _cli_asm(void);
|
||||||
|
extern void _sti_asm(void);
|
||||||
|
|
||||||
static const char scancode_map[128] = {
|
static const char scancode_map[128] = {
|
||||||
0, 27, '1','2','3','4','5','6','7','8','9','0','-','=','\b', /* Backspace */
|
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)
|
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) */
|
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;
|
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)
|
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.
|
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:
|
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.
|
- 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;
|
is_new_char = false;
|
||||||
|
return current_char;
|
||||||
return temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t get_key(void)
|
uint16_t get_key(void)
|
||||||
@ -122,39 +251,184 @@ char* get_string(void)
|
|||||||
return current_string;
|
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)
|
if (current_length + 1 >= capacity)
|
||||||
{
|
{
|
||||||
/* Need more space (+1 for the null zero) */
|
|
||||||
int new_capacity = (capacity == 0) ? 16 : capacity * 2;
|
int new_capacity = (capacity == 0) ? 16 : capacity * 2;
|
||||||
|
|
||||||
char* new_str = (char*)malloc(new_capacity);
|
char* new_str = (char*) malloc(new_capacity);
|
||||||
if (!new_str) {
|
|
||||||
|
if (!new_str)
|
||||||
|
{
|
||||||
|
printf("[keyboard] ERROR: malloc failed for new input buffer\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (current_string)
|
if (current_string)
|
||||||
{
|
{
|
||||||
memcpy(new_str, current_string, current_length);
|
memcpy(new_str, current_string, current_length);
|
||||||
free(current_string);
|
free(current_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_string = new_str;
|
||||||
|
capacity = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
if (!current_string)
|
if (!current_string)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_string = new_str;
|
|
||||||
capacity = new_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_string[current_length] = c;
|
current_string[current_length] = c;
|
||||||
current_length++;
|
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)
|
if (current_string)
|
||||||
{
|
{
|
||||||
@ -198,8 +472,8 @@ void keyboard_handler(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint16_t c = (uint16_t)scancode_map[scancode];
|
uint16_t c = (uint16_t) scancode_map[scancode];
|
||||||
if ((shift_pressed ^ capslock_pressed) && ((char)c >= 'a') && ((char)c <= 'z'))
|
if ((shift_pressed ^ capslock_pressed) && ((char) c >= 'a') && ((char) c <= 'z'))
|
||||||
{
|
{
|
||||||
c -= 32; /* Convert to uppercase */
|
c -= 32; /* Convert to uppercase */
|
||||||
}
|
}
|
||||||
@ -208,11 +482,10 @@ void keyboard_handler(void)
|
|||||||
c = (uint16_t) terminal_get_shifted((unsigned char) c);
|
c = (uint16_t) terminal_get_shifted((unsigned char) c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (scancode == 0x1C) {
|
if (hook_count > 0)
|
||||||
printf("\n");
|
{
|
||||||
return;
|
call_hooks(c);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
|
||||||
if (extended)
|
if (extended)
|
||||||
{
|
{
|
||||||
@ -235,6 +508,13 @@ void keyboard_handler(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gets_called)
|
||||||
|
{
|
||||||
|
gets_append_char(c);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
current_key = c;
|
current_key = c;
|
||||||
|
|
||||||
is_new_key = true;
|
is_new_key = true;
|
||||||
@ -243,19 +523,34 @@ void keyboard_handler(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gets_called)
|
||||||
|
{
|
||||||
|
gets_append_char(c);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
current_char = c;
|
if (c != '\n')
|
||||||
|
{
|
||||||
|
append_char(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_char = c;
|
||||||
is_new_char = true;
|
is_new_char = true;
|
||||||
|
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
|
/*append_char(c);
|
||||||
|
current_char = c;
|
||||||
|
is_new_char = true;*/
|
||||||
|
|
||||||
free_current_string();
|
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;
|
||||||
|
}
|
||||||
107
drivers/tty.c
107
drivers/tty.c
@ -1,16 +1,21 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vga/vga.h>
|
#include <vga/vga.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <port_io.h>
|
||||||
|
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
|
|
||||||
static size_t terminal_row;
|
size_t terminal_row;
|
||||||
static size_t terminal_column;
|
size_t terminal_column;
|
||||||
static uint8_t terminal_color;
|
uint8_t terminal_color;
|
||||||
static uint16_t* terminal_buffer;
|
uint16_t* terminal_buffer;
|
||||||
|
|
||||||
|
|
||||||
void terminal_initialize(void)
|
void terminal_initialize(void)
|
||||||
{
|
{
|
||||||
terminal_initializec(0x00);
|
terminal_initializec(0x00);
|
||||||
|
|
||||||
|
terminal_update_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_initializec(uint8_t color)
|
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);
|
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
terminal_color = color;
|
terminal_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal_buffer = VGA_MEMORY;
|
terminal_buffer = VGA_MEMORY;
|
||||||
|
|
||||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||||
{
|
{
|
||||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||||
@ -55,16 +62,29 @@ void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y)
|
|||||||
|
|
||||||
void terminal_putchar(const char c)
|
void terminal_putchar(const char c)
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned char uc = c;
|
unsigned char uc = c;
|
||||||
|
|
||||||
if (uc == '\n')
|
if (uc == '\n')
|
||||||
{
|
{
|
||||||
terminal_column = 0;
|
terminal_column = 0;
|
||||||
if (++terminal_row == VGA_HEIGHT)
|
if (++terminal_row == VGA_HEIGHT)
|
||||||
|
{
|
||||||
|
if (1)
|
||||||
{
|
{
|
||||||
terminal_scroll();
|
terminal_scroll();
|
||||||
terminal_row = VGA_HEIGHT - 1;
|
terminal_row = VGA_HEIGHT - 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal_clear();
|
||||||
|
terminal_row = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal_update_cursor();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (uc == '\t')
|
else if (uc == '\t')
|
||||||
@ -76,27 +96,34 @@ void terminal_putchar(const char c)
|
|||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminal_update_cursor();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (uc == '\b')
|
else if (uc == '\b')
|
||||||
{
|
{
|
||||||
if (terminal_column == 0)
|
if (terminal_column == 0)
|
||||||
{
|
{
|
||||||
terminal_row -= 1;
|
if (terminal_row > 0)
|
||||||
|
|
||||||
if (terminal_row == (size_t)-1)
|
|
||||||
{
|
{
|
||||||
terminal_row = 0;
|
terminal_row--;
|
||||||
}
|
terminal_column = VGA_WIDTH - 1;
|
||||||
|
|
||||||
terminal_column = VGA_WIDTH;
|
|
||||||
|
|
||||||
terminal_putentryat(' ', terminal_getcolor(), (size_t)terminal_column, (size_t)terminal_row);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
terminal_putentryat(' ', terminal_getcolor(), (size_t)--terminal_column, (size_t)terminal_row);
|
terminal_update_cursor(); /* For good measure */
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal_column--;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal_putentryat(' ', terminal_color, terminal_column, terminal_row);
|
||||||
|
|
||||||
|
terminal_update_cursor();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -110,9 +137,10 @@ void terminal_putchar(const char c)
|
|||||||
if (++terminal_row == VGA_HEIGHT)
|
if (++terminal_row == VGA_HEIGHT)
|
||||||
{
|
{
|
||||||
terminal_scroll();
|
terminal_scroll();
|
||||||
terminal_row = VGA_HEIGHT - 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminal_update_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_write(const char* data, size_t size)
|
void terminal_write(const char* data, size_t size)
|
||||||
@ -157,7 +185,7 @@ 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());
|
||||||
}
|
}
|
||||||
@ -182,20 +210,18 @@ void terminal_clearl(size_t num_lines)
|
|||||||
|
|
||||||
void terminal_scroll(void)
|
void terminal_scroll(void)
|
||||||
{
|
{
|
||||||
for (size_t y = 1; y < VGA_HEIGHT; y++)
|
|
||||||
{
|
|
||||||
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++)
|
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++)
|
||||||
{
|
{
|
||||||
const size_t index = (VGA_HEIGHT - 1) * VGA_WIDTH + x;
|
terminal_putentryat((unsigned char)' ', terminal_getcolor(), (size_t)terminal_row, (size_t)k);
|
||||||
terminal_buffer[index] = (terminal_color << 8) | ' ';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +234,7 @@ unsigned char terminal_get_shifted(unsigned char uc)
|
|||||||
unsigned char syms1[] = { ',', '.', '/', ';', '\'', '[', ']', '`', '-', '=', '\\', '\0' };
|
unsigned char syms1[] = { ',', '.', '/', ';', '\'', '[', ']', '`', '-', '=', '\\', '\0' };
|
||||||
unsigned char syms2[] = { '<', '>', '?', ':', '\"', '{', '}', '~', '_', '+', '|', '\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])
|
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])
|
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])
|
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)
|
if (row < VGA_HEIGHT && column < VGA_WIDTH)
|
||||||
{
|
{
|
||||||
terminal_row = (size_t)row;
|
terminal_row = (size_t) row;
|
||||||
terminal_column = (size_t)column;
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
16
include/ctype.h
Normal file
16
include/ctype.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _CHAR_TYPE_H
|
||||||
|
#define _CHAR_TYPE_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
int32_t ischar(int32_t c);
|
||||||
|
int32_t isspace(char c);
|
||||||
|
int32_t isalpha(char c);
|
||||||
|
int isprint(int c);
|
||||||
|
char upper(char c);
|
||||||
|
char toupper(char c);
|
||||||
|
char lower(char c);
|
||||||
|
char toupper(char c);
|
||||||
|
char lower(char c);
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -62,6 +62,8 @@ struct pci_header_type_0 {
|
|||||||
uint8_t max_latency;
|
uint8_t max_latency;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
void pci_init(void);
|
||||||
|
|
||||||
uint32_t pci_config_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset);
|
uint32_t pci_config_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset);
|
||||||
void pci_config_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value);
|
void pci_config_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value);
|
||||||
void pci_enumerate(void);
|
void pci_enumerate(void);
|
||||||
|
|||||||
@ -2,16 +2,26 @@
|
|||||||
#define _PS2_KEYBOARD_H
|
#define _PS2_KEYBOARD_H
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
#include <drivers/irq.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
KEY_NONE = 0,
|
KEY_NONE = 0,
|
||||||
KEY_ARROW_UP = 0xAA0,
|
KEY_ARROW_UP = 0xFC,
|
||||||
KEY_ARROW_DOWN,
|
KEY_ARROW_DOWN,
|
||||||
KEY_ARROW_LEFT,
|
KEY_ARROW_LEFT,
|
||||||
KEY_ARROW_RIGHT,
|
KEY_ARROW_RIGHT,
|
||||||
/* Note: add more special keys here */
|
/* Note: add more special keys here */
|
||||||
} special_key;
|
} special_key;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KEY_UP = 0x1E,
|
||||||
|
KEY_DOWN = 0x1F,
|
||||||
|
KEY_RIGHT = 0x1C,
|
||||||
|
KEY_LEFT = 0x1D,
|
||||||
|
} lower_key;
|
||||||
|
|
||||||
|
typedef void (*ps2_hook_t)(char);
|
||||||
|
|
||||||
void keyboard_init(void);
|
void keyboard_init(void);
|
||||||
void keyboard_handler(void);
|
void keyboard_handler(void);
|
||||||
|
|
||||||
@ -19,4 +29,9 @@ char get_char(void);
|
|||||||
uint16_t get_key(void);
|
uint16_t get_key(void);
|
||||||
char* get_string(void);
|
char* get_string(void);
|
||||||
|
|
||||||
|
char* kbd_gets(void);
|
||||||
|
|
||||||
|
bool setup_hook(ps2_hook_t func);
|
||||||
|
bool remove_hook(ps2_hook_t func);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
14
include/drivers/serio.h
Normal file
14
include/drivers/serio.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _SERIAL_IO_H
|
||||||
|
#define _SERIAL_IO_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
int serial_init(void);
|
||||||
|
|
||||||
|
void serial_write(char a);
|
||||||
|
void serial_puts(const char* s);
|
||||||
|
char serial_read(void);
|
||||||
|
|
||||||
|
bool use_serial(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
19
include/fs/ssfs.h
Normal file
19
include/fs/ssfs.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _STUPID_SIMPLE_FS_H
|
||||||
|
#define _STUPID_SIMPLE_FS_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef struct ssfs_file_header {
|
||||||
|
char filename[16]; /* 15 chars + null zero */
|
||||||
|
|
||||||
|
uint32_t num_sectors;
|
||||||
|
uint64_t start_sector;
|
||||||
|
uint32_t num_bytes;
|
||||||
|
|
||||||
|
/*uint8_t padding_[11];*/ /* 32 bytes without this */
|
||||||
|
} __attribute__((packed)) ssfs_file_header_t;
|
||||||
|
|
||||||
|
int ssfs_read_file(const char* name, void* buffer, int size);
|
||||||
|
int ssfs_write_file(const char* name, void* data, int size);
|
||||||
|
|
||||||
|
#endif
|
||||||
15
include/kdebug.h
Normal file
15
include/kdebug.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _KERNEL_DEBUG_H
|
||||||
|
#define _KERNEL_DEBUG_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
void set_debug(void);
|
||||||
|
|
||||||
|
void clear_debug(void);
|
||||||
|
|
||||||
|
void toggle_debug(void);
|
||||||
|
|
||||||
|
bool get_debug(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -2,6 +2,6 @@
|
|||||||
#define _KERNEL_BOOT_H
|
#define _KERNEL_BOOT_H
|
||||||
|
|
||||||
|
|
||||||
uint8_t parse_boot_data(const char* data);
|
void clear_bss(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
|
void intro_begin(void);
|
||||||
int16_t begin_anim(const char* version);
|
int16_t begin_anim(const char* version);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
7
include/kernel/ksh_debug.h
Normal file
7
include/kernel/ksh_debug.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef _KERNEL_SHELL_DEBUGGER_H
|
||||||
|
#define _KERNEL_SHELL_DEBUGGER_H
|
||||||
|
|
||||||
|
void print_all_regs(void);
|
||||||
|
void print_gprs(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
0
include/kernel/kshell.c
Normal file
0
include/kernel/kshell.c
Normal file
8
include/kernel/kshell.h
Normal file
8
include/kernel/kshell.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _KERNEL_SHELL_H
|
||||||
|
#define _KERNEL_SHELL_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
int kshell_start(int argc, char** argv);
|
||||||
|
|
||||||
|
#endif
|
||||||
7
include/kernel/vars.h
Normal file
7
include/kernel/vars.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef _KERNEL_VARIABLES_H
|
||||||
|
#define _KERNEL_VARIABLES_H
|
||||||
|
|
||||||
|
|
||||||
|
void init_vars(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,23 +0,0 @@
|
|||||||
#ifndef _KSYMTAB_H
|
|
||||||
#define _KSYMTAB_H
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
typedef struct kfunc {
|
|
||||||
/*
|
|
||||||
Bit 31 = 1 -> driver/module function, Bit 31 = 0 -> kernel function
|
|
||||||
Bits 30-20 -> module/driver ID (11 bits)
|
|
||||||
Bits 19-0 -> function ID (20 bits)
|
|
||||||
*/
|
|
||||||
uint32_t id;
|
|
||||||
|
|
||||||
uint32_t addr; /* Pointer to function, 0x0 if nonexistent */
|
|
||||||
} kfunc_t;
|
|
||||||
|
|
||||||
uint64_t kfunc_call(kfunc_t* func, uint32_t a, uint32_t b, uint32_t c, uint32_t d);
|
|
||||||
uint64_t call_kfunc_by_id(uint32_t id, uint32_t a, uint32_t b, uint32_t c, uint32_t d);
|
|
||||||
|
|
||||||
uint32_t add_kfunc(void* addr, bool module, uint16_t module_id, uint32_t function_id);
|
|
||||||
kfunc_t make_kfunc(void* addr, bool module, uint16_t module_id, uint32_t function_id);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
17
include/math.h
Normal file
17
include/math.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _MATH_H
|
||||||
|
#define _MATH_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
bool is_low_power_of_two(int n);
|
||||||
|
|
||||||
|
uint64_t int_pow(uint64_t base, uint32_t exp);
|
||||||
|
|
||||||
|
/* Divide a by b, rounding up */
|
||||||
|
static inline int div_round_up(int a, int b)
|
||||||
|
{
|
||||||
|
return (a + b - 1) / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,19 +1,13 @@
|
|||||||
#ifndef _HEAP_H
|
#ifndef _HEAP_H
|
||||||
#define _HEAP_H
|
#define _HEAP_H
|
||||||
|
|
||||||
#include <types.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#define HEAP_START 0xC0000000
|
|
||||||
#define HEAP_SIZE (1024 * 4096) /* 1MB heap */
|
|
||||||
|
|
||||||
void heap_init(void);
|
|
||||||
|
|
||||||
|
void heap_init(uint32_t start, uint32_t size);
|
||||||
void* malloc(size_t size);
|
void* malloc(size_t size);
|
||||||
void* malloc_aligned(size_t size, size_t alignment);
|
void free(void* ptr);
|
||||||
|
|
||||||
void* calloc(size_t nmemb, size_t size);
|
void* calloc(size_t nmemb, size_t size);
|
||||||
void* realloc(void* ptr, size_t size);
|
void* realloc(void* ptr, size_t size);
|
||||||
|
|
||||||
void free(void* ptr);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
#ifndef _PAGING_H
|
#ifndef _PAGING_H
|
||||||
#define _PAGING_H
|
#define _PAGING_H
|
||||||
|
|
||||||
#include <types.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void paging_init(void);
|
void paging_init(void);
|
||||||
void map_page(void* phys, void* virt);
|
void map_page(void* phys_addr, void* virt_addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <multiboot.h>
|
#include <multiboot.h>
|
||||||
|
|
||||||
void pmm_init(multiboot_info_t* mb_info);
|
void pmm_init(multiboot_info_t* mb);
|
||||||
void* alloc_page(void);
|
void* pmm_alloc_page(void);
|
||||||
void free_page(void* ptr);
|
void pmm_free_page(void* addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
12
include/mm_macros.h
Normal file
12
include/mm_macros.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _MM_MACROS_H
|
||||||
|
#define _MM_MACROS_H
|
||||||
|
|
||||||
|
#define MEMSET(ptr, value, num) \
|
||||||
|
do { \
|
||||||
|
unsigned char *_p = (unsigned char*)(ptr); \
|
||||||
|
for (size_t _i = 0; _i < (num); ++_i) \
|
||||||
|
_p[_i] = (unsigned char)(value); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -12,9 +12,13 @@ void printd(const char* str);
|
|||||||
void printf(const char*, ...);
|
void printf(const char*, ...);
|
||||||
|
|
||||||
void print_int(int32_t value);
|
void print_int(int32_t value);
|
||||||
|
void print_lint(int64_t value);
|
||||||
void print_uint(uint32_t value);
|
void print_uint(uint32_t value);
|
||||||
|
void print_luint(uint64_t value);
|
||||||
void print_hex(uint32_t value, int width, bool uppercase);
|
void print_hex(uint32_t value, int width, bool uppercase);
|
||||||
void print_hex64(uint64_t value, int width, bool uppercase);
|
void print_hex64(uint64_t value, int width, bool uppercase);
|
||||||
void print_double(double value, int precision);
|
void print_double(double value, int precision);
|
||||||
|
|
||||||
|
void printf_set_color(uint8_t _color);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -6,5 +6,11 @@
|
|||||||
|
|
||||||
char getchar(void);
|
char getchar(void);
|
||||||
char* getstring(void);
|
char* getstring(void);
|
||||||
|
char* gets(void); /* Use this instead of getstring() */
|
||||||
|
|
||||||
|
static inline void putchar(char c)
|
||||||
|
{
|
||||||
|
printf("%c", c);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#define STRING_H
|
#define STRING_H
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/* TODO: change all applicable `int32_t`s with `size_t`s. */
|
/* TODO: change all applicable `int32_t`s with `size_t`s. */
|
||||||
|
|
||||||
@ -16,18 +17,17 @@ 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);
|
||||||
|
|
||||||
int32_t ischar(int32_t c);
|
void lowers(char* str);
|
||||||
int32_t isspace(char c);
|
void uppers(char* str);
|
||||||
int32_t isalpha(char c);
|
|
||||||
char upper(char c);
|
|
||||||
char lower(char c);
|
|
||||||
char toupper(char c);
|
|
||||||
char lower(char c);
|
|
||||||
|
|
||||||
void* memset(void *dst, char c, uint32_t n);
|
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);
|
||||||
int32_t memcmp(const void *s1, const void *s2, size_t n);
|
int32_t memcmp(const void *s1, const void *s2, size_t n);
|
||||||
void* memclr(void* m_start, size_t m_count);
|
void* memclr(void* m_start, size_t m_count);
|
||||||
|
void* memmove(void* dest, const void* src, size_t n);
|
||||||
|
|
||||||
|
int atoi(const char *str);
|
||||||
|
long atol(const char *str);
|
||||||
|
double atof(const char *str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -26,5 +26,6 @@ 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_update_cursor(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,16 +1,66 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <cpuid.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <kernel/boot.h>
|
#include <kernel/boot.h>
|
||||||
|
|
||||||
|
|
||||||
uint8_t parse_boot_data(const char* data)
|
extern uint8_t __bss_start;
|
||||||
|
extern uint8_t __bss_end;
|
||||||
|
|
||||||
|
|
||||||
|
void clear_bss(void)
|
||||||
{
|
{
|
||||||
if (strlen(data) == 0)
|
/*memset(&__bss_start, 0, &__bss_end - &__bss_start);*/
|
||||||
|
|
||||||
|
for (int i = 0; i < ((&__bss_end) - (&__bss_start)); i++)
|
||||||
{
|
{
|
||||||
return 0;
|
(&(__bss_start))[i] = 0x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_cpu_vendor_string(void)
|
||||||
|
{
|
||||||
|
unsigned int eax, ebx, ecx, edx;
|
||||||
|
char vendor[13];
|
||||||
|
|
||||||
|
if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx))
|
||||||
|
{
|
||||||
|
return strdup("Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
memcpy(&vendor[0], &ebx, 4);
|
||||||
|
memcpy(&vendor[4], &edx, 4);
|
||||||
|
memcpy(&vendor[8], &ecx, 4);
|
||||||
|
vendor[12] = '\0';
|
||||||
|
|
||||||
|
return strdup(vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_cpu_brand_string(void)
|
||||||
|
{
|
||||||
|
unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||||
|
|
||||||
|
int k = __get_cpuid_max(0x80000000, NULL);
|
||||||
|
|
||||||
|
if (k >= (int) 0x80000005)
|
||||||
|
{
|
||||||
|
return strdup("Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
char brand[49];
|
||||||
|
unsigned int* brand_ptr = (unsigned int*) brand;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
__get_cpuid(0x80000002 + i, &eax, &ebx, &ecx, &edx);
|
||||||
|
brand_ptr[i * 4 + 0] = eax;
|
||||||
|
brand_ptr[i * 4 + 1] = ebx;
|
||||||
|
brand_ptr[i * 4 + 2] = ecx;
|
||||||
|
brand_ptr[i * 4 + 3] = edx;
|
||||||
|
}
|
||||||
|
|
||||||
|
brand[48] = '\0';
|
||||||
|
return strdup(brand);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,30 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <port_io.h>
|
#include <stdlib.h>
|
||||||
|
#include <drivers/ps2_keyboard.h>
|
||||||
|
|
||||||
#include <kernel/intro.h>
|
#include <kernel/intro.h>
|
||||||
|
|
||||||
void delay_us(uint32_t microseconds, uint32_t cpu_mhz)
|
void ack_char(char c);
|
||||||
{
|
void start_kernel_shell(void);
|
||||||
uint32_t count = cpu_mhz * microseconds;
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
asm volatile ("nop" ::: "memory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
char char_entered = 0x00;
|
||||||
|
|
||||||
|
void intro_begin(void)
|
||||||
|
{
|
||||||
|
extern char* kernel_version;
|
||||||
|
|
||||||
|
char* fin = (char*) malloc(strlen(kernel_version) + 6);
|
||||||
|
memset(fin, 0, (strlen(kernel_version) + 5));
|
||||||
|
strcpy(fin, kernel_version);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
strcat(fin, " DEBUG");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
begin_anim(fin);
|
||||||
|
}
|
||||||
|
|
||||||
int16_t begin_anim(const char* version)
|
int16_t begin_anim(const char* version)
|
||||||
{
|
{
|
||||||
@ -32,10 +43,17 @@ int16_t begin_anim(const char* version)
|
|||||||
int32_t sh_pos = VGA_WIDTH / 2;
|
int32_t sh_pos = VGA_WIDTH / 2;
|
||||||
int32_t sv_pos = VGA_HEIGHT / 2;
|
int32_t sv_pos = VGA_HEIGHT / 2;
|
||||||
|
|
||||||
|
setup_hook((ps2_hook_t) ack_char);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
terminal_clear();
|
terminal_clear();
|
||||||
|
|
||||||
|
if (char_entered != 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (int32_t i = 0; n[i]; ++i)
|
for (int32_t i = 0; n[i]; ++i)
|
||||||
{
|
{
|
||||||
terminal_putentryat(n[i], terminal_getcolor(), sh_pos, sv_pos);
|
terminal_putentryat(n[i], terminal_getcolor(), sh_pos, sv_pos);
|
||||||
@ -64,11 +82,35 @@ int16_t begin_anim(const char* version)
|
|||||||
|
|
||||||
b = 0;
|
b = 0;
|
||||||
|
|
||||||
delay_us(50000, 5000);
|
sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (char_entered != 0)
|
||||||
|
{
|
||||||
|
start_kernel_shell();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
terminal_clear();
|
terminal_clear();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ack_char(char c)
|
||||||
|
{
|
||||||
|
char_entered = c;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_kernel_shell(void)
|
||||||
|
{
|
||||||
|
/* terminal_clear() already called by begin_anim() */
|
||||||
|
|
||||||
|
extern int kshell_start(int argc, char** argv);
|
||||||
|
|
||||||
|
kshell_start(0, NULL);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|||||||
25
kernel/kdebug.c
Normal file
25
kernel/kdebug.c
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include <kdebug.h>
|
||||||
|
|
||||||
|
static bool __debug = false;
|
||||||
|
|
||||||
|
void set_debug(void)
|
||||||
|
{
|
||||||
|
__debug = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_debug(void)
|
||||||
|
{
|
||||||
|
__debug = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle_debug(void)
|
||||||
|
{
|
||||||
|
__debug = !__debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_debug(void)
|
||||||
|
{
|
||||||
|
return __debug;
|
||||||
|
}
|
||||||
@ -11,8 +11,13 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <kernel/boot.h>
|
#include <kernel/boot.h>
|
||||||
|
#include <kernel/kshell.h>
|
||||||
|
|
||||||
|
#include <kdebug.h>
|
||||||
|
|
||||||
#include <gdt.h>
|
#include <gdt.h>
|
||||||
#include <drivers/idt.h>
|
#include <drivers/idt.h>
|
||||||
@ -20,7 +25,6 @@
|
|||||||
|
|
||||||
#include <multiboot.h>
|
#include <multiboot.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <drivers/pci.h>
|
#include <drivers/pci.h>
|
||||||
#include <drivers/ps2_keyboard.h>
|
#include <drivers/ps2_keyboard.h>
|
||||||
#include <drivers/pit.h>
|
#include <drivers/pit.h>
|
||||||
@ -38,6 +42,8 @@
|
|||||||
|
|
||||||
#include <builtin_games/miner.h>
|
#include <builtin_games/miner.h>
|
||||||
|
|
||||||
|
#include <fs/ssfs.h>
|
||||||
|
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
|
||||||
|
|
||||||
@ -53,18 +59,24 @@ char* espresso_str = ""
|
|||||||
"# # # # # # # # # # # # #\n"
|
"# # # # # # # # # # # # #\n"
|
||||||
"####### ##### # # # ####### ##### ##### #######\n";
|
"####### ##### # # # ####### ##### ##### #######\n";
|
||||||
|
|
||||||
|
char* kernel_version = "0.0.2a";
|
||||||
|
|
||||||
|
|
||||||
void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* --- BEGIN INITIALIZATION SECTION --- */
|
/* --- BEGIN INITIALIZATION SECTION --- */
|
||||||
|
|
||||||
const char* espresso_kernel_version = "0.0.1e";
|
|
||||||
|
|
||||||
/* We need to initialize the terminal so that any error/debugging messages show. */
|
/* We need to initialize the terminal so that any error/debugging messages show. */
|
||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
|
|
||||||
printf("Loading Espresso %s...\n", espresso_kernel_version);
|
printf("Loading Espresso %s... ", kernel_version);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("[ DEBUG BUILD ]");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
terminal_setcolor(VGA_COLOR_RED);
|
terminal_setcolor(VGA_COLOR_RED);
|
||||||
|
|
||||||
@ -85,24 +97,20 @@ void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
|||||||
gdt_install(false);
|
gdt_install(false);
|
||||||
|
|
||||||
pic_remap();
|
pic_remap();
|
||||||
|
|
||||||
idt_init();
|
idt_init();
|
||||||
|
|
||||||
_sti_asm();
|
_sti_asm();
|
||||||
|
|
||||||
irq_init(); /* MUST be done after pic_remap() and idt_init() */
|
irq_init(); /* MUST be done after pic_remap() and idt_init() */
|
||||||
|
|
||||||
terminal_setcolor(VGA_COLOR_GREEN);
|
terminal_setcolor(VGA_COLOR_GREEN);
|
||||||
|
|
||||||
printd("Initializing physical memory manager...\n");
|
|
||||||
pmm_init(mbd);
|
pmm_init(mbd);
|
||||||
printd("Physical memory manager initialized\n");
|
|
||||||
|
|
||||||
printd("Initializing paging...\n");
|
|
||||||
paging_init();
|
paging_init();
|
||||||
printd("Paging initialized\n");
|
|
||||||
|
|
||||||
printd("Initializing heap allocator...\n");
|
heap_init(0xC2000000, 0x80000);
|
||||||
heap_init();
|
|
||||||
printd("Heap allocator initialized\n");
|
|
||||||
|
|
||||||
printd("Testing SSE...\n");
|
printd("Testing SSE...\n");
|
||||||
int32_t sse_test_result = test_sse();
|
int32_t sse_test_result = test_sse();
|
||||||
@ -115,31 +123,13 @@ void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
|||||||
printd("SSE test passed\n");
|
printd("SSE test passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printd("Initializing the PIT...\n");
|
|
||||||
pit_init();
|
pit_init();
|
||||||
printd("PIT initialized\n");
|
|
||||||
|
|
||||||
printd("Initializing the PS/2 keyboard...\n");
|
|
||||||
keyboard_init();
|
keyboard_init();
|
||||||
printd("PS/2 Keyboard initialized\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
printd("Initalizing AHCI...\n");
|
|
||||||
ahci_init();
|
|
||||||
printd("AHCI initialized\n");
|
|
||||||
*/
|
|
||||||
|
|
||||||
printd("Initializing IDE system...\n");
|
|
||||||
ide_initialize();
|
ide_initialize();
|
||||||
printd("IDE initialized\n");
|
|
||||||
|
|
||||||
/*printd("Initializing DuckFS...\n");
|
pci_init();
|
||||||
duckfs_init();
|
|
||||||
printd("DuckFS initialized\n");*/
|
|
||||||
|
|
||||||
printd("Initializing PCI...\n");
|
|
||||||
pci_enumerate();
|
|
||||||
printd("PCI initialized\n");
|
|
||||||
|
|
||||||
|
|
||||||
/* --- END INITIALIZATION SECTION --- */
|
/* --- END INITIALIZATION SECTION --- */
|
||||||
@ -148,22 +138,19 @@ void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
|||||||
|
|
||||||
|
|
||||||
/*pit_sleep(4000);
|
/*pit_sleep(4000);
|
||||||
begin_anim(espresso_kernel_version);*/
|
begin_anim(kernel_version);*/
|
||||||
|
|
||||||
printf("Guten tag and welcome to Espresso %s\n", espresso_kernel_version);
|
printf("Guten tag and welcome to Espresso %s\n", kernel_version);
|
||||||
|
|
||||||
printf("%s\n", espresso_str);
|
sleep(1000);
|
||||||
|
|
||||||
char buffer[512] = { 0 };
|
intro_begin();
|
||||||
|
|
||||||
int32_t i = sfs_read_file("test.txt", buffer, -1);
|
/*extern void terminal_clear(void);
|
||||||
|
|
||||||
printf("%i\n", i);
|
terminal_clear();
|
||||||
|
|
||||||
if (i == 0)
|
kshell_start(1, NULL);*/
|
||||||
{
|
|
||||||
printf("%s\n", buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|||||||
54
kernel/ksh_debug.c
Normal file
54
kernel/ksh_debug.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#include <kernel/ksh_debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print_all_regs(void)
|
||||||
|
{
|
||||||
|
uint32_t eax, ebx, ecx, edx, esi, edi, esp, ebp, eip;
|
||||||
|
uint16_t cs, ds, es, ss;
|
||||||
|
|
||||||
|
asm volatile ("mov %%eax, %0" : "=r"(eax));
|
||||||
|
asm volatile ("mov %%ebx, %0" : "=r"(ebx));
|
||||||
|
asm volatile ("mov %%ecx, %0" : "=r"(ecx));
|
||||||
|
asm volatile ("mov %%edx, %0" : "=r"(edx));
|
||||||
|
asm volatile ("mov %%esi, %0" : "=r"(esi));
|
||||||
|
asm volatile ("mov %%edi, %0" : "=r"(edi));
|
||||||
|
asm volatile ("mov %%esp, %0" : "=r"(esp));
|
||||||
|
asm volatile ("mov %%ebp, %0" : "=r"(ebp));
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
"call 1f\n"
|
||||||
|
"1: pop %0\n"
|
||||||
|
: "=r"(eip)
|
||||||
|
);
|
||||||
|
|
||||||
|
asm volatile ("mov %%cs, %0" : "=r"(cs));
|
||||||
|
asm volatile ("mov %%ds, %0" : "=r"(ds));
|
||||||
|
asm volatile ("mov %%es, %0" : "=r"(es));
|
||||||
|
asm volatile ("mov %%ss, %0" : "=r"(ss));
|
||||||
|
|
||||||
|
printf("EAX -> 0x%x EBX -> 0x%x ECX -> 0x%x EDX -> 0x%x\n", eax, ebx, ecx, edx);
|
||||||
|
printf("ESI -> 0x%x EDI -> 0x%x ESP -> 0x%x EBP -> 0x%x\n", esi, edi, esp, ebp);
|
||||||
|
printf("EIP (maybe) -> 0x%x\n", eip);
|
||||||
|
printf("CS -> 0x%04x DS -> 0x%04x ES -> 0x%04x SS -> 0x%04x\n", cs, ds, es, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_gprs(void)
|
||||||
|
{
|
||||||
|
uint32_t eax, ebx, ecx, edx, esi, edi, esp, ebp;
|
||||||
|
|
||||||
|
asm volatile ("mov %%eax, %0" : "=r"(eax));
|
||||||
|
asm volatile ("mov %%ebx, %0" : "=r"(ebx));
|
||||||
|
asm volatile ("mov %%ecx, %0" : "=r"(ecx));
|
||||||
|
asm volatile ("mov %%edx, %0" : "=r"(edx));
|
||||||
|
asm volatile ("mov %%esi, %0" : "=r"(esi));
|
||||||
|
asm volatile ("mov %%edi, %0" : "=r"(edi));
|
||||||
|
asm volatile ("mov %%esp, %0" : "=r"(esp));
|
||||||
|
asm volatile ("mov %%ebp, %0" : "=r"(ebp));
|
||||||
|
|
||||||
|
printf("EAX -> 0x%x EBX -> 0x%x ECX -> 0x%x EDX -> 0x%x\n", eax, ebx, ecx, edx);
|
||||||
|
printf("ESI -> 0x%x EDI -> 0x%x ESP -> 0x%x EBP -> 0x%x\n", esi, edi, esp, ebp);
|
||||||
|
}
|
||||||
287
kernel/kshell.c
Normal file
287
kernel/kshell.c
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <drivers/ps2_keyboard.h>
|
||||||
|
#include <tty.h>
|
||||||
|
#include <kernel/ksh_debug.h>
|
||||||
|
|
||||||
|
#include <kernel/kshell.h>
|
||||||
|
|
||||||
|
|
||||||
|
const char* shell_version = "0.0.2";
|
||||||
|
|
||||||
|
char* prompt = NULL;
|
||||||
|
int command = -1;
|
||||||
|
bool _debug = false;
|
||||||
|
|
||||||
|
int execute(void);
|
||||||
|
|
||||||
|
|
||||||
|
static void print_intro(void)
|
||||||
|
{
|
||||||
|
printf("Espresso kshell, ver %s on Espresso %s", shell_version, KERNEL_VERSION);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf(" DEBUG BUILD");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("\nSSE level: ");
|
||||||
|
|
||||||
|
command = 0;
|
||||||
|
|
||||||
|
execute();
|
||||||
|
|
||||||
|
extern char* get_cpu_vendor_string(void);
|
||||||
|
extern char* get_cpu_brand_string(void);
|
||||||
|
|
||||||
|
char* temp_ = get_cpu_vendor_string();
|
||||||
|
char* _temp = get_cpu_brand_string();
|
||||||
|
|
||||||
|
printf("CPU: %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");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_opts(int argc, char** argv)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[i], "--color") == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int kshell_start(int argc, char** argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
prompt = strdup(">");
|
||||||
|
|
||||||
|
char* i = NULL;
|
||||||
|
|
||||||
|
terminal_setcolor(VGA_COLOR_LIGHT_BLUE);
|
||||||
|
|
||||||
|
print_intro();
|
||||||
|
|
||||||
|
command = -1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
printf("%s ", prompt);
|
||||||
|
|
||||||
|
i = gets();
|
||||||
|
|
||||||
|
command = -1;
|
||||||
|
|
||||||
|
if (strcmp(i, "") == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strcmp(i, "exit") == 0 || strcmp(i, "quit") == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (strcmp(i, "sseinfo") == 0)
|
||||||
|
{
|
||||||
|
command = 0;
|
||||||
|
}
|
||||||
|
else if (strcmp(i, "kinfo") == 0)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (_debug)
|
||||||
|
{
|
||||||
|
printf(" ASCII -> ");
|
||||||
|
|
||||||
|
size_t len = strlen(i) + 1;
|
||||||
|
|
||||||
|
for (size_t n = 0; n < len; n++)
|
||||||
|
{
|
||||||
|
printf("%02X ", (int) i[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
execute();
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
free(i);
|
||||||
|
|
||||||
|
printf("Goodbye\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int execute(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case 0: {
|
||||||
|
extern int sse_initialized;
|
||||||
|
|
||||||
|
switch (sse_initialized)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
printf("No SSE support");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
printf("SSE1");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf("SSE2");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
printf("SSE3");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
printf("SSSE3");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
printf("SSE4.1");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
printf("SSE4.2");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("WARNING: sse_initialized is in a invalid state!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
printf("Espresso %s\n", KERNEL_VERSION);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
print_all_regs();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
print_gprs();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
extern uint8_t __kernel_start;
|
||||||
|
extern uint8_t __kernel_end;
|
||||||
|
size_t kernel_size = (size_t)&__kernel_end - (size_t)&__kernel_start;
|
||||||
|
|
||||||
|
printf("Kernel start: 0x%x\n", (&__kernel_start));
|
||||||
|
printf("Kernel end: 0x%x\n", (&__kernel_end));
|
||||||
|
printf("Kernel size (bytes): %llu\n", (uint64_t) kernel_size);
|
||||||
|
printf("Kernel size (kbytes): %llu\n", (((uint64_t) kernel_size) / 1000));
|
||||||
|
printf("Kernel size (mbytes): %f\n", (((uint64_t) kernel_size) / 1000.0) / 1000.0);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: {
|
||||||
|
extern uint8_t __kernel_text_start;
|
||||||
|
extern uint8_t __kernel_text_end;
|
||||||
|
extern uint8_t __kernel_rodata_start;
|
||||||
|
extern uint8_t __kernel_rodata_end;
|
||||||
|
extern uint8_t __kernel_data_start;
|
||||||
|
extern uint8_t __kernel_data_end;
|
||||||
|
extern uint8_t __bss_start;
|
||||||
|
extern uint8_t __bss_end;
|
||||||
|
|
||||||
|
printf(".text: %i\n.data: %i\n.rodata: %i\n.bss: %i\n", ((&__kernel_text_end) - (&__kernel_text_start)), ((&__kernel_data_end) - (&__kernel_data_start)),
|
||||||
|
((&__kernel_rodata_end) - (&__kernel_rodata_start)), ((&__bss_end) - (&__bss_start)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6: {
|
||||||
|
/*extern void terminal_clear(void);*/
|
||||||
|
|
||||||
|
terminal_clear();
|
||||||
|
|
||||||
|
printf("Printing ASCII chars 0x00 through 0xFE, hit enter to exit\n");
|
||||||
|
|
||||||
|
sleep(2500);
|
||||||
|
|
||||||
|
terminal_clear();
|
||||||
|
|
||||||
|
for (int i = 0x00; i < 0xFF; i++)
|
||||||
|
{
|
||||||
|
printf("%c", (char) i);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nCool ASCII art\n%c%c\n%c%c\n", 0xDA, 0xBF, 0xC0, 0xD9);
|
||||||
|
|
||||||
|
gets();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7: {
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
16
kernel/vars.c
Normal file
16
kernel/vars.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <types.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <kernel/vars.h>
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t* vars_start = NULL;
|
||||||
|
|
||||||
|
static int num_bytes_used = 0;
|
||||||
|
|
||||||
|
void init_vars(void)
|
||||||
|
{
|
||||||
|
vars_start = (uint8_t*) malloc(8 * 1024); /* 1 KiB */
|
||||||
|
memclr(vars_start, (size_t) 1024);
|
||||||
|
}
|
||||||
6
kincl.h
Normal file
6
kincl.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _KERNEL_INCLUDE_H
|
||||||
|
#define _KERNEL_INCLUDE_H
|
||||||
|
|
||||||
|
#define KERNEL_VERSION "0.0.2a"
|
||||||
|
|
||||||
|
#endif
|
||||||
124
lib/ksymtab.c
124
lib/ksymtab.c
@ -1,124 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <ksymtab.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define KFUNC_TABLE_ADDRESS 0xC0101000
|
|
||||||
|
|
||||||
#define KSYMTAB_MAX 0x8086FF
|
|
||||||
|
|
||||||
#define IS_MODULE_FUNC(id) ((id) & 0x80000000)
|
|
||||||
#define GET_MODULE_ID(id) (((id) >> 20) & 0x7FF)
|
|
||||||
#define GET_FUNC_ID(id) ((id) & 0xFFFFF)
|
|
||||||
#define EXISTS(id) ((id) > 0x0)
|
|
||||||
|
|
||||||
#define MAKE_KERNEL_FUNC(id) ((id) & 0x7FFFFFFF)
|
|
||||||
|
|
||||||
#define MAKE_MODULE_FUNC(mid, fid) (0x80000000 | ((mid) << 20) | ((fid) & 0xFFFFF))
|
|
||||||
|
|
||||||
kfunc_t* kfunc_table = (kfunc_t*)KFUNC_TABLE_ADDRESS;
|
|
||||||
|
|
||||||
static uint32_t ktab_size = 0;
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t kfunc_call(kfunc_t* func, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
|
||||||
{
|
|
||||||
uint32_t eax_ret, edx_ret;
|
|
||||||
|
|
||||||
asm volatile (
|
|
||||||
"push %[d]\n\t"
|
|
||||||
"push %[c]\n\t"
|
|
||||||
"push %[b]\n\t"
|
|
||||||
"push %[a]\n\t"
|
|
||||||
"call *%[fn]\n\t"
|
|
||||||
"add $16, %%esp\n\t" /* clean up stack (4 args * 4 bytes) */
|
|
||||||
: "=a"(eax_ret), "=d"(edx_ret)
|
|
||||||
: [a]"r"(a), [b]"r"(b), [c]"r"(c), [d]"r"(d), [fn]"r"(func->addr)
|
|
||||||
: "memory"
|
|
||||||
);
|
|
||||||
|
|
||||||
return ((uint64_t)edx_ret << 32) | eax_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t call_kfunc_by_id(uint32_t id, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < (int)ktab_size; i++)
|
|
||||||
{
|
|
||||||
if (kfunc_table[i].id == id)
|
|
||||||
{
|
|
||||||
if (kfunc_table[i].addr == 0x0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return kfunc_call(&kfunc_table[i], a, b, c, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t add_kfunc(void* addr, bool module, uint16_t module_id, uint32_t function_id)
|
|
||||||
{
|
|
||||||
if (ktab_size >= KSYMTAB_MAX)
|
|
||||||
{
|
|
||||||
return 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfunc_t kf = make_kfunc(addr, module, module_id, function_id);
|
|
||||||
kfunc_table[ktab_size] = kf;
|
|
||||||
|
|
||||||
ktab_size++;
|
|
||||||
|
|
||||||
return kf.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Constructs and returns a kfunc_t:
|
|
||||||
- 'addr' is the address of the function (can be NULL/0)
|
|
||||||
- 'module' indicates if it's a module/driver function
|
|
||||||
- 'module_id' is used only if 'module' is true (11 bits max)
|
|
||||||
- 'function_id':
|
|
||||||
- 20 bits if module is true
|
|
||||||
- 31 bits if kernel function
|
|
||||||
*/
|
|
||||||
kfunc_t make_kfunc(void* addr, bool module, uint16_t module_id, uint32_t function_id)
|
|
||||||
{
|
|
||||||
uint32_t id;
|
|
||||||
|
|
||||||
if (module)
|
|
||||||
{
|
|
||||||
id = 0x80000000 | ((module_id & 0x7FF) << 20) | (function_id & 0xFFFFF);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (function_id == UINT32_MAX)
|
|
||||||
{
|
|
||||||
function_id = ktab_size;
|
|
||||||
}
|
|
||||||
id = function_id & 0x7FFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfunc_t result = {
|
|
||||||
.id = id,
|
|
||||||
.addr = (uint32_t)(uintptr_t)addr
|
|
||||||
};
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfunc_t* find_kfunc(uint32_t id)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < ktab_size; i++)
|
|
||||||
{
|
|
||||||
if (kfunc_table[i].id == id)
|
|
||||||
{
|
|
||||||
return &kfunc_table[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
37
lib/math.c
Normal file
37
lib/math.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
static int ps_of_two[12] = { 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 };
|
||||||
|
|
||||||
|
bool is_low_power_of_two(int n)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 11; i++)
|
||||||
|
{
|
||||||
|
if (n == ps_of_two[i])
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t int_pow(uint64_t base, uint32_t exp)
|
||||||
|
{
|
||||||
|
uint64_t result = 1;
|
||||||
|
|
||||||
|
while (exp)
|
||||||
|
{
|
||||||
|
if (exp & 1)
|
||||||
|
{
|
||||||
|
result *= base;
|
||||||
|
}
|
||||||
|
|
||||||
|
exp >>= 1;
|
||||||
|
base *= base;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
186
lib/mm/heap.c
186
lib/mm/heap.c
@ -1,76 +1,138 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <mm/heap.h>
|
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <mm/paging.h>
|
#include <mm/paging.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <mm_macros.h>
|
||||||
|
|
||||||
|
#include <mm/heap.h>
|
||||||
|
|
||||||
#define ALIGNMENT 8
|
#define ALIGN4(x) (((x) + 3) & ~3)
|
||||||
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
|
#define MIN_BLOCK_SIZE 16
|
||||||
|
|
||||||
typedef struct block_header {
|
typedef struct block {
|
||||||
size_t size;
|
size_t size;
|
||||||
struct block_header* next;
|
struct block* next;
|
||||||
int free;
|
int free;
|
||||||
} block_header_t;
|
} block_t;
|
||||||
|
|
||||||
#define BLOCK_SIZE sizeof(block_header_t)
|
#define BLOCK_SIZE sizeof(block_t)
|
||||||
|
|
||||||
static uint8_t* heap_base = (uint8_t*)HEAP_START;
|
static uint8_t* heap_base;
|
||||||
static uint8_t* heap_end = (uint8_t*)(HEAP_START + HEAP_SIZE);
|
static uint8_t* heap_end;
|
||||||
|
static size_t heap_size;
|
||||||
|
static block_t* free_list;
|
||||||
|
|
||||||
static block_header_t* free_list = NULL;
|
void heap_init(uint32_t start, uint32_t size)
|
||||||
|
|
||||||
|
|
||||||
void heap_init(void)
|
|
||||||
{
|
{
|
||||||
free_list = (block_header_t*)heap_base;
|
#ifdef _DEBUG
|
||||||
free_list->size = HEAP_SIZE - BLOCK_SIZE;
|
printf("[ HEAP ] Initializing heap allocator...\n");
|
||||||
free_list->next = NULL;
|
#endif
|
||||||
|
|
||||||
|
heap_base = (uint8_t*) ALIGN4((uintptr_t) start);
|
||||||
|
heap_end = heap_base;
|
||||||
|
heap_size = size;
|
||||||
|
free_list = NULL;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < size; i += 0x1000)
|
||||||
|
{
|
||||||
|
map_page(pmm_alloc_page(), (void*)(start + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up initial free block */
|
||||||
|
free_list = (block_t*)heap_base;
|
||||||
|
free_list->size = heap_size - BLOCK_SIZE;
|
||||||
free_list->free = 1;
|
free_list->free = 1;
|
||||||
|
free_list->next = NULL;
|
||||||
|
|
||||||
|
heap_end = heap_base + size;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("[ HEAP ] Heap allocator initialized\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static block_t* find_free_block(size_t size)
|
||||||
void* malloc(size_t size)
|
|
||||||
{
|
{
|
||||||
size = ALIGN(size);
|
block_t* curr = free_list;
|
||||||
block_header_t* curr = free_list;
|
|
||||||
|
|
||||||
while (curr)
|
while (curr)
|
||||||
{
|
{
|
||||||
if (curr->free && curr->size >= size)
|
if (curr->free && curr->size >= size)
|
||||||
{
|
{
|
||||||
/* Split if there's space for another block */
|
return curr;
|
||||||
if (curr->size >= size + BLOCK_SIZE + ALIGNMENT)
|
|
||||||
{
|
|
||||||
block_header_t* new_block = (block_header_t*)((uint8_t*)curr + BLOCK_SIZE + size);
|
|
||||||
new_block->size = curr->size - size - BLOCK_SIZE;
|
|
||||||
new_block->next = curr->next;
|
|
||||||
new_block->free = 1;
|
|
||||||
|
|
||||||
curr->next = new_block;
|
|
||||||
curr->size = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curr->free = 0;
|
|
||||||
return (void*)((uint8_t*)curr + BLOCK_SIZE);
|
|
||||||
}
|
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
printd("Malloc failed due to lack of free memory\n");
|
printf("find_free_block(): No free block found!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void split_block(block_t* blk, size_t size)
|
||||||
|
{
|
||||||
|
if (blk->size >= size + BLOCK_SIZE + MIN_BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
block_t* new_blk = (block_t*)((uint8_t*)blk + BLOCK_SIZE + size);
|
||||||
|
new_blk->size = blk->size - size - BLOCK_SIZE;
|
||||||
|
new_blk->free = 1;
|
||||||
|
new_blk->next = blk->next;
|
||||||
|
blk->next = new_blk;
|
||||||
|
blk->size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* malloc(size_t size)
|
||||||
|
{
|
||||||
|
size = ALIGN4(size);
|
||||||
|
block_t* blk = find_free_block(size);
|
||||||
|
|
||||||
|
if (!blk)
|
||||||
|
{
|
||||||
|
printf("malloc(): No free block found!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
split_block(blk, size);
|
||||||
|
blk->free = 0;
|
||||||
|
return (void*)((uint8_t*)blk + BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void* ptr)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_t* blk = (block_t*)((uint8_t*)ptr - BLOCK_SIZE);
|
||||||
|
blk->free = 1;
|
||||||
|
|
||||||
|
/* coalesce */
|
||||||
|
block_t* curr = free_list;
|
||||||
|
while (curr && curr->next)
|
||||||
|
{
|
||||||
|
if (curr->free && curr->next->free)
|
||||||
|
{
|
||||||
|
curr->size += BLOCK_SIZE + curr->next->size;
|
||||||
|
curr->next = curr->next->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void* calloc(size_t nmemb, size_t size)
|
void* calloc(size_t nmemb, size_t size)
|
||||||
{
|
{
|
||||||
size_t total = nmemb * size;
|
size_t total = nmemb * size;
|
||||||
void* ptr = malloc(total);
|
void* ptr = malloc(total);
|
||||||
|
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
memset(ptr, 0, total);
|
MEMSET(ptr, 0, total);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,57 +143,25 @@ void* realloc(void* ptr, size_t size)
|
|||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0)
|
if (!size)
|
||||||
{
|
{
|
||||||
free(ptr);
|
free(ptr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
block_header_t* block = (block_header_t*)((uint8_t*)ptr - BLOCK_SIZE);
|
block_t* blk = (block_t*)((uint8_t*)ptr - BLOCK_SIZE);
|
||||||
if (block->size >= size)
|
if (blk->size >= size)
|
||||||
{
|
{
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* new_ptr = malloc(size);
|
void* new_ptr = malloc(size);
|
||||||
if (new_ptr) {
|
|
||||||
memcpy(new_ptr, ptr, block->size);
|
if (new_ptr)
|
||||||
|
{
|
||||||
|
memcpy(new_ptr, ptr, blk->size);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
return new_ptr;
|
return new_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(void* ptr)
|
|
||||||
{
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
block_header_t* block = (block_header_t*)((uint8_t*)ptr - BLOCK_SIZE);
|
|
||||||
block->free = 1;
|
|
||||||
|
|
||||||
/* Forward coalescing */
|
|
||||||
if (block->next && block->next->free)
|
|
||||||
{
|
|
||||||
block->size += BLOCK_SIZE + block->next->size;
|
|
||||||
block->next = block->next->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Backward coalescing */
|
|
||||||
block_header_t* prev = NULL;
|
|
||||||
block_header_t* curr = free_list;
|
|
||||||
|
|
||||||
while (curr && curr != block)
|
|
||||||
{
|
|
||||||
prev = curr;
|
|
||||||
curr = curr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev && prev->free)
|
|
||||||
{
|
|
||||||
prev->size += BLOCK_SIZE + block->size;
|
|
||||||
prev->next = block->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
108
lib/mm/paging.c
108
lib/mm/paging.c
@ -1,82 +1,60 @@
|
|||||||
|
#include <mm/pmm.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <mm_macros.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <mm/paging.h>
|
#include <mm/paging.h>
|
||||||
#include <mm/pmm.h>
|
|
||||||
#include <mm/heap.h>
|
|
||||||
|
|
||||||
#define PAGE_DIRECTORY_ENTRIES 1024
|
#define PAGE_PRESENT 0x1
|
||||||
#define PAGE_TABLE_ENTRIES 1024
|
#define PAGE_WRITE 0x2
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
typedef uint32_t page_directory_entry_t;
|
static uint32_t* page_directory;
|
||||||
typedef uint32_t page_table_entry_t;
|
|
||||||
|
|
||||||
static page_directory_entry_t* page_directory = NULL; /* Will be allocated */
|
|
||||||
static page_table_entry_t* page_tables[PAGE_DIRECTORY_ENTRIES];
|
|
||||||
|
|
||||||
extern void _enable_paging_asm(void);
|
|
||||||
|
|
||||||
void paging_init(void)
|
|
||||||
{
|
|
||||||
/* Allocate and clear the page directory */
|
|
||||||
page_directory = (page_directory_entry_t*)alloc_page();
|
|
||||||
memset(page_directory, 0, PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Allocate and set up the first identity-mapped page table (0-4MB) */
|
|
||||||
page_tables[0] = (page_table_entry_t*)alloc_page();
|
|
||||||
memset(page_tables[0], 0, PAGE_SIZE);
|
|
||||||
for (uint32_t i = 0; i < PAGE_TABLE_ENTRIES; i++)
|
|
||||||
{
|
|
||||||
page_tables[0][i] = (i * PAGE_SIZE) | 3; /* Present | RW */
|
|
||||||
}
|
|
||||||
page_directory[0] = ((uint32_t)page_tables[0]) | 3;
|
|
||||||
|
|
||||||
/* Allocate and clear the heap page table */
|
|
||||||
uint32_t heap_pd_index = HEAP_START >> 22; /* 0xC0000000 >> 22 = 768 */
|
|
||||||
page_tables[heap_pd_index] = (page_table_entry_t*)alloc_page();
|
|
||||||
memset(page_tables[heap_pd_index], 0, PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Map 4MB heap pages */
|
|
||||||
for (uint32_t i = 0; i < PAGE_TABLE_ENTRIES; i++) /* 1024 pages = 4MB */
|
|
||||||
{
|
|
||||||
void* phys = alloc_page();
|
|
||||||
if (phys == 0)
|
|
||||||
{
|
|
||||||
printf("Out of physical memory during heap mapping!\n");
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
page_tables[heap_pd_index][i] = ((uint32_t)phys & 0xFFFFF000) | 3; /* Present | RW */
|
|
||||||
}
|
|
||||||
page_directory[heap_pd_index] = ((uint32_t)page_tables[heap_pd_index]) | 3;
|
|
||||||
|
|
||||||
/* Load page directory */
|
|
||||||
asm volatile ("mov %0, %%cr3" : : "r"(page_directory));
|
|
||||||
|
|
||||||
/* Enable paging */
|
|
||||||
_enable_paging_asm();
|
|
||||||
}
|
|
||||||
|
|
||||||
void map_page(void* phys_addr, void* virt_addr)
|
void map_page(void* phys_addr, void* virt_addr)
|
||||||
{
|
{
|
||||||
uint32_t pd_index = ((uint32_t)virt_addr >> 22) & 0x3FF;
|
uint32_t pd_idx = ((uint32_t)virt_addr >> 22) & 0x3FF;
|
||||||
uint32_t pt_index = ((uint32_t)virt_addr >> 12) & 0x3FF;
|
uint32_t pt_idx = ((uint32_t)virt_addr >> 12) & 0x3FF;
|
||||||
|
|
||||||
/* Allocate page table if necessary */
|
uint32_t* page_table;
|
||||||
if (!(page_directory[pd_index] & 1))
|
|
||||||
|
if (!(page_directory[pd_idx] & PAGE_PRESENT))
|
||||||
{
|
{
|
||||||
void* pt_phys = alloc_page();
|
page_table = (uint32_t*) pmm_alloc_page();
|
||||||
page_tables[pd_index] = (page_table_entry_t*)((uint32_t)pt_phys + 0xC0000000); /* Map it higher */
|
MEMSET(page_table, 0, PAGE_SIZE);
|
||||||
|
page_directory[pd_idx] = ((uint32_t)page_table) | PAGE_PRESENT | PAGE_WRITE;
|
||||||
memset(page_tables[pd_index], 0, PAGE_SIZE);
|
}
|
||||||
|
else
|
||||||
page_directory[pd_index] = ((uint32_t)pt_phys) | 0x3; /* Present, R/W */
|
{
|
||||||
|
page_table = (uint32_t*)(page_directory[pd_idx] & ~0xFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
page_table_entry_t* page_table = (page_table_entry_t*)((page_directory[pd_index] & 0xFFFFF000) + 0xC0000000);
|
page_table[pt_idx] = ((uint32_t)phys_addr) | PAGE_PRESENT | PAGE_WRITE;
|
||||||
page_table[pt_index] = ((uint32_t)phys_addr & 0xFFFFF000) | 0x3; /* Present, R/W */
|
|
||||||
|
|
||||||
asm volatile ("invlpg (%0)" :: "r" (virt_addr) : "memory");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void paging_init(void)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("[ PAGING ] Initializing paging...\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
page_directory = (uint32_t*)pmm_alloc_page();
|
||||||
|
|
||||||
|
MEMSET(page_directory, 0, PAGE_SIZE);
|
||||||
|
|
||||||
|
for (uint32_t addr = 0; addr < 0x800000; addr += PAGE_SIZE)
|
||||||
|
{
|
||||||
|
map_page((void*) addr, (void*) addr); /* identity map first 8MB */
|
||||||
|
}
|
||||||
|
|
||||||
|
asm volatile("mov %0, %%cr3" :: "r"(page_directory));
|
||||||
|
uint32_t cr0;
|
||||||
|
asm volatile("mov %%cr0, %0" : "=r"(cr0));
|
||||||
|
cr0 |= 0x80000000;
|
||||||
|
asm volatile("mov %0, %%cr0" :: "r"(cr0));
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("[ PAGING ] Paging initialized\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
128
lib/mm/pmm.c
128
lib/mm/pmm.c
@ -1,80 +1,76 @@
|
|||||||
#include <stddef.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
|
||||||
#define BITMAP_SIZE (1024 * 1024) /* Supports up to 4GB RAM (1 bit per page) */
|
|
||||||
|
|
||||||
static uint8_t bitmap[BITMAP_SIZE / 8];
|
#define MAX_PAGES (1024 * 1024) /* 4GB / 4KB */
|
||||||
static uint32_t total_pages;
|
static uint8_t bitmap[MAX_PAGES / 8] __attribute__((section(".pmm_bitmap")));
|
||||||
static uint32_t used_pages = 0;
|
static size_t total_pages;
|
||||||
|
|
||||||
static inline void set_bit(uint32_t idx)
|
#define BITMAP_SET(i) (bitmap[(i) / 8] |= (1 << ((i) % 8)))
|
||||||
|
#define BITMAP_CLEAR(i) (bitmap[(i) / 8] &= ~(1 << ((i) % 8)))
|
||||||
|
#define BITMAP_TEST(i) (bitmap[(i) / 8] & (1 << ((i) % 8)))
|
||||||
|
|
||||||
|
void pmm_init(multiboot_info_t* mb)
|
||||||
{
|
{
|
||||||
bitmap[idx / 8] |= (1 << (idx % 8));
|
#ifdef _DEBUG
|
||||||
|
printf("[ PMM ] Initializing physical memory manager...\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
total_pages = MAX_PAGES;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < (total_pages / 8); i++)
|
||||||
|
{
|
||||||
|
bitmap[i] = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiboot_memory_map_t* mmap = (void*)(uintptr_t)mb->mmap_addr;
|
||||||
|
size_t entries = mb->mmap_length / sizeof(multiboot_memory_map_t);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < entries; i++)
|
||||||
|
{
|
||||||
|
if (mmap[i].type == 1) /* usable */
|
||||||
|
{
|
||||||
|
uint64_t start = mmap[i].addr;
|
||||||
|
uint64_t end = start + mmap[i].len;
|
||||||
|
for (uint64_t addr = start; addr < end; addr += 0x1000)
|
||||||
|
{
|
||||||
|
if (addr >= 0x100000) /* skip below 1MB */
|
||||||
|
{
|
||||||
|
size_t idx = addr / 0x1000;
|
||||||
|
BITMAP_CLEAR(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total_pages = MAX_PAGES;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("[ PMM ] Physical memory manager initialized\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void clear_bit(uint32_t idx)
|
void* pmm_alloc_page(void)
|
||||||
{
|
{
|
||||||
bitmap[idx / 8] &= ~(1 << (idx % 8));
|
for (uint32_t i = 0; i < total_pages; ++i)
|
||||||
|
{
|
||||||
|
if (!BITMAP_TEST(i))
|
||||||
|
{
|
||||||
|
BITMAP_SET(i);
|
||||||
|
return (void*)(i * 4096);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("pmm_alloc_page(): No free page found!\n");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int test_bit(uint32_t idx)
|
|
||||||
|
void pmm_free_page(void* addr)
|
||||||
{
|
{
|
||||||
return (bitmap[idx / 8] >> (idx % 8)) & 1;
|
size_t idx = (uintptr_t)addr / 0x1000;
|
||||||
}
|
BITMAP_CLEAR(idx);
|
||||||
|
|
||||||
void pmm_init(multiboot_info_t* mb_info)
|
|
||||||
{
|
|
||||||
total_pages = 0x100000; /* 4GB / 4KB = 1M pages */
|
|
||||||
for (uint32_t i = 0; i < total_pages / 8; i++)
|
|
||||||
{
|
|
||||||
bitmap[i] = 0xFF; /* Mark all as used */
|
|
||||||
}
|
|
||||||
|
|
||||||
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) mb_info->mmap_addr;
|
|
||||||
while ((uint32_t)mmap < mb_info->mmap_addr + mb_info->mmap_length)
|
|
||||||
{
|
|
||||||
if (mmap->type == 1) /* Usable */
|
|
||||||
{
|
|
||||||
uint64_t base = mmap->addr;
|
|
||||||
uint64_t len = mmap->len;
|
|
||||||
for (uint64_t addr = base; addr < base + len; addr += PAGE_SIZE)
|
|
||||||
{
|
|
||||||
if (addr >= 0x210000) /* Skip first 2.1MB, or ≈ 2.06MiB */
|
|
||||||
{
|
|
||||||
uint32_t idx = addr / PAGE_SIZE;
|
|
||||||
|
|
||||||
if (idx >= total_pages)
|
|
||||||
{
|
|
||||||
continue; /* skip entries above 4GB */
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_bit(idx);
|
|
||||||
used_pages--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mmap = (multiboot_memory_map_t*)((uint32_t)mmap + mmap->size + sizeof(mmap->size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* alloc_page(void) {
|
|
||||||
for (uint32_t i = 0; i < total_pages; i++)
|
|
||||||
{
|
|
||||||
if (!test_bit(i))
|
|
||||||
{
|
|
||||||
set_bit(i);
|
|
||||||
used_pages++;
|
|
||||||
return (void*)(i * PAGE_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL; /* Out of memory */
|
|
||||||
}
|
|
||||||
|
|
||||||
void free_page(void* ptr)
|
|
||||||
{
|
|
||||||
uint32_t idx = (uint32_t)ptr / PAGE_SIZE;
|
|
||||||
clear_bit(idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
265
lib/printf.c
265
lib/printf.c
@ -2,93 +2,160 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <drivers/serio.h>
|
||||||
|
|
||||||
#include <printf.h>
|
#include <printf.h>
|
||||||
|
|
||||||
|
static uint8_t color = 0xFF;
|
||||||
|
|
||||||
void printwc(const char* str, uint8_t color)
|
void printwc(const char* str, uint8_t color)
|
||||||
{
|
{
|
||||||
uint8_t c = terminal_getcolor();
|
uint8_t c = terminal_getcolor();
|
||||||
|
|
||||||
terminal_setcolor(color);
|
terminal_setcolor(color);
|
||||||
|
|
||||||
printf(str);
|
printf(str);
|
||||||
|
|
||||||
terminal_setcolor(c);
|
terminal_setcolor(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printd(const char* str)
|
void printd(const char* str)
|
||||||
{
|
{
|
||||||
terminal_debug_writestring(str);
|
terminal_debug_writestring(str);
|
||||||
|
|
||||||
|
serial_puts("[ DEBUG ] ");
|
||||||
|
serial_puts(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printdc(const char* str, uint8_t color)
|
void printdc(const char* str, uint8_t color)
|
||||||
{
|
{
|
||||||
uint8_t c = terminal_getcolor();
|
uint8_t c = terminal_getcolor();
|
||||||
terminal_setcolor(color);
|
terminal_setcolor(color);
|
||||||
|
|
||||||
printd(str);
|
printd(str);
|
||||||
|
|
||||||
terminal_setcolor(c);
|
terminal_setcolor(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printf_set_color(uint8_t _color)
|
||||||
|
{
|
||||||
|
if (_color == 0xFF)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
color = _color;
|
||||||
|
}
|
||||||
|
|
||||||
void printf(const char* format, ...)
|
void printf(const char* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
for (size_t i = 0; format[i] != '\0'; ++i) {
|
if (color != 0xFF)
|
||||||
if (format[i] == '%' && format[i + 1] != '\0') {
|
{
|
||||||
|
terminal_setcolor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; format[i] != '\0'; ++i)
|
||||||
|
{
|
||||||
|
if (format[i] == '%' && format[i + 1] != '\0')
|
||||||
|
{
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
// Check for width (like %016llx)
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
if (format[i] == '0') {
|
if (format[i] == '0')
|
||||||
|
{
|
||||||
++i;
|
++i;
|
||||||
while (format[i] >= '0' && format[i] <= '9') {
|
while (format[i] >= '0' && format[i] <= '9')
|
||||||
|
{
|
||||||
width = width * 10 + (format[i] - '0');
|
width = width * 10 + (format[i] - '0');
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for 'll' prefix
|
|
||||||
bool is_ll = false;
|
bool is_ll = false;
|
||||||
if (format[i] == 'l' && format[i + 1] == 'l') {
|
if (format[i] == 'l' && format[i + 1] == 'l')
|
||||||
|
{
|
||||||
is_ll = true;
|
is_ll = true;
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (format[i]) {
|
switch (format[i])
|
||||||
|
{
|
||||||
case 's': {
|
case 's': {
|
||||||
const char* str = va_arg(args, const char*);
|
const char* str = va_arg(args, const char*);
|
||||||
|
|
||||||
terminal_writestring(str ? str : "(null)");
|
terminal_writestring(str ? str : "(null)");
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_puts(str ? str : "(null)");
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'c': {
|
case 'c': {
|
||||||
char c = (char) va_arg(args, int);
|
char c = (char) va_arg(args, int);
|
||||||
terminal_putchar(c);
|
terminal_putchar(c);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write(c);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i': {
|
case 'i': {
|
||||||
|
if (is_ll)
|
||||||
|
{
|
||||||
|
int64_t val = va_arg(args, int64_t);
|
||||||
|
print_lint(val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
int32_t val = va_arg(args, int32_t);
|
int32_t val = va_arg(args, int32_t);
|
||||||
print_int(val);
|
print_int(val);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'u': {
|
case 'u': {
|
||||||
|
if (is_ll)
|
||||||
|
{
|
||||||
|
uint64_t val = va_arg(args, uint64_t);
|
||||||
|
print_luint(val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
uint32_t val = va_arg(args, uint32_t);
|
uint32_t val = va_arg(args, uint32_t);
|
||||||
print_uint(val);
|
print_uint(val);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'x': {
|
case 'x': {
|
||||||
if (is_ll) {
|
if (is_ll)
|
||||||
|
{
|
||||||
uint64_t val = va_arg(args, uint64_t);
|
uint64_t val = va_arg(args, uint64_t);
|
||||||
print_hex64(val, width ? width : 16, false);
|
print_hex64(val, width ? width : 16, false);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
uint32_t val = va_arg(args, uint32_t);
|
uint32_t val = va_arg(args, uint32_t);
|
||||||
print_hex(val, width ? width : 8, false);
|
print_hex(val, width ? width : 8, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'X': {
|
case 'X': {
|
||||||
if (is_ll) {
|
if (is_ll)
|
||||||
|
{
|
||||||
uint64_t val = va_arg(args, uint64_t);
|
uint64_t val = va_arg(args, uint64_t);
|
||||||
print_hex64(val, width ? width : 16, true);
|
print_hex64(val, width ? width : 16, true);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
uint32_t val = va_arg(args, uint32_t);
|
uint32_t val = va_arg(args, uint32_t);
|
||||||
print_hex(val, width ? width : 8, true);
|
print_hex(val, width ? width : 8, true);
|
||||||
}
|
}
|
||||||
@ -97,7 +164,15 @@ void printf(const char* format, ...)
|
|||||||
case 'p': {
|
case 'p': {
|
||||||
void* ptr = va_arg(args, void*);
|
void* ptr = va_arg(args, void*);
|
||||||
terminal_writestring("0x");
|
terminal_writestring("0x");
|
||||||
print_hex((uint32_t)(uintptr_t)ptr, 8, true); // assumes 32-bit pointer
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write('0');
|
||||||
|
serial_write('x');
|
||||||
|
}
|
||||||
|
|
||||||
|
print_hex((uint32_t)(uintptr_t)ptr, 8, true);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'f':
|
case 'f':
|
||||||
@ -108,16 +183,36 @@ void printf(const char* format, ...)
|
|||||||
}
|
}
|
||||||
case '%': {
|
case '%': {
|
||||||
terminal_putchar('%');
|
terminal_putchar('%');
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write('%');
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
terminal_putchar('%');
|
terminal_putchar('%');
|
||||||
terminal_putchar(format[i]);
|
terminal_putchar(format[i]);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write('%');
|
||||||
|
serial_write(format[i]);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
terminal_putchar(format[i]);
|
terminal_putchar(format[i]);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write(format[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,27 +220,81 @@ void printf(const char* format, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void print_int(int32_t value) {
|
void print_int(int32_t value)
|
||||||
char buffer[12]; // Enough for 32-bit signed int (-2147483648)
|
{
|
||||||
|
char buffer[12];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
uint32_t u;
|
uint32_t u;
|
||||||
|
|
||||||
if (value < 0) {
|
if (value < 0)
|
||||||
|
{
|
||||||
terminal_putchar('-');
|
terminal_putchar('-');
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write('-');
|
||||||
|
}
|
||||||
|
|
||||||
u = (uint32_t)(-value);
|
u = (uint32_t)(-value);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
u = (uint32_t)value;
|
u = (uint32_t)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to string in reverse
|
do
|
||||||
do {
|
{
|
||||||
buffer[i++] = '0' + (u % 10);
|
buffer[i++] = '0' + (u % 10);
|
||||||
u /= 10;
|
u /= 10;
|
||||||
} while (u > 0);
|
} while (u > 0);
|
||||||
|
|
||||||
// Print in correct order
|
while (i--)
|
||||||
while (i--) {
|
{
|
||||||
terminal_putchar(buffer[i]);
|
terminal_putchar(buffer[i]);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write(buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_lint(int64_t value)
|
||||||
|
{
|
||||||
|
char buffer[21];
|
||||||
|
int i = 0;
|
||||||
|
uint64_t u;
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
terminal_putchar('-');
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write('-');
|
||||||
|
}
|
||||||
|
|
||||||
|
u = (uint64_t) (-value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u = (uint64_t) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buffer[i++] = '0' + (u % 10);
|
||||||
|
u /= 10;
|
||||||
|
} while (u > 0);
|
||||||
|
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
terminal_putchar(buffer[i]);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write(buffer[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,13 +304,20 @@ void print_hex(uint32_t value, int width, bool uppercase)
|
|||||||
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--)
|
||||||
|
{
|
||||||
terminal_putchar(buffer[i]);
|
terminal_putchar(buffer[i]);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write(buffer[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,9 +333,15 @@ void print_double(double value, int precision)
|
|||||||
// Print the decimal point
|
// Print the decimal point
|
||||||
terminal_putchar('.');
|
terminal_putchar('.');
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write('.');
|
||||||
|
}
|
||||||
|
|
||||||
// Print the fractional part (scaled up)
|
// Print the fractional part (scaled up)
|
||||||
fractional_part *= 1;
|
fractional_part *= 1;
|
||||||
for (int i = 0; i < precision; i++) {
|
for (int i = 0; i < precision; i++)
|
||||||
|
{
|
||||||
fractional_part *= 10;
|
fractional_part *= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,34 +349,75 @@ void print_double(double value, int precision)
|
|||||||
print_int(frac_int);
|
print_int(frac_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_uint(uint32_t value) {
|
void print_uint(uint32_t value)
|
||||||
char buffer[11]; // Enough for 32-bit unsigned int
|
{
|
||||||
|
char buffer[11];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
buffer[i++] = '0' + (value % 10);
|
buffer[i++] = '0' + (value % 10);
|
||||||
value /= 10;
|
value /= 10;
|
||||||
} while (value > 0);
|
} while (value > 0);
|
||||||
|
|
||||||
while (i--) {
|
while (i--)
|
||||||
|
{
|
||||||
terminal_putchar(buffer[i]);
|
terminal_putchar(buffer[i]);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write(buffer[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_hex64(uint64_t value, int width, bool uppercase) {
|
void print_luint(uint64_t value)
|
||||||
|
{
|
||||||
|
char buffer[21];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buffer[i++] = '0' + (value % 10);
|
||||||
|
value /= 10;
|
||||||
|
} while (value > 0);
|
||||||
|
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
terminal_putchar(buffer[i]);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write(buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_hex64(uint64_t value, int width, bool uppercase)
|
||||||
|
{
|
||||||
char buffer[17] = {0};
|
char buffer[17] = {0};
|
||||||
const char* digits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
|
const char* digits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
buffer[i++] = digits[value % 16];
|
buffer[i++] = digits[value % 16];
|
||||||
value /= 16;
|
value /= 16;
|
||||||
} while (value > 0);
|
} while (value > 0);
|
||||||
|
|
||||||
while (i < width)
|
while (i < width)
|
||||||
|
{
|
||||||
buffer[i++] = '0';
|
buffer[i++] = '0';
|
||||||
|
}
|
||||||
|
|
||||||
while (i--)
|
while (i--)
|
||||||
|
{
|
||||||
terminal_putchar(buffer[i]);
|
terminal_putchar(buffer[i]);
|
||||||
|
|
||||||
|
if (use_serial())
|
||||||
|
{
|
||||||
|
serial_write(buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
lib/stdio.c
10
lib/stdio.c
@ -1,5 +1,6 @@
|
|||||||
#include <drivers/ps2_keyboard.h>
|
#include <drivers/ps2_keyboard.h>
|
||||||
#include <fs/vfs.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@ -25,6 +26,13 @@ char* getstring(void)
|
|||||||
return "HELLO\0";
|
return "HELLO\0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* gets(void)
|
||||||
|
{
|
||||||
|
return kbd_gets();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*char* fgets(char* buf, int n, FILE file)
|
/*char* fgets(char* buf, int n, FILE file)
|
||||||
{
|
{
|
||||||
if (!buf || n <= 1 || file < 1)
|
if (!buf || n <= 1 || file < 1)
|
||||||
|
|||||||
170
lib/string.c
170
lib/string.c
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
extern int32_t sse_initialized;
|
extern int32_t sse_initialized;
|
||||||
|
|
||||||
size_t strlen(const char* str)
|
size_t strlen(const char* str)
|
||||||
@ -184,22 +183,28 @@ char* strchr(const char* s, int c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void* memset(void *dst, char c, uint32_t n)
|
void* memset(void* dst, int c, size_t n)
|
||||||
{
|
{
|
||||||
char *temp = dst;
|
/*printf("memset(%p, %d, %u)\n", dst, c, n);*/
|
||||||
for (; n != 0; n--)
|
|
||||||
|
unsigned char* temp = (unsigned char*) dst;
|
||||||
|
unsigned char val = (unsigned char) c;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
*temp++ = c;
|
temp[i] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
@ -216,7 +221,7 @@ int32_t memcmp(const void *s1, const void *s2, size_t n)
|
|||||||
const uint8_t *p1 = (const uint8_t *)s1;
|
const uint8_t *p1 = (const uint8_t *)s1;
|
||||||
const uint8_t *p2 = (const uint8_t *)s2;
|
const uint8_t *p2 = (const uint8_t *)s2;
|
||||||
|
|
||||||
printf("p1: %i, p2: %i\n", (int32_t)*p1, (int32_t)*p2);
|
/*printf("p1: %i, p2: %i\n", (int32_t)*p1, (int32_t)*p2);*/
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++)
|
for (size_t i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
@ -239,6 +244,34 @@ void* memclr(void* m_start, size_t m_count)
|
|||||||
return memset(m_start, '\0', (uint32_t)m_count);
|
return memset(m_start, '\0', (uint32_t)m_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* memmove(void* dest, const void* src, size_t n)
|
||||||
|
{
|
||||||
|
unsigned char* d = (unsigned char*) dest;
|
||||||
|
const unsigned char* s = (const unsigned char*) src;
|
||||||
|
|
||||||
|
if (d == s || n == 0)
|
||||||
|
{
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d < s)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
d[i] = s[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t i = n; i > 0; i--)
|
||||||
|
{
|
||||||
|
d[i - 1] = s[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t isspace(char c)
|
int32_t isspace(char c)
|
||||||
{
|
{
|
||||||
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
|
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
|
||||||
@ -281,3 +314,124 @@ char tolower(char c)
|
|||||||
{
|
{
|
||||||
return lower(c);
|
return lower(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int isprint(int c)
|
||||||
|
{
|
||||||
|
return (c >= 32 && c < 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lowers(char* str)
|
||||||
|
{
|
||||||
|
size_t len = strlen(str);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
str[i] = lower(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uppers(char* str)
|
||||||
|
{
|
||||||
|
size_t len = strlen(str);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
str[i] = upper(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int atoi(const char *str)
|
||||||
|
{
|
||||||
|
int res = 0, sign = 1;
|
||||||
|
|
||||||
|
while (*str == ' ' || *str == '\t')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*str == '-')
|
||||||
|
{
|
||||||
|
sign = -1; str++;
|
||||||
|
}
|
||||||
|
else if (*str == '+')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*str >= '0' && *str <= '9')
|
||||||
|
{
|
||||||
|
res = res * 10 + (*str - '0');
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res * sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
long atol(const char *str)
|
||||||
|
{
|
||||||
|
long res = 0;
|
||||||
|
int sign = 1;
|
||||||
|
|
||||||
|
while (*str == ' ' || *str == '\t')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*str == '-')
|
||||||
|
{
|
||||||
|
sign = -1; str++;
|
||||||
|
}
|
||||||
|
else if (*str == '+')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*str >= '0' && *str <= '9')
|
||||||
|
{
|
||||||
|
res = res * 10 + (*str - '0');
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res * sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
double atof(const char *str)
|
||||||
|
{
|
||||||
|
double res = 0.0, frac = 0.0;
|
||||||
|
int sign = 1, frac_div = 1;
|
||||||
|
|
||||||
|
while (*str == ' ' || *str == '\t')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*str == '-')
|
||||||
|
{
|
||||||
|
sign = -1; str++;
|
||||||
|
}
|
||||||
|
else if (*str == '+')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*str >= '0' && *str <= '9')
|
||||||
|
{
|
||||||
|
res = res * 10 + (*str - '0');
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*str == '.')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
|
||||||
|
while (*str >= '0' && *str <= '9')
|
||||||
|
{
|
||||||
|
frac = frac * 10 + (*str - '0');
|
||||||
|
frac_div *= 10;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sign * (res + frac / frac_div);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
25
linker.ld
25
linker.ld
@ -19,32 +19,42 @@ SECTIONS
|
|||||||
chosen as a safer option than the traditional 1M. */
|
chosen as a safer option than the traditional 1M. */
|
||||||
. = 2M;
|
. = 2M;
|
||||||
|
|
||||||
|
__kernel_start = .;
|
||||||
|
|
||||||
/* First put the multiboot header, as it is required to be put very early
|
/* First put the multiboot header, as it is required to be put very early
|
||||||
in the image or the bootloader won't recognize the file format.
|
in the image or the bootloader won't recognize the file format.
|
||||||
Next we'll put the .text section. */
|
Next we'll put the .text section. */
|
||||||
.text BLOCK(4K) : ALIGN(4K)
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
|
__kernel_text_start = .;
|
||||||
KEEP(*(.multiboot))
|
KEEP(*(.multiboot))
|
||||||
*(.text)
|
*(.text)
|
||||||
|
__kernel_text_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read-only data. */
|
/* Read-only data. */
|
||||||
.rodata BLOCK(4K) : ALIGN(4K)
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
|
__kernel_rodata_start = .;
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
|
__kernel_rodata_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read-write data (initialized) */
|
/* Read-write data (initialized) */
|
||||||
.data BLOCK(4K) : ALIGN(4K)
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
|
__kernel_data_start = .;
|
||||||
*(.data)
|
*(.data)
|
||||||
|
__kernel_data_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read-write data (uninitialized) and stack */
|
/* Read-write data (uninitialized) */
|
||||||
.bss BLOCK(4K) : ALIGN(4K)
|
.bss BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
|
__bss_start = .;
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
*(.bss)
|
*(.bss)
|
||||||
|
__bss_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Include the list of initialization functions sorted. */
|
/* Include the list of initialization functions sorted. */
|
||||||
@ -65,7 +75,20 @@ SECTIONS
|
|||||||
crtn.o(.fini_array)
|
crtn.o(.fini_array)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pmm_bitmap (NOLOAD) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
KEEP(*(.pmm_bitmap))
|
||||||
|
}
|
||||||
|
|
||||||
|
.stack : ALIGN(16)
|
||||||
|
{
|
||||||
|
*(.stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The compiler may produce other sections, by default it will put them in
|
/* The compiler may produce other sections, by default it will put them in
|
||||||
a segment with the same name. Simply add stuff here as needed. */
|
a segment with the same name. Simply add stuff here as needed. */
|
||||||
|
|
||||||
|
__kernel_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
serial.log
Normal file
5
serial.log
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
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