Compare commits
2 commits
memory_all
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
05c8516217 | ||
|
ef72a8d37a |
8 changed files with 103 additions and 487 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,5 +1 @@
|
||||||
target/
|
target/
|
||||||
|
|
||||||
.idea/
|
|
||||||
CMakeLists.txt
|
|
||||||
cmake-build-debug/
|
|
||||||
|
|
|
@ -11,8 +11,14 @@ To compile, you need:
|
||||||
- `nasm` for compiling the bootloader
|
- `nasm` for compiling the bootloader
|
||||||
- `qemu-system-i386` for emulating (`qemu-system-x86_64` will probably work too, but that is not directly supported)
|
- `qemu-system-i386` for emulating (`qemu-system-x86_64` will probably work too, but that is not directly supported)
|
||||||
|
|
||||||
|
More information about installing a cross compiler can be found [here](https://wiki.osdev.org/GCC_Cross-Compiler#The_Build).
|
||||||
|
|
||||||
If you run `make bin`, it will generate `target/boot.bin`, this is a binary file layed out as described in [the docs](docs/bootloader.md). To burn it on a USB drive, simply `dd if=target/boot.bin of=/dev/sdb` and the drive is bootable and contains an SFS filesystem with the files in `filesystem/`.
|
If you run `make bin`, it will generate `target/boot.bin`, this is a binary file layed out as described in [the docs](docs/bootloader.md). To burn it on a USB drive, simply `dd if=target/boot.bin of=/dev/sdb` and the drive is bootable and contains an SFS filesystem with the files in `filesystem/`.
|
||||||
|
|
||||||
|
In case there are errors in the bootloader you can use `make compile_kernel` to only compile the kernel.
|
||||||
|
|
||||||
|
To run TABS in the qemu simulator run `make run`.
|
||||||
|
|
||||||
## Bootloader
|
## Bootloader
|
||||||
|
|
||||||
The bootloader is self-written, based on articles on [the OSDev wiki](https://wiki.osdev.org/). It's a single stage, ELF-loading bootloader in the most basic way possible.
|
The bootloader is self-written, based on articles on [the OSDev wiki](https://wiki.osdev.org/). It's a single stage, ELF-loading bootloader in the most basic way possible.
|
||||||
|
@ -37,7 +43,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
|
||||||
- [x] Better memory management
|
- [ ] 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,67 +16,52 @@
|
||||||
#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 */
|
{
|
||||||
terminal_initialize();
|
/* Initialize terminal interface */
|
||||||
|
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));
|
||||||
print(" kernel");
|
terminal_writestring(" 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));
|
||||||
print(" World!\n");
|
terminal_writestring(" World!\n");
|
||||||
print("Newlines!\n");
|
terminal_writestring("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;
|
||||||
|
|
||||||
print(memory_str);
|
terminal_writestring(memory_str);
|
||||||
print(management_str);
|
terminal_writestring(management_str);
|
||||||
|
|
||||||
free(memory_str);
|
terminal_writestring((are_interrupts_enabled())? "Interrupts!\n": "No interrupts :(\n");
|
||||||
free(management_str);
|
|
||||||
|
|
||||||
// Some dummy allocations to demonstrate the states of memory and to showcase the memory dump printout.
|
interrupt_init();
|
||||||
void* ptr = alloc(30);
|
|
||||||
alloc(30);
|
|
||||||
alloc(31);
|
|
||||||
free(ptr);
|
|
||||||
|
|
||||||
void* ptr2 = alloc(64);
|
for(;;) {
|
||||||
alloc(61);
|
shell_step();
|
||||||
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,208 +1,13 @@
|
||||||
#ifndef MEMORY_C
|
#ifndef MEMORY_C
|
||||||
#define MEMORY_C
|
#define MEMORY_C
|
||||||
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "terminal.c"
|
void* _curr_end = (void*) 0x200000;
|
||||||
#include "util/printer.c"
|
|
||||||
|
|
||||||
#define MEMORY_START 0x200000
|
void* alloc(size_t size) {
|
||||||
//#define MEMORY_END 0x300000
|
void* thanks_jp = _curr_end;
|
||||||
|
_curr_end += size;
|
||||||
#define PAGE_ALIGNMENT 4
|
return thanks_jp;
|
||||||
|
|
||||||
//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,29 +8,28 @@
|
||||||
#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);
|
||||||
|
@ -38,8 +37,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;
|
||||||
|
@ -49,66 +48,68 @@ int get_gdt(char *unused) {
|
||||||
|
|
||||||
//terminal_writestring("\nEntry ");
|
//terminal_writestring("\nEntry ");
|
||||||
//terminal_writeint(entry_num, 10);
|
//terminal_writeint(entry_num, 10);
|
||||||
print("base = %x\n", base);
|
terminal_writestring("base = 0x");
|
||||||
print("limit = %x\n", limit);
|
terminal_writeint(base, 16);
|
||||||
print("flags = %b\n", (entry.flags_limit_higher >> 4));
|
terminal_writestring("\nlimit = 0x");
|
||||||
|
terminal_writeint(limit, 16);
|
||||||
|
terminal_writestring("\nflags = 0b");
|
||||||
|
terminal_writeint((entry.flags_limit_higher >> 4), 2);
|
||||||
|
|
||||||
if ((flags & 0b1000) == 0) {
|
if ((flags & 0b1000) == 0) {
|
||||||
print(" (byte granularity");
|
terminal_writestring(" (byte granularity");
|
||||||
} else {
|
} else {
|
||||||
print(" (page granularity");
|
terminal_writestring(" (page granularity");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & 0b0100) == 0) {
|
if ((flags & 0b0100) == 0) {
|
||||||
print(", 16 bit)");
|
terminal_writestring(", 16 bit)");
|
||||||
} else {
|
} else {
|
||||||
print(", 32 bit)");
|
terminal_writestring(", 32 bit)");
|
||||||
}
|
}
|
||||||
print("\n");
|
|
||||||
|
|
||||||
print("access = %b (ring %d",
|
terminal_writestring("\naccess = 0b");
|
||||||
entry.access_byte,
|
terminal_writeint(entry.access_byte, 2);
|
||||||
(entry.access_byte & 0b01100000) >> 5
|
terminal_writestring(" (ring ");
|
||||||
);
|
terminal_writeint((entry.access_byte & 0b01100000) >> 5, 10);
|
||||||
if ((entry.access_byte & 0b00010000) == 0) {
|
if ((entry.access_byte & 0b00010000) == 0) {
|
||||||
print(", System");
|
terminal_writestring(", System");
|
||||||
}
|
}
|
||||||
if (is_data) {
|
if (is_data) {
|
||||||
print(", Data");
|
terminal_writestring(", Data");
|
||||||
|
|
||||||
if ((entry.access_byte & 0b00000100) == 0) {
|
if((entry.access_byte & 0b00000100) == 0) {
|
||||||
print(" (growing up, ");
|
terminal_writestring(" (growing up, ");
|
||||||
} else {
|
} else {
|
||||||
print(" (growing down, ");
|
terminal_writestring(" (growing down, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((entry.access_byte & 0b00000010) == 0) {
|
if((entry.access_byte & 0b00000010) == 0) {
|
||||||
print("r--)");
|
terminal_writestring("r--)");
|
||||||
} else {
|
} else {
|
||||||
print("rw-)");
|
terminal_writestring("rw-)");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print(", Code");
|
terminal_writestring(", Code");
|
||||||
|
|
||||||
if ((entry.access_byte & 0b00000100) == 0) {
|
if((entry.access_byte & 0b00000100) == 0) {
|
||||||
print(" (non-conforming, ");
|
terminal_writestring(" (non-conforming, ");
|
||||||
} else {
|
} else {
|
||||||
print(" (conforming, ");
|
terminal_writestring(" (conforming, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((entry.access_byte & 0b00000010) == 0) {
|
if((entry.access_byte & 0b00000010) == 0) {
|
||||||
print("--x)");
|
terminal_writestring("--x)");
|
||||||
} else {
|
} else {
|
||||||
print("r-x)");
|
terminal_writestring("r-x)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print(")\n");
|
terminal_writestring(")\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++) {
|
||||||
|
@ -117,41 +118,27 @@ 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",
|
||||||
"memdump",
|
NULL
|
||||||
"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};
|
||||||
|
@ -163,9 +150,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) {
|
||||||
|
@ -189,7 +176,7 @@ void shell_step() {
|
||||||
buffer_idx = 0;
|
buffer_idx = 0;
|
||||||
|
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
print("No such command\n");
|
terminal_writestring("No such command\n");
|
||||||
}
|
}
|
||||||
} else if (curr_char == 0x08) {
|
} else if (curr_char == 0x08) {
|
||||||
if (buffer_idx != 0) {
|
if (buffer_idx != 0) {
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
#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
|
|
|
@ -1,72 +0,0 @@
|
||||||
#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