Espresso 0.0.2a

This commit is contained in:
2025-10-20 21:57:30 -05:00
parent 102d517097
commit ff6cba1164
59 changed files with 29272 additions and 773 deletions

View File

@ -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
View 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;
}

View File

@ -1,76 +1,138 @@
#include <stdio.h>
#include <string.h>
#include <mm/heap.h>
#include <mm/pmm.h>
#include <mm/paging.h>
#include <string.h>
#include <stdio.h>
#include <mm_macros.h>
#include <mm/heap.h>
#define ALIGNMENT 8
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
#define ALIGN4(x) (((x) + 3) & ~3)
#define MIN_BLOCK_SIZE 16
typedef struct block_header {
typedef struct block {
size_t size;
struct block_header* next;
struct block* next;
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_end = (uint8_t*)(HEAP_START + HEAP_SIZE);
static uint8_t* heap_base;
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(void)
void heap_init(uint32_t start, uint32_t size)
{
free_list = (block_header_t*)heap_base;
free_list->size = HEAP_SIZE - BLOCK_SIZE;
free_list->next = NULL;
#ifdef _DEBUG
printf("[ HEAP ] Initializing heap allocator...\n");
#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->next = NULL;
heap_end = heap_base + size;
#ifdef _DEBUG
printf("[ HEAP ] Heap allocator initialized\n");
#endif
}
void* malloc(size_t size)
static block_t* find_free_block(size_t size)
{
size = ALIGN(size);
block_header_t* curr = free_list;
block_t* curr = free_list;
while (curr)
{
if (curr->free && curr->size >= size)
{
/* Split if there's space for another block */
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);
return curr;
}
curr = curr->next;
}
printd("Malloc failed due to lack of free memory\n");
printf("find_free_block(): No free block found!\n");
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)
{
size_t total = nmemb * size;
void* ptr = malloc(total);
if (ptr)
{
memset(ptr, 0, total);
MEMSET(ptr, 0, total);
}
return ptr;
}
@ -81,57 +143,25 @@ void* realloc(void* ptr, size_t size)
return malloc(size);
}
if (size == 0)
if (!size)
{
free(ptr);
return NULL;
}
block_header_t* block = (block_header_t*)((uint8_t*)ptr - BLOCK_SIZE);
if (block->size >= size)
block_t* blk = (block_t*)((uint8_t*)ptr - BLOCK_SIZE);
if (blk->size >= size)
{
return ptr;
}
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);
}
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;
}
}

View File

@ -1,82 +1,60 @@
#include <mm/pmm.h>
#include <string.h>
#include <mm_macros.h>
#include <stdio.h>
#include <mm/paging.h>
#include <mm/pmm.h>
#include <mm/heap.h>
#define PAGE_DIRECTORY_ENTRIES 1024
#define PAGE_TABLE_ENTRIES 1024
#define PAGE_SIZE 4096
#define PAGE_PRESENT 0x1
#define PAGE_WRITE 0x2
#define PAGE_SIZE 4096
typedef uint32_t page_directory_entry_t;
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();
}
static uint32_t* page_directory;
void map_page(void* phys_addr, void* virt_addr)
{
uint32_t pd_index = ((uint32_t)virt_addr >> 22) & 0x3FF;
uint32_t pt_index = ((uint32_t)virt_addr >> 12) & 0x3FF;
uint32_t pd_idx = ((uint32_t)virt_addr >> 22) & 0x3FF;
uint32_t pt_idx = ((uint32_t)virt_addr >> 12) & 0x3FF;
/* Allocate page table if necessary */
if (!(page_directory[pd_index] & 1))
uint32_t* page_table;
if (!(page_directory[pd_idx] & PAGE_PRESENT))
{
void* pt_phys = alloc_page();
page_tables[pd_index] = (page_table_entry_t*)((uint32_t)pt_phys + 0xC0000000); /* Map it higher */
memset(page_tables[pd_index], 0, PAGE_SIZE);
page_directory[pd_index] = ((uint32_t)pt_phys) | 0x3; /* Present, R/W */
page_table = (uint32_t*) pmm_alloc_page();
MEMSET(page_table, 0, PAGE_SIZE);
page_directory[pd_idx] = ((uint32_t)page_table) | PAGE_PRESENT | PAGE_WRITE;
}
else
{
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_index] = ((uint32_t)phys_addr & 0xFFFFF000) | 0x3; /* Present, R/W */
asm volatile ("invlpg (%0)" :: "r" (virt_addr) : "memory");
page_table[pt_idx] = ((uint32_t)phys_addr) | PAGE_PRESENT | PAGE_WRITE;
}
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
}

