Compare commits
18 commits
master
...
memory_all
Author | SHA1 | Date | |
---|---|---|---|
|
fe30349d17 | ||
|
256efe6b22 | ||
|
5b8f5cac54 | ||
|
8ae1816819 | ||
|
a537ac162e | ||
|
3af5ab06a7 | ||
|
c66bb87aaf | ||
|
200e58b6f6 | ||
|
9589e2f804 | ||
|
5e1a12239a | ||
|
5c8f8defe0 | ||
|
831b49d8dd | ||
|
2064d1a802 | ||
|
d547432270 | ||
|
a042169845 | ||
|
4f214b2d5a | ||
|
fafe06ed2b | ||
|
ea9f4c6e49 |
8 changed files with 487 additions and 97 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1 +1,5 @@
|
||||||
target/
|
target/
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
CMakeLists.txt
|
||||||
|
cmake-build-debug/
|
||||||
|
|
|
@ -37,7 +37,7 @@ The kernel is based on [the bare bones kernel from the OSDev wiki](https://wiki.
|
||||||
- [ ] Write files in directory
|
- [ ] Write files in directory
|
||||||
- [ ] Tests
|
- [ ] Tests
|
||||||
- [ ] Running executables from filesystem
|
- [ ] Running executables from filesystem
|
||||||
- [ ] Better memory management
|
- [x] Better memory management
|
||||||
- [ ] Better shell
|
- [ ] Better shell
|
||||||
|
|
||||||
As a test, I've implemented day 1 of [advent of code](https://adventofcode.com/) on the [AoC branch](https://github.com/Robbe7730/RoBoot/tree/AoC).
|
As a test, I've implemented day 1 of [advent of code](https://adventofcode.com/) on the [AoC branch](https://github.com/Robbe7730/RoBoot/tree/AoC).
|
||||||
|
|
|
@ -290,7 +290,7 @@ repnz movsd
|
||||||
or ax, ax
|
or ax, ax
|
||||||
jnz .elf_ph_loop
|
jnz .elf_ph_loop
|
||||||
|
|
||||||
.start_kernel
|
.start_kernel:
|
||||||
|
|
||||||
cmp edi, KERNEL_START
|
cmp edi, KERNEL_START
|
||||||
je .invalid_elf
|
je .invalid_elf
|
||||||
|
|
|
@ -16,52 +16,67 @@
|
||||||
#include "memory.c"
|
#include "memory.c"
|
||||||
#include "interrupts.c"
|
#include "interrupts.c"
|
||||||
#include "shell.c"
|
#include "shell.c"
|
||||||
|
#include "util/printer.c"
|
||||||
|
|
||||||
static inline bool are_interrupts_enabled() {
|
static inline bool are_interrupts_enabled() {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
asm volatile ( "pushf\n\t"
|
asm volatile ( "pushf\n\t"
|
||||||
"pop %0"
|
"pop %0"
|
||||||
: "=g"(flags) );
|
: "=g"(flags));
|
||||||
return flags & (1 << 9);
|
return flags & (1 << 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kernel_main(void)
|
void kernel_main(void) {
|
||||||
{
|
/* Initialize terminal interface */
|
||||||
/* Initialize terminal interface */
|
terminal_initialize();
|
||||||
terminal_initialize();
|
|
||||||
|
|
||||||
terminal_putchar('H');
|
terminal_putchar('H');
|
||||||
terminal_putchar('e');
|
terminal_putchar('e');
|
||||||
terminal_putchar('l');
|
terminal_putchar('l');
|
||||||
terminal_putchar('l');
|
terminal_putchar('l');
|
||||||
terminal_putchar('o');
|
terminal_putchar('o');
|
||||||
|
|
||||||
terminal_setcolor(vga_entry_color(VGA_COLOR_GREEN, VGA_COLOR_BLACK));
|
terminal_setcolor(vga_entry_color(VGA_COLOR_GREEN, VGA_COLOR_BLACK));
|
||||||
terminal_writestring(" kernel");
|
print(" kernel");
|
||||||
terminal_setcolor(vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK));
|
terminal_setcolor(vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK));
|
||||||
terminal_writestring(" World!\n");
|
print(" World!\n");
|
||||||
terminal_writestring("Newlines!\n");
|
print("Newlines!\n");
|
||||||
|
|
||||||
char* memory_str = alloc(sizeof(char) * 7);
|
char *memory_str = alloc(sizeof(char) * 7);
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
memory_str[i] = "Memory"[i];
|
memory_str[i] = "Memory"[i];
|
||||||
}
|
}
|
||||||
memory_str[6] = 0;
|
memory_str[6] = 0;
|
||||||
|
|
||||||
char* management_str = alloc(sizeof(char) * 13);
|
char *management_str = alloc(sizeof(char) * 13);
|
||||||
for (int i = 0; i < 13; i++) {
|
for (int i = 0; i < 13; i++) {
|
||||||
management_str[i] = " management!\n"[i];
|
management_str[i] = " management!\n"[i];
|
||||||
}
|
}
|
||||||
management_str[13] = 0;
|
management_str[13] = 0;
|
||||||
|
|
||||||
terminal_writestring(memory_str);
|
print(memory_str);
|
||||||
terminal_writestring(management_str);
|
print(management_str);
|
||||||
|
|
||||||
terminal_writestring((are_interrupts_enabled())? "Interrupts!\n": "No interrupts :(\n");
|
free(memory_str);
|
||||||
|
free(management_str);
|
||||||
|
|
||||||
interrupt_init();
|
// Some dummy allocations to demonstrate the states of memory and to showcase the memory dump printout.
|
||||||
|
void* ptr = alloc(30);
|
||||||
|
alloc(30);
|
||||||
|
alloc(31);
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
for(;;) {
|
void* ptr2 = alloc(64);
|
||||||
shell_step();
|
alloc(61);
|
||||||
}
|
free(ptr2);
|
||||||
|
|
||||||
|
print((are_interrupts_enabled()) ? "Interrupts!\n" : "No interrupts :(\n");
|
||||||
|
|
||||||
|
interrupt_init();
|
||||||
|
|
||||||
|
print_memory();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
shell_step();
|
||||||
|
}
|
||||||
}
|
}
|
205
kernel/memory.c
205
kernel/memory.c
|
@ -1,13 +1,208 @@
|
||||||
#ifndef MEMORY_C
|
#ifndef MEMORY_C
|
||||||
#define MEMORY_C
|
#define MEMORY_C
|
||||||
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
void* _curr_end = (void*) 0x200000;
|
#include "terminal.c"
|
||||||
|
#include "util/printer.c"
|
||||||
|
|
||||||
void* alloc(size_t size) {
|
#define MEMORY_START 0x200000
|
||||||
void* thanks_jp = _curr_end;
|
//#define MEMORY_END 0x300000
|
||||||
_curr_end += size;
|
|
||||||
return thanks_jp;
|
#define PAGE_ALIGNMENT 4
|
||||||
|
|
||||||
|
//size_t total_memory = MEMORY_END - MEMORY_START;
|
||||||
|
|
||||||
|
typedef struct page_tag {
|
||||||
|
size_t size;
|
||||||
|
size_t realsize;
|
||||||
|
|
||||||
|
struct page_tag *prev;
|
||||||
|
struct page_tag *next;
|
||||||
|
} page_tag;
|
||||||
|
|
||||||
|
|
||||||
|
page_tag *start = (void *) MEMORY_START;;
|
||||||
|
|
||||||
|
size_t calculate_realsize(size_t size) {
|
||||||
|
if (size % PAGE_ALIGNMENT == 0) return size;
|
||||||
|
return size + PAGE_ALIGNMENT - (size % PAGE_ALIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *alloc(size_t size) {
|
||||||
|
page_tag *curr_page = start;
|
||||||
|
|
||||||
|
while (curr_page->next != NULL) {
|
||||||
|
page_tag *new_page = ((void *) curr_page) + sizeof(page_tag) + curr_page->realsize;
|
||||||
|
size_t realsize = calculate_realsize(size);
|
||||||
|
if ((void *) new_page + sizeof(page_tag) + realsize <= (void *) curr_page->next) {
|
||||||
|
|
||||||
|
new_page->size = size;
|
||||||
|
new_page->realsize = realsize;
|
||||||
|
|
||||||
|
curr_page->next->prev = new_page;
|
||||||
|
new_page->next = curr_page->next;
|
||||||
|
|
||||||
|
curr_page->next = new_page;
|
||||||
|
new_page->prev = curr_page;
|
||||||
|
|
||||||
|
return new_page + 1;
|
||||||
|
}
|
||||||
|
curr_page = curr_page->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
page_tag *new_page = ((void *) curr_page) + sizeof(page_tag) + curr_page->realsize;
|
||||||
|
new_page->size = size;
|
||||||
|
new_page->realsize = calculate_realsize(size);
|
||||||
|
|
||||||
|
curr_page->next = new_page;
|
||||||
|
new_page->prev = curr_page;
|
||||||
|
new_page->next = NULL;
|
||||||
|
return new_page + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void *data) {
|
||||||
|
page_tag *data_tag = data - sizeof(page_tag);
|
||||||
|
|
||||||
|
data_tag->prev->next = data_tag->next;
|
||||||
|
data_tag->next->prev = data_tag->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
int amount_of_digits(int x) {
|
||||||
|
if (x == 0) return 1;
|
||||||
|
int n = 0;
|
||||||
|
while (x != 0) {
|
||||||
|
n += 1;
|
||||||
|
x /= 10;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MEM_SIZE_WIDTH 3
|
||||||
|
#define SPACED_ARRAY {' ', ' ', ' '};
|
||||||
|
|
||||||
|
void print_memory() {
|
||||||
|
print("____________________\n");
|
||||||
|
print(" === MEM DUMP === \n");
|
||||||
|
print("--------------------\n");
|
||||||
|
print("Page tag size: %d bytes\n", sizeof(page_tag));
|
||||||
|
print("Memory alignment: %d bytes\n", PAGE_ALIGNMENT);
|
||||||
|
print("=> idx: [page_tag_address] [data_address (size|aligment_padding_size)]\n\n");
|
||||||
|
page_tag *curr_page = start;
|
||||||
|
int i = 0;
|
||||||
|
bool left = true;
|
||||||
|
while (curr_page != NULL) {
|
||||||
|
char padding[MEM_SIZE_WIDTH] = SPACED_ARRAY;
|
||||||
|
padding[MEM_SIZE_WIDTH - amount_of_digits(curr_page->size)] = '\0';
|
||||||
|
print("%d: [%x] [%x (%s%d|%d)]",
|
||||||
|
i,
|
||||||
|
curr_page,
|
||||||
|
(curr_page + 1), padding, curr_page->size,
|
||||||
|
curr_page->realsize - curr_page->size);
|
||||||
|
|
||||||
|
if (left) {
|
||||||
|
print(" | ");
|
||||||
|
} else {
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
left = !left;
|
||||||
|
|
||||||
|
bool empty_print = false;
|
||||||
|
void *empty_start = (void *) curr_page + sizeof(page_tag) + curr_page->realsize;
|
||||||
|
if (empty_start + sizeof(page_tag) < (void *) curr_page->next) {
|
||||||
|
size_t memory_left = (void *) curr_page->next -
|
||||||
|
(empty_start + sizeof(page_tag));
|
||||||
|
char empty_padding[MEM_SIZE_WIDTH] = SPACED_ARRAY;
|
||||||
|
empty_padding[MEM_SIZE_WIDTH - amount_of_digits(memory_left)] = '\0';
|
||||||
|
|
||||||
|
print("_: free space (%d + %s%d| ) ",
|
||||||
|
sizeof(page_tag),
|
||||||
|
empty_padding,
|
||||||
|
memory_left
|
||||||
|
);
|
||||||
|
empty_print = true;
|
||||||
|
} else if (empty_start < (void *) curr_page->next) {
|
||||||
|
size_t memory_left = (void *) curr_page->next - empty_start;
|
||||||
|
|
||||||
|
char empty_padding[MEM_SIZE_WIDTH] = SPACED_ARRAY;
|
||||||
|
empty_padding[MEM_SIZE_WIDTH - amount_of_digits(memory_left)] = '\0';
|
||||||
|
|
||||||
|
print("_: not enough room (%s%d| ) ",
|
||||||
|
empty_padding,
|
||||||
|
memory_left);
|
||||||
|
empty_print = true;
|
||||||
|
}
|
||||||
|
if (empty_print) {
|
||||||
|
if (left) {
|
||||||
|
print(" | ");
|
||||||
|
} else {
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
left = !left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
curr_page = curr_page->next;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
if (!left) {
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
print("____________________\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int command_mem_dump(char *string) {
|
||||||
|
print_memory();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//void test_allocs() {
|
||||||
|
// void *ptr0 = __alloc(64);
|
||||||
|
// void *ptr1 = __alloc(64);
|
||||||
|
// void *ptr4 = __alloc(64);
|
||||||
|
// print();
|
||||||
|
//
|
||||||
|
// printf("Free nr 2 -> %p\n", ptr1);
|
||||||
|
// __free(ptr1);
|
||||||
|
// print();
|
||||||
|
//
|
||||||
|
// printf("Alloc 32 bytes\n");
|
||||||
|
// void *ptr2 = __alloc(32);
|
||||||
|
// print();
|
||||||
|
//
|
||||||
|
// printf("Alloc 32 bytes\n");
|
||||||
|
// __alloc(32);
|
||||||
|
// print();
|
||||||
|
//
|
||||||
|
// printf("Alloc 8 bytes\n");
|
||||||
|
// void *ptr3 = __alloc(8);
|
||||||
|
// print();
|
||||||
|
//
|
||||||
|
// __free(ptr2);
|
||||||
|
// print();
|
||||||
|
// __free(ptr4);
|
||||||
|
// print();
|
||||||
|
// __free(ptr3);
|
||||||
|
// print();
|
||||||
|
//
|
||||||
|
// __free(ptr0);
|
||||||
|
// print();
|
||||||
|
//
|
||||||
|
// printf("#########\nTry almost fill\n");
|
||||||
|
// __alloc(160);
|
||||||
|
// print();
|
||||||
|
// __alloc(50);
|
||||||
|
// print();
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//int main() {
|
||||||
|
// start = malloc(sizeof(size_t) * 1000);
|
||||||
|
// start->next = NULL;
|
||||||
|
// start->prev = NULL;
|
||||||
|
// test_allocs();
|
||||||
|
//}
|
||||||
|
|
||||||
#endif // MEMORY_C
|
#endif // MEMORY_C
|
125
kernel/shell.c
125
kernel/shell.c
|
@ -8,28 +8,29 @@
|
||||||
#include "terminal.c"
|
#include "terminal.c"
|
||||||
#include "inline_asm.c"
|
#include "inline_asm.c"
|
||||||
#include "drivers/keyboard/keyboard.c"
|
#include "drivers/keyboard/keyboard.c"
|
||||||
|
#include "memory.c"
|
||||||
|
|
||||||
char buffer[SHELL_CMD_BUFFER_SIZE];
|
char buffer[SHELL_CMD_BUFFER_SIZE];
|
||||||
int buffer_idx = 0;
|
int buffer_idx = 0;
|
||||||
|
|
||||||
int echo(char* input) {
|
int echo(char *input) {
|
||||||
terminal_writestring(input);
|
terminal_writestring(input);
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hello(char* unused) {
|
int hello(char *unused) {
|
||||||
terminal_writestring("Hello, world!\n");
|
terminal_writestring("Hello, world!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cls(char* unused) {
|
int cls(char *unused) {
|
||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_gdt(char* unused) {
|
int get_gdt(char *unused) {
|
||||||
gdt_desc desc = {2,2};
|
gdt_desc desc = {2, 2};
|
||||||
sgdt(&desc);
|
sgdt(&desc);
|
||||||
terminal_writestring("limit = ");
|
terminal_writestring("limit = ");
|
||||||
terminal_writeint(desc.limit, 10);
|
terminal_writeint(desc.limit, 10);
|
||||||
|
@ -37,8 +38,8 @@ int get_gdt(char* unused) {
|
||||||
terminal_writeint(desc.base, 16);
|
terminal_writeint(desc.base, 16);
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
|
|
||||||
gdt_entry* entries = (gdt_entry*) desc.base;
|
gdt_entry *entries = (gdt_entry *) desc.base;
|
||||||
int num_entries = (desc.limit+1) / 8;
|
int num_entries = (desc.limit + 1) / 8;
|
||||||
for (int entry_num = 0; entry_num < num_entries; entry_num++) {
|
for (int entry_num = 0; entry_num < num_entries; entry_num++) {
|
||||||
gdt_entry entry = entries[entry_num];
|
gdt_entry entry = entries[entry_num];
|
||||||
uint32_t base = entry.base_lower | entry.base_middle << 16 | entry.base_higher << 24;
|
uint32_t base = entry.base_lower | entry.base_middle << 16 | entry.base_higher << 24;
|
||||||
|
@ -48,68 +49,66 @@ int get_gdt(char* unused) {
|
||||||
|
|
||||||
//terminal_writestring("\nEntry ");
|
//terminal_writestring("\nEntry ");
|
||||||
//terminal_writeint(entry_num, 10);
|
//terminal_writeint(entry_num, 10);
|
||||||
terminal_writestring("base = 0x");
|
print("base = %x\n", base);
|
||||||
terminal_writeint(base, 16);
|
print("limit = %x\n", limit);
|
||||||
terminal_writestring("\nlimit = 0x");
|
print("flags = %b\n", (entry.flags_limit_higher >> 4));
|
||||||
terminal_writeint(limit, 16);
|
|
||||||
terminal_writestring("\nflags = 0b");
|
|
||||||
terminal_writeint((entry.flags_limit_higher >> 4), 2);
|
|
||||||
|
|
||||||
if ((flags & 0b1000) == 0) {
|
if ((flags & 0b1000) == 0) {
|
||||||
terminal_writestring(" (byte granularity");
|
print(" (byte granularity");
|
||||||
} else {
|
} else {
|
||||||
terminal_writestring(" (page granularity");
|
print(" (page granularity");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & 0b0100) == 0) {
|
if ((flags & 0b0100) == 0) {
|
||||||
terminal_writestring(", 16 bit)");
|
print(", 16 bit)");
|
||||||
} else {
|
} else {
|
||||||
terminal_writestring(", 32 bit)");
|
print(", 32 bit)");
|
||||||
}
|
}
|
||||||
|
print("\n");
|
||||||
|
|
||||||
terminal_writestring("\naccess = 0b");
|
print("access = %b (ring %d",
|
||||||
terminal_writeint(entry.access_byte, 2);
|
entry.access_byte,
|
||||||
terminal_writestring(" (ring ");
|
(entry.access_byte & 0b01100000) >> 5
|
||||||
terminal_writeint((entry.access_byte & 0b01100000) >> 5, 10);
|
);
|
||||||
if ((entry.access_byte & 0b00010000) == 0) {
|
if ((entry.access_byte & 0b00010000) == 0) {
|
||||||
terminal_writestring(", System");
|
print(", System");
|
||||||
}
|
}
|
||||||
if (is_data) {
|
if (is_data) {
|
||||||
terminal_writestring(", Data");
|
print(", Data");
|
||||||
|
|
||||||
if((entry.access_byte & 0b00000100) == 0) {
|
if ((entry.access_byte & 0b00000100) == 0) {
|
||||||
terminal_writestring(" (growing up, ");
|
print(" (growing up, ");
|
||||||
} else {
|
} else {
|
||||||
terminal_writestring(" (growing down, ");
|
print(" (growing down, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if((entry.access_byte & 0b00000010) == 0) {
|
if ((entry.access_byte & 0b00000010) == 0) {
|
||||||
terminal_writestring("r--)");
|
print("r--)");
|
||||||
} else {
|
} else {
|
||||||
terminal_writestring("rw-)");
|
print("rw-)");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
terminal_writestring(", Code");
|
print(", Code");
|
||||||
|
|
||||||
if((entry.access_byte & 0b00000100) == 0) {
|
if ((entry.access_byte & 0b00000100) == 0) {
|
||||||
terminal_writestring(" (non-conforming, ");
|
print(" (non-conforming, ");
|
||||||
} else {
|
} else {
|
||||||
terminal_writestring(" (conforming, ");
|
print(" (conforming, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if((entry.access_byte & 0b00000010) == 0) {
|
if ((entry.access_byte & 0b00000010) == 0) {
|
||||||
terminal_writestring("--x)");
|
print("--x)");
|
||||||
} else {
|
} else {
|
||||||
terminal_writestring("r-x)");
|
print("r-x)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal_writestring(")\n");
|
print(")\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ree(char* unused) {
|
int ree(char *unused) {
|
||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
terminal_putchar('R');
|
terminal_putchar('R');
|
||||||
for (int i = 1; i < VGA_WIDTH * VGA_HEIGHT; i++) {
|
for (int i = 1; i < VGA_WIDTH * VGA_HEIGHT; i++) {
|
||||||
|
@ -118,27 +117,41 @@ int ree(char* unused) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int save_text(char *text) {
|
||||||
|
char *mem_block = alloc(strlen(text) * sizeof(char));
|
||||||
|
char *c;
|
||||||
|
int i = 0;
|
||||||
|
for (c = text; *c != '\0'; c++) {
|
||||||
|
mem_block[i] = *c;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO This is ugly, fix this
|
// TODO This is ugly, fix this
|
||||||
const char* shell_commands_strings[] = {
|
const char *shell_commands_strings[] = {
|
||||||
"echo",
|
"echo",
|
||||||
"hello",
|
"hello",
|
||||||
"cls",
|
"cls",
|
||||||
"ree",
|
"ree",
|
||||||
"getgdt",
|
"getgdt",
|
||||||
NULL
|
"memdump",
|
||||||
|
"savetext",
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
int (*shell_commands_functions[]) (char*) = {
|
int (*shell_commands_functions[])(char *) = {
|
||||||
echo,
|
echo,
|
||||||
hello,
|
hello,
|
||||||
cls,
|
cls,
|
||||||
ree,
|
ree,
|
||||||
get_gdt
|
get_gdt,
|
||||||
|
command_mem_dump,
|
||||||
|
save_text
|
||||||
};
|
};
|
||||||
|
|
||||||
int run_command(char* buffer) {
|
int run_command(char *buffer) {
|
||||||
|
|
||||||
if(buffer[0] == 0) {
|
if (buffer[0] == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
char command[SHELL_CMD_BUFFER_SIZE] = {0};
|
char command[SHELL_CMD_BUFFER_SIZE] = {0};
|
||||||
|
@ -150,9 +163,9 @@ int run_command(char* buffer) {
|
||||||
|
|
||||||
int command_idx = 0;
|
int command_idx = 0;
|
||||||
|
|
||||||
while(shell_commands_strings[command_idx] != NULL) {
|
while (shell_commands_strings[command_idx] != NULL) {
|
||||||
int check_idx = 0;
|
int check_idx = 0;
|
||||||
while(command[check_idx] != 0 && shell_commands_strings[command_idx][check_idx] == command[check_idx]) {
|
while (command[check_idx] != 0 && shell_commands_strings[command_idx][check_idx] == command[check_idx]) {
|
||||||
check_idx++;
|
check_idx++;
|
||||||
}
|
}
|
||||||
if (command[check_idx] == 0 && shell_commands_strings[command_idx][check_idx] == 0) {
|
if (command[check_idx] == 0 && shell_commands_strings[command_idx][check_idx] == 0) {
|
||||||
|
@ -176,7 +189,7 @@ void shell_step() {
|
||||||
buffer_idx = 0;
|
buffer_idx = 0;
|
||||||
|
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
terminal_writestring("No such command\n");
|
print("No such command\n");
|
||||||
}
|
}
|
||||||
} else if (curr_char == 0x08) {
|
} else if (curr_char == 0x08) {
|
||||||
if (buffer_idx != 0) {
|
if (buffer_idx != 0) {
|
||||||
|
|
91
kernel/tests/tests.c
Normal file
91
kernel/tests/tests.c
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#ifndef TESTS_TESTS_C
|
||||||
|
#define TESTS_TESTS_C
|
||||||
|
|
||||||
|
#define TESTS_ENABLED
|
||||||
|
#ifdef TESTS_ENABLED
|
||||||
|
|
||||||
|
|
||||||
|
#define mu_assert(message, test) do { if (!(test)) return message; } while (0)
|
||||||
|
#define mu_run_test(test) do { char *message = test(); tests_run++; \
|
||||||
|
if (message) return message; } while (0)
|
||||||
|
extern int tests_run;
|
||||||
|
|
||||||
|
#include "../memory.c"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
int tests_run = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static char *test_memory() {
|
||||||
|
|
||||||
|
ll_node *ll_head = __new_node();
|
||||||
|
ll_head->data = malloc(sizeof(size_t) * 5000);
|
||||||
|
ll_head->used = true;
|
||||||
|
ll_head->size = 1;
|
||||||
|
void *ptr0 = __alloc(ll_head, 5);
|
||||||
|
void *ptr1 = __alloc(ll_head, 5);
|
||||||
|
void *ptr4 = __alloc(ll_head, 5);
|
||||||
|
print(ll_head);
|
||||||
|
mu_assert("Error: chain should be complete at 1", ll_head->next != NULL);
|
||||||
|
mu_assert("Error: chain should be complete at 2", ll_head->next->next != NULL);
|
||||||
|
mu_assert("Error: chain should be complete at 3", ll_head->next->next->next != NULL);
|
||||||
|
mu_assert("Error: chain should be complete at 4", ll_head->next->next->next->next == NULL);
|
||||||
|
|
||||||
|
ll_node *current = ll_head;
|
||||||
|
while (current->next != NULL) {
|
||||||
|
current = current->next;
|
||||||
|
|
||||||
|
mu_assert("Error: block should have size 5", current->size == 5);
|
||||||
|
mu_assert("Error: block should be in use", current->used == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
__free(ll_head, ptr1);
|
||||||
|
mu_assert("", ll_head->next->used == true);
|
||||||
|
mu_assert("", ll_head->next->next->used == false);
|
||||||
|
mu_assert("", ll_head->next->next->next->used == true);
|
||||||
|
|
||||||
|
printf("Alloc 3 bytes\n");
|
||||||
|
void *ptr2 = __alloc(ll_head, 3);
|
||||||
|
print(ll_head);
|
||||||
|
|
||||||
|
printf("Alloc 3 bytes\n");
|
||||||
|
__alloc(ll_head, 3);
|
||||||
|
print(ll_head);
|
||||||
|
|
||||||
|
printf("Alloc 2 bytes\n");
|
||||||
|
void *ptr3 = __alloc(ll_head, 2);
|
||||||
|
print(ll_head);
|
||||||
|
|
||||||
|
__free(ll_head, ptr2);
|
||||||
|
print(ll_head);
|
||||||
|
__free(ll_head, ptr4);
|
||||||
|
print(ll_head);
|
||||||
|
__free(ll_head, ptr3);
|
||||||
|
print(ll_head);
|
||||||
|
|
||||||
|
__free(ll_head, ptr0);
|
||||||
|
print(ll_head);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *all_tests() {
|
||||||
|
mu_run_test(test_memory);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//int main(int argc, char **argv) {
|
||||||
|
// char *result = all_tests();
|
||||||
|
// if (result != 0) {
|
||||||
|
// printf("%s\n", result);
|
||||||
|
// } else {
|
||||||
|
// printf("ALL TESTS PASSED\n");
|
||||||
|
// }
|
||||||
|
// printf("Tests run: %d\n", tests_run);
|
||||||
|
//
|
||||||
|
// return result != 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
#endif // TESTS_ENABLED
|
||||||
|
|
||||||
|
#endif // TESTS_TESTS_C
|
72
kernel/util/printer.c
Normal file
72
kernel/util/printer.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
#ifndef UTIL_PRINTER_C
|
||||||
|
#define UTIL_PRINTER_C
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "../terminal.c"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fmt is a string with specifiers where variables can be inserted.
|
||||||
|
*
|
||||||
|
* ex: ("Hello %s", "world") -> "Hello world"
|
||||||
|
*
|
||||||
|
* Specifiers are
|
||||||
|
* - %c: character
|
||||||
|
* - %d: digit (integer)
|
||||||
|
* - %x: hexadecimal value. Can be used to print pointers to
|
||||||
|
* - %b: binary value. Digits with base 2
|
||||||
|
* @param fmt Formatter string
|
||||||
|
* @param ... Variable amount of arguments to be inserted
|
||||||
|
*/
|
||||||
|
void print(const char *fmt, ...) {
|
||||||
|
const char *p;
|
||||||
|
va_list argp;
|
||||||
|
int i;
|
||||||
|
char *s;
|
||||||
|
char fmtbuf[256];
|
||||||
|
|
||||||
|
va_start(argp, fmt);
|
||||||
|
|
||||||
|
for (p = fmt; *p != '\0'; p++)
|
||||||
|
if (*p != '%') {
|
||||||
|
terminal_putchar(*p);
|
||||||
|
} else {
|
||||||
|
switch (*++p) {
|
||||||
|
case 'c':
|
||||||
|
i = va_arg(argp, int);
|
||||||
|
|
||||||
|
terminal_putchar((char) i);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
i = va_arg(argp, int);
|
||||||
|
s = itoa(i, fmtbuf, 10);
|
||||||
|
terminal_writestring(s);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
s = va_arg(argp, char *);
|
||||||
|
terminal_writestring(s);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
terminal_writestring("0x");
|
||||||
|
|
||||||
|
i = va_arg(argp, int);
|
||||||
|
s = itoa(i, fmtbuf, 16);
|
||||||
|
terminal_writestring(s);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
terminal_writestring("0b");
|
||||||
|
|
||||||
|
i = va_arg(argp, int);
|
||||||
|
s = itoa(i, fmtbuf, 2);
|
||||||
|
terminal_writestring(s);
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
terminal_putchar('%');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(argp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //UTIL_PRINTER_C
|
Loading…
Reference in a new issue