summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-02-01 12:48:55 -0500
committerFreya Murphy <freya@freyacat.org>2024-02-01 12:49:44 -0500
commit192a4ccd6bbc2239f047f782a05e888990011e51 (patch)
tree2b3d8a194d3dd33a5d344b4ec6376dbdfdb3eb0c
parentundo bad decisions (diff)
downloadcorn-192a4ccd6bbc2239f047f782a05e888990011e51.tar.gz
corn-192a4ccd6bbc2239f047f782a05e888990011e51.tar.bz2
corn-192a4ccd6bbc2239f047f782a05e888990011e51.zip
acpi, fix mboot memory map, fix kalloc, fix virtalloc node allocator, add kprintf, other changes
-rw-r--r--Makefile2
-rw-r--r--include/lib.h52
-rw-r--r--include/serial.h2
-rw-r--r--include/shim.h6
-rw-r--r--src/arch/amd64/acpi.c7
-rw-r--r--src/arch/amd64/boot.S4
-rw-r--r--src/arch/amd64/linker.ld38
-rw-r--r--src/arch/amd64/mboot.c138
-rw-r--r--src/arch/amd64/mboot.h2
-rw-r--r--src/arch/amd64/serial.c4
-rw-r--r--src/arch/amd64/shim.c5
-rw-r--r--src/kmain.c4
-rw-r--r--src/lib.c5
-rw-r--r--src/memory/memory.c34
-rw-r--r--src/memory/physalloc.c25
-rw-r--r--src/memory/virtalloc.c81
-rw-r--r--src/print.c564
17 files changed, 836 insertions, 137 deletions
diff --git a/Makefile b/Makefile
index 8b38f24..2a8c565 100644
--- a/Makefile
+++ b/Makefile
@@ -52,5 +52,7 @@ run: all
qemu-system-x86_64 \
-cdrom $(BUILD_DIR)/$(ISO_NAME) \
-serial stdio \
+ -display gtk,show-menubar=off,zoom-to-fit=on \
-m 4G \
+ -enable-kvm \
-name corn
diff --git a/include/lib.h b/include/lib.h
index 1b6d1f4..3be1f8b 100644
--- a/include/lib.h
+++ b/include/lib.h
@@ -1,5 +1,6 @@
#pragma once
+#include <stdarg.h>
#include <stddef.h>
/**
@@ -109,7 +110,7 @@ long long int atoll(const char* s);
/**
* Converts a integer to asci inside a string with a given radix (base).
- * @param n - the number to conver
+ * @param n - the number to conver
* @param buffer - the string buffer
* @param radix - the base to convert
*/
@@ -117,15 +118,23 @@ char *itoa(int n, char *buffer, int radix);
/**
* Converts a long to asci inside a string with a given radix (base).
- * @param n - the number to conver
+ * @param n - the number to conver
* @param buffer - the string buffer
* @param radix - the base to convert
*/
char *ltoa(long int n, char *buffer, int radix);
/**
+ * Converts a long long to asci inside a string with a given radix (base).
+ * @param n - the number to conver
+ * @param buffer - the string buffer
+ * @param radix - the base to convert
+ */
+char *lltoa(long long int n, char *buffer, int radix);
+
+/**
* Converts a unsigned integer to asci inside a string with a given radix (base).
- * @param n - the number to conver
+ * @param n - the number to conver
* @param buffer - the string buffer
* @param radix - the base to convert
*/
@@ -133,13 +142,21 @@ char *utoa(unsigned int n, char *buffer, int radix);
/**
* Converts a unsigned long to asci inside a string with a given radix (base).
- * @param n - the number to conver
+ * @param n - the number to conver
* @param buffer - the string buffer
* @param radix - the base to convert
*/
char *ultoa(unsigned long int n, char *buffer, int radix);
/**
+ * Converts a unsigned long long to asci inside a string with a given radix (base).
+ * @param n - the number to conver
+ * @param buffer - the string buffer
+ * @param radix - the base to convert
+ */
+char *ulltoa(unsigned long long int n, char *buffer, int radix);
+
+/**
* Converts the string in str to an int value based on the given base.
* The endptr is updated to where the string was no longer valid.
* @param str - the string buffer
@@ -168,3 +185,30 @@ long int strtol(const char *str, char **endptr, int base);
* @returns 0 on error or success, error if endptr is still equal to str
*/
long long int strtoll(const char *str, char **endptr, int base);
+
+/**
+ * Prints out a char
+ * @param c - the char
+ */
+void kputc(char c);
+
+/**
+ * Prints out a null terminated string
+ * @param s - the string
+ */
+void kputs(const char *s);
+
+/**
+ * Prints out a formatted string
+ * @param format - the format string
+ * @param ... - variable args for the format
+ */
+void kvprintf(const char *format, va_list args);
+
+/**
+ * Prints out a formatted string
+ * @param format - the format string
+ * @param ... - variable args for the format
+ */
+__attribute__((format(printf, 1, 2)))
+void kprintf(const char *format, ...);
diff --git a/include/serial.h b/include/serial.h
index a7da91c..7587d74 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -5,4 +5,4 @@
int serial_init(void);
uint8_t serial_in(void);
void serial_out(uint8_t ch);
-void serial_out_str(char *str);
+void serial_out_str(const char *str);
diff --git a/include/shim.h b/include/shim.h
index dc8c19c..7178a0f 100644
--- a/include/shim.h
+++ b/include/shim.h
@@ -2,7 +2,8 @@
#include <memory.h>
-#define CMDLINE_MAX 32
+#define CMDLINE_MAX 32
+#define MMAP_MAX_ENTRY 64
struct memory_segment {
uint64_t addr;
@@ -12,8 +13,7 @@ struct memory_segment {
struct memory_map {
uint32_t entry_count;
- uint32_t entry_length;
- struct memory_segment *entries;
+ struct memory_segment entries[MMAP_MAX_ENTRY];
};
struct boot_info {
diff --git a/src/arch/amd64/acpi.c b/src/arch/amd64/acpi.c
index 83f2014..70c2f38 100644
--- a/src/arch/amd64/acpi.c
+++ b/src/arch/amd64/acpi.c
@@ -31,7 +31,7 @@ struct rsdp {
char oemid[6];
uint8_t revision;
uint32_t rsdt_addr;
-} __attribute__((packed));
+};
// eXtended system descriptor pointer
// ACPI 2.0
@@ -46,7 +46,7 @@ struct xsdp {
uint64_t xsdt_addr;
uint8_t extendeid_checksum;
uint8_t reserved[3];
-} __attribute__((packed));
+};
// root system descriptor table
// ACPI 1.0
@@ -161,10 +161,8 @@ static bool checksum(uint8_t *data, size_t len) {
}
static int read_s5_addr(struct acpi_state *state) {
- serial_out_str("a");
uintptr_t ptr = state->fadt.dsdt;
char *s5_addr = (void*) (ptr + 36);
- serial_out_str("a");
int dsdt_len = *((int*) (ptr+1)) - 36;
while (0 < dsdt_len--) {
@@ -256,6 +254,7 @@ int acpi_init_rsdt(struct rsdt *rsdt) {
int acpi_init_xsdt(struct xsdt *xsdt) {
xsdt = mmap(xsdt, sizeof(struct xsdt));
+ return -1;
state.dst.xsdt = xsdt;
state.version = 2;
diff --git a/src/arch/amd64/boot.S b/src/arch/amd64/boot.S
index 55d942b..455b68b 100644
--- a/src/arch/amd64/boot.S
+++ b/src/arch/amd64/boot.S
@@ -90,6 +90,8 @@ start:
push DWORD 0
push ebx
+ push DWORD 0
+ push eax
mov edi, 0x1000
mov cr3, edi
@@ -143,8 +145,10 @@ code64:
xor rbp, rbp ; set ebp to 0 so we know where to end stack traces
pop rdi
+ pop rsi
call amd64_shim
mov rdi, rax
+ xor rsi, rsi
sti
call kmain
diff --git a/src/arch/amd64/linker.ld b/src/arch/amd64/linker.ld
new file mode 100644
index 0000000..0032765
--- /dev/null
+++ b/src/arch/amd64/linker.ld
@@ -0,0 +1,38 @@
+ENTRY(start)
+
+SECTIONS {
+ . = 1M;
+
+ kernel_start = .;
+
+ .boot BLOCK(4K) : ALIGN(4K)
+ {
+ *(.multiboot)
+ }
+
+ .rodata BLOCK(4K) : ALIGN(4K)
+ {
+ *(.rodata)
+ }
+
+ .data BLOCK(4K) : ALIGN(4K)
+ {
+ *(.data)
+ }
+
+ text_start = .;
+
+ .text BLOCK(4K) : ALIGN(4K)
+ {
+ *(.text)
+ }
+
+ text_end = .;
+
+ .bss BLOCK(4K) : ALIGN(4K)
+ {
+ *(.bss)
+ }
+
+ kernel_end = .;
+}
diff --git a/src/arch/amd64/mboot.c b/src/arch/amd64/mboot.c
index 6c3c413..b7124df 100644
--- a/src/arch/amd64/mboot.c
+++ b/src/arch/amd64/mboot.c
@@ -1,17 +1,25 @@
-#include "mboot.h"
-#include "serial.h"
-#include "shim.h"
-
+#include <shim.h>
#include <lib.h>
#include <stdint.h>
+#include <panic.h>
+
+#include "mboot.h"
+
+#define MBOOT_HEADER_MAGIC 0x36D76289
+
+#define MBOOT_CMDLINE 1
+#define MBOOT_MEMORY_MAP 6
+#define MBOOT_ELF_SYMBOLS 9
+#define MBOOT_OLD_RSDP 14
+#define MBOOT_NEW_RSDP 15
extern char symtab;
#define kaddr(addr) ((uintptr_t)(&addr))
-typedef unsigned char mboot_uint8_t;
-typedef unsigned short mboot_uint16_t;
-typedef unsigned int mboot_uint32_t;
-typedef unsigned long long mboot_uint64_t;
+typedef uint8_t mboot_uint8_t;
+typedef uint16_t mboot_uint16_t;
+typedef uint32_t mboot_uint32_t;
+typedef uint64_t mboot_uint64_t;
struct mboot_info {
mboot_uint32_t total_size;
@@ -25,24 +33,17 @@ struct mboot_tag {
char data[];
};
-enum mboot_tag_type {
- MBOOT_CMDLINE = 0,
- MBOOT_MEMORYMAP = 6,
- MBOOT_SYMBOLS = 9,
- MBOOT_RSDP = 14,
- MBOOT_XSDP = 15,
-};
-
-struct mboot_elf_header_layout {
+struct mboot_tag_elf_sections {
mboot_uint32_t type;
mboot_uint32_t size;
- mboot_uint32_t num;
- mboot_uint32_t entsize;
- mboot_uint32_t shndx;
- char elf_section_headers[];
+ mboot_uint16_t num;
+ mboot_uint16_t entsize;
+ mboot_uint16_t shndx;
+ mboot_uint16_t reserved;
+ char sections[];
};
-struct mboot_elf_section_header {
+struct mboot_tag_elf_sections_entry {
mboot_uint32_t sh_name;
mboot_uint32_t sh_type;
mboot_uint64_t sh_flags;
@@ -55,45 +56,46 @@ struct mboot_elf_section_header {
mboot_uint64_t sh_entsize;
};
-struct mboot_memory_segment {
+struct mboot_mmap_entry {
mboot_uint64_t addr;
mboot_uint64_t len;
mboot_uint32_t type;
- mboot_uint32_t reserved;
+ mboot_uint32_t zero;
};
-struct mboot_memory_map {
- mboot_uint32_t tag;
+struct mboot_tag_mmap {
+ mboot_uint32_t type;
mboot_uint32_t size;
mboot_uint32_t entry_size;
mboot_uint32_t entry_version;
- struct memory_segment entries[];
+ struct mboot_mmap_entry entries[];
};
-struct mboot_rsdp {
- mboot_uint32_t tag;
+
+struct mboot_tag_old_rsdp {
+ mboot_uint32_t type;
mboot_uint32_t size;
mboot_uint8_t rsdp[];
};
-struct mboot_xsdp {
- mboot_uint32_t tag;
+struct mboot_tag_new_rsdp {
+ mboot_uint32_t type;
mboot_uint32_t size;
- mboot_uint8_t xsdp[];
+ mboot_uint8_t rsdp[];
};
-struct mboot_cmdline {
- mboot_uint32_t tag;
+struct mboot_tag_cmdline {
+ mboot_uint32_t type;
mboot_uint32_t size;
- char cmdline[];
+ mboot_uint8_t cmdline[];
};
static void read_symbols(
struct boot_info *shim_info,
- struct mboot_elf_header_layout *layout
+ struct mboot_tag_elf_sections *sections
) {
- shim_info->symbol_table = layout->elf_section_headers;
+ shim_info->symbol_table = sections->sections;
// struct mboot_elf_section_header *section =
// (struct mboot_elf_section_header *) (layout->elf_section_headers);
@@ -130,7 +132,7 @@ static void read_symbols(
static void read_cmdline(
struct boot_info *shim_info,
- struct mboot_cmdline *cmdline
+ struct mboot_tag_cmdline *cmdline
) {
mboot_uint32_t size = cmdline->size - 8;
if (size >= CMDLINE_MAX)
@@ -139,39 +141,49 @@ static void read_cmdline(
shim_info->cmdline[size] = '\0';
}
-static void read_memorymap(
+static void read_memory_map(
struct boot_info *shim_info,
- struct mboot_memory_map *map
+ struct mboot_tag_mmap *map
) {
- int size = map->size - sizeof(mboot_uint32_t) * 4;
- int count = size / map->entry_size;
-
- shim_info->map.entry_count = count;
- shim_info->map.entry_length = map->entry_size;
- shim_info->map.entries = map->entries;
+ int idx = 0;
+ uintptr_t i = (uintptr_t)map->entries;
+ for ( ;
+ i < (uintptr_t)map->entries + map->size;
+ i += map->entry_size, idx++
+ ) {
+ struct mboot_mmap_entry *seg = (struct mboot_mmap_entry *) i;
+ shim_info->map.entries[idx].addr = seg->addr;
+ shim_info->map.entries[idx].type = seg->type;
+ shim_info->map.entries[idx].len = seg->len;
+ }
+ shim_info->map.entry_count = idx;
}
-static void read_rsdp(
+static void read_old_rsdp(
struct boot_info *shim_info,
- struct mboot_rsdp *rsdp
+ struct mboot_tag_old_rsdp *rsdp
) {
if (shim_info->acpi_table != NULL)
return; // xsdp is newer and has been loaded
shim_info->acpi_table = rsdp->rsdp;
}
-static void read_xsdp(
+static void read_new_rsdp(
struct boot_info *shim_info,
- struct mboot_xsdp *xsdp
+ struct mboot_tag_new_rsdp *rsdp
) {
- shim_info->acpi_table = xsdp->xsdp;
+ shim_info->acpi_table = rsdp->rsdp;
}
void mboot_load_info(
+ long mboot_magic,
const void *mboot_data_ptr,
struct boot_info *shim_info
) {
+ if (mboot_magic != MBOOT_HEADER_MAGIC)
+ panic("invalid multiboot magic");
+
memset(shim_info, 0, sizeof(struct boot_info));
struct mboot_info *mboot_info = (struct mboot_info *) mboot_data_ptr;
@@ -186,31 +198,31 @@ void mboot_load_info(
case MBOOT_CMDLINE:
read_cmdline(
shim_info,
- (struct mboot_cmdline *) tag
+ (struct mboot_tag_cmdline *) tag
);
break;
- case MBOOT_MEMORYMAP:
- read_memorymap(
+ case MBOOT_MEMORY_MAP:
+ read_memory_map(
shim_info,
- (struct mboot_memory_map *) tag
+ (struct mboot_tag_mmap *) tag
);
break;
- case MBOOT_SYMBOLS:
+ case MBOOT_ELF_SYMBOLS:
read_symbols(
shim_info,
- (struct mboot_elf_header_layout *) tag
+ (struct mboot_tag_elf_sections *) tag
);
break;
- case MBOOT_RSDP:
- read_rsdp(
+ case MBOOT_OLD_RSDP:
+ read_old_rsdp(
shim_info,
- (struct mboot_rsdp *) tag
+ (struct mboot_tag_old_rsdp *) tag
);
break;
- case MBOOT_XSDP:
- read_xsdp(
+ case MBOOT_NEW_RSDP:
+ read_new_rsdp(
shim_info,
- (struct mboot_xsdp *) tag
+ (struct mboot_tag_new_rsdp *) tag
);
break;
default:
diff --git a/src/arch/amd64/mboot.h b/src/arch/amd64/mboot.h
index 90ed75c..b9c647b 100644
--- a/src/arch/amd64/mboot.h
+++ b/src/arch/amd64/mboot.h
@@ -8,4 +8,4 @@
* @param mboot_info - the pointer passed from multiboot2
* @param shim_info - the info to be collected by shim
*/
-void mboot_load_info(const void *mboot_info, struct boot_info *shim_info);
+void mboot_load_info(long mboot_magic, const void *mboot_info, struct boot_info *shim_info);
diff --git a/src/arch/amd64/serial.c b/src/arch/amd64/serial.c
index 85cd408..d63d9dd 100644
--- a/src/arch/amd64/serial.c
+++ b/src/arch/amd64/serial.c
@@ -16,7 +16,7 @@ int serial_init(void) {
// outb(port + 4, 0x0B); // TODO copied this from osdev wiki but i don't think you need it here
outb(PORT + 4, 0x1E); // set in loopback mode for test
outb(PORT + 0, 0xAE); // test by sending 0xAE
-
+
uint8_t response = inb(PORT + 0);
if(response != 0xAE) {
// TODO panic here?
@@ -40,7 +40,7 @@ void serial_out(uint8_t ch) {
outb(PORT, ch);
}
-void serial_out_str(char *str) {
+void serial_out_str(const char *str) {
for(; *str != '\0'; str++) {
serial_out(*str);
}
diff --git a/src/arch/amd64/shim.c b/src/arch/amd64/shim.c
index 7332994..3c0bd72 100644
--- a/src/arch/amd64/shim.c
+++ b/src/arch/amd64/shim.c
@@ -11,14 +11,13 @@
static struct boot_info boot_info;
-void* amd64_shim(void *mboot_data_ptr) {
-
+void* amd64_shim(long mboot_magic, void *mboot_data_ptr) {
serial_init();
paging_init();
pic_remap();
idt_init();
- mboot_load_info(mboot_data_ptr, &boot_info);
+ mboot_load_info(mboot_magic, mboot_data_ptr, &boot_info);
return &boot_info;
}
diff --git a/src/kmain.c b/src/kmain.c
index 54ed506..057620d 100644
--- a/src/kmain.c
+++ b/src/kmain.c
@@ -10,11 +10,13 @@ void kmain(struct boot_info *info) {
//acpi_init(info->acpi_table);
//fb_init(1024, 768);
- serial_out_str("entered kmain\n");
+ kprintf("enterd kmain\n");
+
*(char*)(0xB8000 + 0x144) = 'h';
*(char*)(0xB8000 + 0x146) = 'i';
while (1) {
+ //kprintf("ret: 0x%p\n", kalloc(2));
// loop so we dont halt
// this allows interrupts to fire
}
diff --git a/src/lib.c b/src/lib.c
index db09dda..7f3d79f 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -1,5 +1,5 @@
+#include "memory.h"
#include <lib.h>
-
#include <stddef.h>
int memcmp(const void *restrict vl, const void *restrict vr, unsigned long n) {
@@ -31,6 +31,7 @@ void *memmove(void *dest, const void *src, unsigned long n) {
}
void *memset(void *restrict dest, int c, unsigned long n) {
+
unsigned char *d = dest;
for (; n; n--) *d++ = c;
return dest;
@@ -149,6 +150,7 @@ int ctoi(char c) {
UXTOA(int, utoa)
UXTOA(long int, ultoa)
+UXTOA(long long int, ulltoa)
#define XTOA(type, name) \
char *name(type n, char* buffer, int radix) { \
@@ -176,6 +178,7 @@ UXTOA(long int, ultoa)
XTOA(int, itoa)
XTOA(long int, ltoa)
+XTOA(long long int, lltoa)
#define STRTOX(name, type) \
type name(const char *s, char **endptr, int radix) { \
diff --git a/src/memory/memory.c b/src/memory/memory.c
index 1c69bae..af63865 100644
--- a/src/memory/memory.c
+++ b/src/memory/memory.c
@@ -1,10 +1,8 @@
+#include "serial.h"
#include <memory.h>
#include <stdint.h>
#include <lib.h>
-
-#ifdef MEMORY_PANIC
#include <panic.h>
-#endif
#define MAGIC 0xBEEFCAFE
@@ -18,8 +16,8 @@ struct page_header {
};
static const size_t header_len = sizeof(struct page_header);
-struct page_header *start_header = NULL;
-struct page_header *end_header = NULL;
+static struct page_header *start_header = NULL;
+static struct page_header *end_header = NULL;
struct page_header* get_header(void *ptr) {
struct page_header *header =
@@ -36,6 +34,7 @@ struct page_header* get_header(void *ptr) {
void *kalloc_new(size_t size) {
size_t pages = ((size + header_len) / PAGE_SIZE) + 1;
+
void *addr = alloc_pages(pages);
void *mem = (char *)addr + header_len;
@@ -54,20 +53,20 @@ void *kalloc_new(size_t size) {
}
struct page_header *header = addr;
- header->magic = MAGIC;
+ header->magic = 0xBEEFCAFE;
header->used = size;
header->free = free;
header->prev = end_header;
header->next = NULL;
header->node_number = node;
- if (end_header == NULL) {
+ if (start_header == NULL) {
start_header = header;
- } else {
- end_header->next = header;
}
- end_header = header;
+ if (end_header != NULL) {
+ end_header->next = header;
+ }
return mem;
}
@@ -97,6 +96,9 @@ void *kalloc(size_t size) {
for (; header != NULL; header = header->next) {
size_t free = header->free;
+ if (free < header_len) {
+ continue;
+ }
if (size <= (free - header_len)) { // we must be able to fit data + header
break;
}
@@ -129,21 +131,13 @@ void *krealloc(void *src, size_t dst_len) {
header = get_header(src);
if (header == NULL) {
-#ifdef MEMORY_PANIC
panic("attempted to realloc on a invalid ptr");
-#else
- return NULL; // invalid pointer passed
-#endif
}
src_len = header->used;
if (src_len == 0) {
-#ifdef MEMORY_PANIC
panic("attempted to realloc on an empty ptr");
-#else
- return NULL; // likely double free :(
-#endif
}
dst = kalloc(dst_len);
@@ -166,11 +160,7 @@ void kfree(void *ptr) {
header = get_header(ptr);
if (header == NULL || header->used == 0) {
-#ifdef MEMORY_PANIC
panic("attempted to kfree invalid pointer");
-#else
- return;
-#endif
}
header->free += header->used;
diff --git a/src/memory/physalloc.c b/src/memory/physalloc.c
index 1140258..bcbc66d 100644
--- a/src/memory/physalloc.c
+++ b/src/memory/physalloc.c
@@ -1,3 +1,4 @@
+#include "serial.h"
#include <memory.h>
#include <stdint.h>
#include <lib.h>
@@ -63,6 +64,10 @@ static inline bool bitmap_get(int i) {
}
static inline void bitmap_set(int i, bool v) {
+ if (v)
+ free_memory -= PAGE_SIZE;
+ else
+ free_memory += PAGE_SIZE;
int idx = i / 64;
bitmap[idx] &= ~(1 << i % 64);
bitmap[idx] |= (v << i % 64);
@@ -115,11 +120,11 @@ void free_phys_pages(void *ptr, int pages) {
}
static bool segment_invalid(const struct memory_segment *segment) {
- if (segment->type != 1) return false;
- if (segment->addr < kaddr(kernel_start)) return false;
- if (segment->addr + segment->len < memory_start) return false;
- if (segment->addr + segment->len < kaddr(kernel_start)) return false;
- return true;
+ if (segment->type != 1) return true;
+ if (segment->addr < kaddr(kernel_start)) return true;
+ if (segment->addr + segment->len < memory_start) return true;
+ if (segment->addr + segment->len < kaddr(kernel_start)) return true;
+ return false;
}
static struct memory_area segment_to_area(const struct memory_segment *segment) {
@@ -195,18 +200,28 @@ void memory_init(struct memory_map *map) {
struct memory_area *area = page_start;
+ kprintf("MEMORY MAP\n");
for(uint32_t i = 0; i < map->entry_count; i++) {
struct memory_segment *segment = &map->entries[i];
if (segment_invalid(segment))
continue;
+ kprintf("addr: 0x%16p\tlen: %ld\n", (void *)segment->addr, segment->len);
+
struct memory_area temp = segment_to_area(segment);
*area = temp;
area++;
}
+ total_memory = page_count * PAGE_SIZE;
page_count -= bitmap_pages;
+ free_memory = page_count * PAGE_SIZE;
+
+ kprintf("\nMEMORY USAGE\n");
+ kprintf("mem total: %ld\n", memory_total());
+ kprintf("mem free: %ld\n", memory_free());
+ kprintf("mem used: %ld\n\n", memory_used());
memory_unlock();
diff --git a/src/memory/virtalloc.c b/src/memory/virtalloc.c
index 781fc9b..2ab9fc2 100644
--- a/src/memory/virtalloc.c
+++ b/src/memory/virtalloc.c
@@ -1,6 +1,9 @@
+#include "lib.h"
+#include "panic.h"
#include <stdint.h>
#include <stddef.h>
#include <memory.h>
+#include <string.h>
#define MEMORY_INTERNAL
#include <memory/virtalloc.h>
@@ -10,34 +13,60 @@ struct addr_node {
uintptr_t end;
struct addr_node *next;
struct addr_node *prev;
- uint8_t is_alloc;
- uint8_t is_bss;
+ uint8_t is_alloc; // if node is storing allocated data
+ uint8_t is_used; // if node is in use by virtalloc
};
-#define BOOTSTRAP_BSS_NODES 16
-static uint8_t bss_nodes = 0;
-static struct addr_node nodes[BOOTSTRAP_BSS_NODES];
+#define BSS_NODES 64
+static struct addr_node bootstrap_nodes[BSS_NODES];
+static struct addr_node *alloc_nodes = NULL;
+static size_t free_node_start = 0;
+static size_t alloc_node_count = 0;
+static size_t used_node_count = 0;
+static bool is_allocating = false;
-static struct addr_node *start_node;
+static struct addr_node *start_node = NULL;
-static struct addr_node *alloc_node(void) {
- struct addr_node *node = NULL;
- if (bss_nodes >= BOOTSTRAP_BSS_NODES) {
- node = kalloc(sizeof(struct addr_node));
- if (node == NULL)
- return NULL;
- node->is_bss = false;
+static struct addr_node *get_node_idx(int idx) {
+ if (idx < BSS_NODES) {
+ return &bootstrap_nodes[idx];
} else {
- node = &nodes[bss_nodes];
- bss_nodes += 1;
- node->is_bss = true;
+ return &alloc_nodes[idx - BSS_NODES];
}
- return node;
+}
+
+static struct addr_node *get_node(void) {
+ size_t count = BSS_NODES + alloc_node_count;
+
+ if (!is_allocating && used_node_count + 16 >= count) {
+ is_allocating = true;
+ int new_alloc = alloc_node_count * 2;
+ if (new_alloc < 8)
+ new_alloc = 8;
+ int allocated = new_alloc - alloc_node_count;
+ int old = new_alloc - allocated;
+ alloc_nodes = krealloc(alloc_nodes, sizeof(struct addr_node) * new_alloc);
+ memset(alloc_nodes + old, 0, sizeof(struct addr_node) + allocated);;
+ alloc_node_count = new_alloc;
+ is_allocating = false;
+ count = BSS_NODES + alloc_node_count;
+ }
+
+ size_t idx = free_node_start;
+ for (; idx < count; idx++) {
+ struct addr_node *node = get_node_idx(idx);
+ if (!node->is_used) {
+ used_node_count++;
+ return node;
+ }
+ }
+
+ panic("could not get virtaddr node");
}
static void free_node(struct addr_node *node) {
- if (!node->is_bss)
- kfree(node);
+ node->is_used = false;
+ used_node_count--;
}
void virtaddr_init(void) {
@@ -47,11 +76,11 @@ void virtaddr_init(void) {
.next = NULL,
.prev = NULL,
.is_alloc = false,
- .is_bss = true,
+ .is_used = true,
};
- nodes[0] = init;
- start_node = &nodes[0];
- bss_nodes++;
+ memset(bootstrap_nodes, 0, sizeof(bootstrap_nodes));
+ bootstrap_nodes[0] = init;
+ start_node = &bootstrap_nodes[0];
}
void *virtaddr_alloc(int n_pages) {
@@ -69,10 +98,7 @@ void *virtaddr_alloc(int n_pages) {
long length = node->end - node->start;
if (length >= n_length) {
- struct addr_node *new = alloc_node();
- if (node == NULL) {
- return NULL;
- }
+ struct addr_node *new = get_node();
if (node->prev != NULL) {
node->prev->next = new;
}
@@ -82,6 +108,7 @@ void *virtaddr_alloc(int n_pages) {
new->end = new->start + n_length;
node->start = new->end;
new->is_alloc = true;
+ new->is_used = true;
new->next = node;
return (void *) new->start;
}
diff --git a/src/print.c b/src/print.c
new file mode 100644
index 0000000..f158985
--- /dev/null
+++ b/src/print.c
@@ -0,0 +1,564 @@
+#include <lib.h>
+#include <serial.h>
+#include <stdarg.h>
+
+void kputc(char c) {
+ serial_out(c);
+}
+
+void kputs(const char *s) {
+ serial_out_str(s);
+}
+
+enum format_flag {
+ FLG_NONE = 0x00,
+ FLG_ALTERNATE = 0x01,
+ FLG_ZERO = 0x02,
+ FLG_LEFT_ALIGN = 0x04,
+ FLG_ADD_SIGN = 0x08
+};
+
+struct format_width {
+ bool defined;
+ bool varys;
+ int value;
+};
+
+struct format_precision {
+ bool defined;
+ bool varys;
+ int value;
+};
+
+enum format_modifier {
+ MOD_NONE,
+ MOD_INVALID,
+ MOD_HALF_HALF,
+ MOD_HALF,
+ MOD_LONG_LONG,
+ MOD_LONG,
+};
+
+enum format_conversion {
+ FMT_INT,
+ FMT_UINT,
+ FMT_OCT,
+ FMT_HEX,
+ FMT_HEX_UPPER,
+ FMT_CHAR,
+ FMT_STR,
+ FMT_PTR,
+ FMT_PTR_UPPER,
+ FMT_PERCENT,
+ FMT_INVALID
+};
+
+static enum format_flag read_flag(const char *format, const char **end) {
+
+ enum format_flag flag = FLG_NONE;
+
+ for (; *format != '\0'; format++) {
+ switch (*format) {
+ case '#':
+ flag |= FLG_ALTERNATE;
+ break;
+ case '0':
+ flag |= FLG_ZERO;
+ break;
+ case '-':
+ flag |= FLG_LEFT_ALIGN;
+ break;
+ case '+':
+ flag |= FLG_ADD_SIGN;
+ break;
+ default:
+ *end = format;
+ return flag;
+ }
+ }
+
+ *end = format;
+ return flag;
+}
+
+static struct format_width read_width(const char *format, const char **end) {
+
+ struct format_width width;
+ width.defined = false;
+ width.varys = false;
+ width.value = 0;
+
+ int value = 0;
+
+ for (; *format != '\0'; format++) {
+ char c = *format;
+
+ if (c == '*' && width.defined == false) {
+ width.defined = true;
+ width.varys = true;
+ break;
+ }
+
+ if (!isdigit(c))
+ break;
+
+ int i = c - '0';
+ value *= 10;
+ value += i;
+
+ width.value = value;
+ width.defined = true;
+ width.varys = false;
+ }
+
+ *end = format;
+ return width;
+
+}
+
+static struct format_precision read_precision(const char *format, const char **end) {
+
+ struct format_precision precision;
+ precision.varys = false;
+ precision.defined = false;
+ precision.value = 0;
+
+ if (*format != '.') {
+ *end = format;
+ return precision;
+ }
+
+ format++;
+
+ int value = 0;
+
+ for (; *format != '\0'; format++) {
+ char c = *format;
+
+ if (c == '*' && precision.defined == false) {
+ precision.defined = true;
+ precision.varys = true;
+ break;
+ }
+
+ if (!isdigit(c))
+ break;
+
+ int i = c - '0';
+ value *= 10;
+ value += i;
+
+ precision.value = value;
+ precision.defined = true;
+ precision.varys = false;
+ }
+
+ *end = format;
+ return precision;
+}
+
+static enum format_modifier read_modifier(const char *format, const char **end) {
+
+ enum format_modifier mod = MOD_NONE;
+
+ for (; *format != '\0'; format++) {
+ *end = format;
+ switch (*format) {
+ case 'l':
+ if (mod == MOD_NONE)
+ mod = MOD_LONG;
+ else if (mod == MOD_LONG)
+ return MOD_LONG_LONG;
+ else
+ return MOD_INVALID;
+ break;
+ case 'L':
+ if (mod == MOD_NONE)
+ return MOD_LONG_LONG;
+ else
+ return MOD_INVALID;
+ break;
+ case 'h':
+ if (mod == MOD_NONE)
+ mod = MOD_HALF;
+ else if (mod == MOD_HALF)
+ return MOD_HALF_HALF;
+ else
+ return MOD_INVALID;
+ break;
+ case 'H':
+ if (mod == MOD_NONE)
+ return MOD_HALF_HALF;
+ else
+ return MOD_INVALID;
+ break;
+ default:
+ return mod;
+ }
+ }
+
+ return MOD_INVALID;
+}
+
+static enum format_conversion read_conversion(const char *format, const char **end) {
+ *end = format + 1;
+ switch (*format) {
+ case 'd':
+ case 'i':
+ return FMT_INT;
+ case 'o':
+ return FMT_OCT;
+ case 'u':
+ return FMT_UINT;
+ case 'x':
+ return FMT_HEX;
+ case 'X':
+ return FMT_HEX_UPPER;
+ case 'c':
+ return FMT_CHAR;
+ case 's':
+ return FMT_STR;
+ case 'p':
+ return FMT_PTR;
+ case 'P':
+ return FMT_PTR_UPPER;
+ case '%':
+ return FMT_PERCENT;
+ default:
+ return FMT_INVALID;
+ }
+}
+
+static void print_string(
+ const char *str,
+ enum format_flag flag,
+ struct format_width width,
+ struct format_precision precision
+) {
+
+ size_t max_len = 0;
+ size_t min_len = 0;
+ size_t len = 0;
+
+ if (width.defined)
+ min_len = width.value;
+
+ if (precision.defined) {
+ max_len = precision.value;
+ len = max_len;
+ if (max_len < min_len)
+ min_len = max_len;
+ } else {
+ len = strlen(str);
+ }
+
+ if (!(flag & FLG_LEFT_ALIGN) && len < min_len) {
+ for (size_t i = 0; i < (min_len - len); i++) {
+ kputc(' ');
+ }
+ }
+
+ for (size_t i = 0; i < len; i++) {
+ kputc(str[i]);
+ }
+
+ if ((flag & FLG_LEFT_ALIGN) && len < min_len) {
+ for (size_t i = 0; i < (min_len - len); i++) {
+ kputc(' ');
+ }
+ }
+}
+
+static char get_letter(
+ char c,
+ char base
+) {
+ if (c >= 0 && c <= 9)
+ return c + '0';
+ c -= 10;
+ return c + base;
+}
+
+static char *get_decimal(
+ long long num,
+ char *buf,
+ char sign,
+ int radix,
+ char base
+) {
+
+ *buf = '\0';
+ buf--;
+
+ if (num == 0) {
+ *buf = '0';
+ buf--;
+ }
+
+ while (num != 0) {
+ char i = num % radix;
+ char c = get_letter(i, base);
+ *buf = c;
+ buf--;
+ num /= radix;
+ }
+
+ if (sign) {
+ *buf = sign;
+ buf--;
+ }
+
+ buf++;
+
+ return buf;
+}
+
+static void print_unum(
+ unsigned long long num,
+ enum format_flag flag,
+ struct format_width width,
+ struct format_precision precision,
+ bool isneg,
+ int radix,
+ char base
+) {
+
+ size_t max_len = 0;
+ size_t min_len = 0;
+ size_t len = 0;
+
+ char sign = 0;
+ if (isneg)
+ sign = '-';
+ else if (flag & FLG_ADD_SIGN)
+ sign = '+';
+
+ char buf[1024];
+ char *str = get_decimal(
+ num,
+ buf,
+ sign,
+ radix,
+ base
+ );
+
+ bool space_pre = (flag & FLG_LEFT_ALIGN) || !(flag & FLG_ZERO);
+
+ if (space_pre && radix == 16 && flag & FLG_ALTERNATE) {
+ char x = base + ('x' - 'a');
+ serial_out('0');
+ serial_out(x);
+ }
+
+ if (width.defined)
+ min_len = width.value;
+
+ if (precision.defined) {
+ max_len = precision.value;
+ len = max_len;
+ if (max_len < min_len)
+ min_len = max_len;
+ } else {
+ len = strlen(str);
+ }
+
+ bool zero_padded = false;
+
+ if (!(flag & FLG_LEFT_ALIGN) && len < min_len) {
+ for (size_t i = 0; i < (min_len - len); i++) {
+ (flag & FLG_ZERO) ? kputc('0') : kputc(' ');
+ }
+ if (flag & FLG_ZERO)
+ zero_padded = true;
+ }
+
+ kputs(str);
+
+ if (!zero_padded && (flag & FLG_ALTERNATE) && radix == 8)
+ kputc('0');
+
+ if ((flag & FLG_LEFT_ALIGN) && len < min_len) {
+ for (size_t i = 0; i < (min_len - len); i++) {
+ (flag & FLG_ZERO) ? kputc('0') : kputc(' ');
+ }
+ }
+}
+
+static void print_num(
+ long long num,
+ enum format_flag flag,
+ struct format_width width,
+ struct format_precision precision,
+ int radix,
+ char base
+) {
+ bool isneg = false;
+
+ if (num < 0) {
+ num = ~num;
+ isneg = true;
+ }
+
+ print_unum(
+ num,
+ flag,
+ width,
+ precision,
+ isneg,
+ radix,
+ base
+ );
+}
+
+void kvprintf(const char *format, va_list args) {
+ for (; *format != '\0'; format++) {
+ char c = *format;
+ if (c == '%') {
+ enum format_flag flag;
+ struct format_width width;
+ struct format_precision precision;
+ enum format_modifier modifier;
+ enum format_conversion conversion;
+
+ const char *ptr = format + 1;
+
+ flag = read_flag(ptr, &ptr);
+ width = read_width(ptr, &ptr);
+ precision = read_precision(ptr, &ptr);
+ modifier = read_modifier(ptr, &ptr);
+
+ if (modifier == MOD_INVALID) {
+ kputc('%');
+ continue;
+ }
+
+ conversion = read_conversion(ptr, &ptr);
+
+ if (conversion == FMT_INVALID) {
+ kputc('%');
+ continue;
+ }
+
+ union {
+ unsigned long long u;
+ long long l;
+ char c;
+ const char *str;
+ void *ptr;
+ } data;
+
+ int radix = 0;
+ char base = 0;
+
+ switch (conversion) {
+ case FMT_INT:
+ if (modifier == MOD_NONE)
+ data.l = va_arg(args, int);
+ else if (modifier == MOD_HALF)
+ data.l = (short) va_arg(args, int);
+ else if (modifier == MOD_HALF_HALF)
+ data.l = (char) va_arg(args, int);
+ else if (modifier == MOD_LONG)
+ data.l = va_arg(args, long);
+ else if (modifier == MOD_LONG_LONG)
+ data.l = va_arg(args, long long);
+ radix = 10;
+ goto printnum;
+ case FMT_UINT:
+ case FMT_OCT:
+ case FMT_HEX_UPPER:
+ case FMT_HEX:
+ if (modifier == MOD_NONE)
+ data.u = va_arg(args, unsigned int);
+ else if (modifier == MOD_HALF)
+ data.u = (unsigned short) va_arg(args, unsigned int);
+ else if (modifier == MOD_HALF_HALF)
+ data.u = (unsigned char) va_arg(args, unsigned int);
+ else if (modifier == MOD_LONG)
+ data.u = va_arg(args, unsigned long);
+ else if (modifier == MOD_LONG_LONG)
+ data.u = va_arg(args, unsigned long long);
+
+ if (conversion == FMT_UINT) {
+ radix = 10;
+ } else if (conversion == FMT_OCT) {
+ radix = 8;
+ } else if (conversion == FMT_HEX) {
+ radix = 16;
+ base = 'a';
+ } else if (conversion == FMT_HEX_UPPER) {
+ radix = 16;
+ base = 'A';
+ }
+ goto printunum;
+ case FMT_PTR:
+ case FMT_PTR_UPPER:
+ flag |= FLG_ZERO;
+ data.u = va_arg(args, size_t);
+ radix = 16;
+ if (conversion == FMT_PTR)
+ base = 'a';
+ else
+ base = 'A';
+ goto printunum;
+ printnum:
+ print_num(
+ data.l,
+ flag,
+ width,
+ precision,
+ radix,
+ base
+ );
+ break;
+ printunum:
+ print_unum(
+ data.u,
+ flag,
+ width,
+ precision,
+ false,
+ radix,
+ base
+ );
+ break;
+ case FMT_CHAR: {
+ char buf[2];
+ buf[0] = (char) va_arg(args, int);
+ buf[1] = '\0';
+ print_string(
+ buf,
+ flag,
+ width,
+ precision
+ );
+ break;
+ }
+ case FMT_STR:
+ data.str = va_arg(args, const char*);
+ print_string(
+ data.str,
+ flag,
+ width,
+ precision
+ );
+ break;
+ case FMT_PERCENT:
+ kputc('%');
+ break;
+ case FMT_INVALID:
+ break;
+ }
+ format = ptr - 1;
+ } else {
+ kputc(c);
+ }
+ }
+}
+
+void kprintf(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ kvprintf(format, args);
+ va_end(args);
+}