View File

@ -1,80 +1,76 @@
#include <stddef.h>
#include <string.h>
#include <stdio.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];
static uint32_t total_pages;
static uint32_t used_pages = 0;
#define MAX_PAGES (1024 * 1024) /* 4GB / 4KB */
static uint8_t bitmap[MAX_PAGES / 8] __attribute__((section(".pmm_bitmap")));
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
static inline void clear_bit(uint32_t idx)
{
bitmap[idx / 8] &= ~(1 << (idx % 8));
}
static inline int test_bit(uint32_t idx)
{
return (bitmap[idx / 8] >> (idx % 8)) & 1;
}
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++)
total_pages = MAX_PAGES;
for (uint32_t i = 0; i < (total_pages / 8); i++)
{
bitmap[i] = 0xFF; /* Mark all as used */
bitmap[i] = 0xFF;
}
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)
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->type == 1) /* Usable */
if (mmap[i].type == 1) /* usable */
{
uint64_t base = mmap->addr;
uint64_t len = mmap->len;
for (uint64_t addr = base; addr < base + len; addr += PAGE_SIZE)
uint64_t start = mmap[i].addr;
uint64_t end = start + mmap[i].len;
for (uint64_t addr = start; addr < end; addr += 0x1000)
{
if (addr >= 0x210000) /* Skip first 2.1MB, or ≈ 2.06MiB */
if (addr >= 0x100000) /* skip below 1MB */
{
uint32_t idx = addr / PAGE_SIZE;
if (idx >= total_pages)
{
continue; /* skip entries above 4GB */
}
clear_bit(idx);
used_pages--;
size_t idx = addr / 0x1000;
BITMAP_CLEAR(idx);
}
}
}
mmap = (multiboot_memory_map_t*)((uint32_t)mmap + mmap->size + sizeof(mmap->size));
}
total_pages = MAX_PAGES;
#ifdef _DEBUG
printf("[ PMM ] Physical memory manager initialized\n");
#endif
}
void* alloc_page(void) {
for (uint32_t i = 0; i < total_pages; i++)
void* pmm_alloc_page(void)
{
for (uint32_t i = 0; i < total_pages; ++i)
{
if (!test_bit(i))
if (!BITMAP_TEST(i))
{
set_bit(i);
used_pages++;
return (void*)(i * PAGE_SIZE);
BITMAP_SET(i);
return (void*)(i * 4096);
}
}
return NULL; /* Out of memory */
printf("pmm_alloc_page(): No free page found!\n");
return NULL;
}
void free_page(void* ptr)
void pmm_free_page(void* addr)
{
uint32_t idx = (uint32_t)ptr / PAGE_SIZE;
clear_bit(idx);
size_t idx = (uintptr_t)addr / 0x1000;
BITMAP_CLEAR(idx);
}

View File

@ -2,219 +2,422 @@
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <drivers/serio.h>
#include <printf.h>
static uint8_t color = 0xFF;
void printwc(const char* str, uint8_t color)
{
uint8_t c = terminal_getcolor();
terminal_setcolor(color);
printf(str);
terminal_setcolor(c);
}
void printd(const char* str)
{
terminal_debug_writestring(str);
serial_puts("[ DEBUG ] ");
serial_puts(str);
}
void printdc(const char* str, uint8_t color)
{
uint8_t c = terminal_getcolor();
terminal_setcolor(color);
printd(str);
terminal_setcolor(c);
}
void printf_set_color(uint8_t _color)
{
if (_color == 0xFF)
{
return;
}
color = _color;
}
void printf(const char* format, ...)
{
va_list args;
va_start(args, format);
va_list args;
va_start(args, format);
if (color != 0xFF)
{
terminal_setcolor(color);
}
for (size_t i = 0; format[i] != '\0'; ++i) {
if (format[i] == '%' && format[i + 1] != '\0') {
++i;
for (size_t i = 0; format[i] != '\0'; ++i)
{
if (format[i] == '%' && format[i + 1] != '\0')
{
++i;
// Check for width (like %016llx)
int width = 0;
if (format[i] == '0') {
++i;
while (format[i] >= '0' && format[i] <= '9') {
width = width * 10 + (format[i] - '0');
++i;
}
}
// Check for 'll' prefix
bool is_ll = false;
if (format[i] == 'l' && format[i + 1] == 'l') {
is_ll = true;
i += 2;
}
switch (format[i]) {
case 's': {
const char* str = va_arg(args, const char*);
terminal_writestring(str ? str : "(null)");
break;
}
case 'c': {
char c = (char) va_arg(args, int);
terminal_putchar(c);
break;
}
case 'd':
case 'i': {
int32_t val = va_arg(args, int32_t);
print_int(val);
break;
}
case 'u': {
uint32_t val = va_arg(args, uint32_t);
print_uint(val);
break;
}
case 'x': {
if (is_ll) {
uint64_t val = va_arg(args, uint64_t);
print_hex64(val, width ? width : 16, false);
} else {
uint32_t val = va_arg(args, uint32_t);
print_hex(val, width ? width : 8, false);
}
break;
}
case 'X': {
if (is_ll) {
uint64_t val = va_arg(args, uint64_t);
print_hex64(val, width ? width : 16, true);
} else {
uint32_t val = va_arg(args, uint32_t);
print_hex(val, width ? width : 8, true);
}
break;
}
case 'p': {
void* ptr = va_arg(args, void*);
terminal_writestring("0x");
print_hex((uint32_t)(uintptr_t)ptr, 8, true); // assumes 32-bit pointer
break;
}
case 'f':
case 'F': {
double val = va_arg(args, double);
print_double(val, 2);
break;
}
case '%': {
terminal_putchar('%');
break;
}
default: {
terminal_putchar('%');
terminal_putchar(format[i]);
break;
}
}
} else {
terminal_putchar(format[i]);
int width = 0;
if (format[i] == '0')
{
++i;
while (format[i] >= '0' && format[i] <= '9')
{
width = width * 10 + (format[i] - '0');
++i;
}
}
}
va_end(args);
bool is_ll = false;
if (format[i] == 'l' && format[i + 1] == 'l')
{
is_ll = true;
i += 2;
}
switch (format[i])
{
case 's': {
const char* str = va_arg(args, const char*);
terminal_writestring(str ? str : "(null)");
if (use_serial())
{
serial_puts(str ? str : "(null)");
}
break;
}
case 'c': {
char c = (char) va_arg(args, int);
terminal_putchar(c);
if (use_serial())
{
serial_write(c);
}
break;
}
case 'd':
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);
print_int(val);
}
break;
}
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);
print_uint(val);
}
break;
}
case 'x': {
if (is_ll)
{
uint64_t val = va_arg(args, uint64_t);
print_hex64(val, width ? width : 16, false);
}
else
{
uint32_t val = va_arg(args, uint32_t);
print_hex(val, width ? width : 8, false);
}
break;
}
case 'X': {
if (is_ll)
{
uint64_t val = va_arg(args, uint64_t);
print_hex64(val, width ? width : 16, true);
}
else
{
uint32_t val = va_arg(args, uint32_t);
print_hex(val, width ? width : 8, true);
}
break;
}
case 'p': {
void* ptr = va_arg(args, void*);
terminal_writestring("0x");
if (use_serial())
{
serial_write('0');
serial_write('x');
}
print_hex((uint32_t)(uintptr_t)ptr, 8, true);
break;
}
case 'f':
case 'F': {
double val = va_arg(args, double);
print_double(val, 2);
break;
}
case '%': {
terminal_putchar('%');
if (use_serial())
{
serial_write('%');
}
break;
}
default: {
terminal_putchar('%');
terminal_putchar(format[i]);
if (use_serial())
{
serial_write('%');
serial_write(format[i]);
}
break;
}
}
}
else
{
terminal_putchar(format[i]);
if (use_serial())
{
serial_write(format[i]);
}
}
}
va_end(args);
}
void print_int(int32_t value) {
char buffer[12]; // Enough for 32-bit signed int (-2147483648)
int i = 0;
uint32_t u;
void print_int(int32_t value)
{
char buffer[12];
int i = 0;
uint32_t u;
if (value < 0) {
terminal_putchar('-');
u = (uint32_t)(-value);
} else {
u = (uint32_t)value;
if (value < 0)
{
terminal_putchar('-');
if (use_serial())
{
serial_write('-');
}
u = (uint32_t)(-value);
}
else
{
u = (uint32_t)value;
}
// Convert to string in reverse
do {
buffer[i++] = '0' + (u % 10);
u /= 10;
} while (u > 0);
do
{
buffer[i++] = '0' + (u % 10);
u /= 10;
} while (u > 0);
// Print in correct order
while (i--) {
terminal_putchar(buffer[i]);
while (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]);
}
}
}
void print_hex(uint32_t value, int width, bool uppercase)
{
const char* hex_chars = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
char buffer[9]; // 8 hex digits max for 32-bit
int i = 0;
const char* hex_chars = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
char buffer[9]; // 8 hex digits max for 32-bit
int i = 0;
do {
buffer[i++] = hex_chars[value & 0xF];
value >>= 4;
} while (value || i < width); // ensure at least 'width' digits
do
{
buffer[i++] = hex_chars[value & 0xF];
value >>= 4;
} while (value || i < width); // ensure at least 'width' digits
while (i--) {
terminal_putchar(buffer[i]);
while (i--)
{
terminal_putchar(buffer[i]);
if (use_serial())
{
serial_write(buffer[i]);
}
}
}
void print_double(double value, int precision)
{
// Handle the integer part
int32_t integer_part = (int32_t)value;
double fractional_part = value - integer_part;
// Handle the integer part
int32_t integer_part = (int32_t)value;
double fractional_part = value - integer_part;
// Print the integer part
print_int(integer_part);
// Print the integer part
print_int(integer_part);
// Print the decimal point
terminal_putchar('.');
// Print the decimal point
terminal_putchar('.');
if (use_serial())
{
serial_write('.');
}
// Print the fractional part (scaled up)
fractional_part *= 1;
for (int i = 0; i < precision; i++) {
fractional_part *= 10;
// Print the fractional part (scaled up)
fractional_part *= 1;
for (int i = 0; i < precision; i++)
{
fractional_part *= 10;
}
int32_t frac_int = (int32_t)fractional_part;
print_int(frac_int);
}
void print_uint(uint32_t value)
{
char buffer[11];
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]);
}
int32_t frac_int = (int32_t)fractional_part;
print_int(frac_int);
}
}
void print_uint(uint32_t value) {
char buffer[11]; // Enough for 32-bit unsigned int
int i = 0;
void print_luint(uint64_t value)
{
char buffer[21];
int i = 0;
do {
buffer[i++] = '0' + (value % 10);
value /= 10;
} while (value > 0);
do
{
buffer[i++] = '0' + (value % 10);
value /= 10;
} while (value > 0);
while (i--) {
terminal_putchar(buffer[i]);
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};
const char* digits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
int i = 0;
void print_hex64(uint64_t value, int width, bool uppercase)
{
char buffer[17] = {0};
const char* digits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
int i = 0;
do {
buffer[i++] = digits[value % 16];
value /= 16;
} while (value > 0);
do
{
buffer[i++] = digits[value % 16];
value /= 16;
} while (value > 0);
while (i < width)
buffer[i++] = '0';
while (i < width)
{
buffer[i++] = '0';
}
while (i--)
terminal_putchar(buffer[i]);
while (i--)
{
terminal_putchar(buffer[i]);
if (use_serial())
{
serial_write(buffer[i]);
}
}
}

View File

@ -1,5 +1,6 @@
#include <drivers/ps2_keyboard.h>
#include <fs/vfs.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -25,6 +26,13 @@ char* getstring(void)
return "HELLO\0";
}
char* gets(void)
{
return kbd_gets();
}
/*char* fgets(char* buf, int n, FILE file)
{
if (!buf || n <= 1 || file < 1)

View File

@ -4,7 +4,6 @@
#include <string.h>
extern int32_t sse_initialized;
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;
for (; n != 0; n--)
/*printf("memset(%p, %d, %u)\n", dst, c, 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;
}
void* memcpy(void *dst, const void *src, uint32_t n)
{
if (sse_initialized > 1)
/*if (sse_initialized > 1)
{
return sse2_memcpy(dst, src, n);
}
}*/
char *d = dst;
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 *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++)
{
@ -239,6 +244,34 @@ void* memclr(void* m_start, size_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)
{
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
@ -281,3 +314,124 @@ char tolower(char 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);
}