From 93bf62580a68533dc8252b9a2a055c02f34ecb67 Mon Sep 17 00:00:00 2001
From: Christian Cunningham <cc@localhost>
Date: Thu, 24 Mar 2022 09:38:08 -0700
Subject: Modularized

---
 kernel/lib/kmem.c    |  38 ++++++++++++++++
 kernel/lib/mmu.S     |  45 +++++++++++++++++++
 kernel/lib/mmu.c     |  33 ++++++++++++++
 kernel/lib/queue.c   |  55 ++++++++++++++++++++++++
 kernel/lib/strings.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 290 insertions(+)
 create mode 100644 kernel/lib/kmem.c
 create mode 100644 kernel/lib/mmu.S
 create mode 100644 kernel/lib/mmu.c
 create mode 100644 kernel/lib/queue.c
 create mode 100644 kernel/lib/strings.c

(limited to 'kernel/lib')

diff --git a/kernel/lib/kmem.c b/kernel/lib/kmem.c
new file mode 100644
index 0000000..9861f12
--- /dev/null
+++ b/kernel/lib/kmem.c
@@ -0,0 +1,38 @@
+#include <globals.h>
+#include <drivers/uart.h>
+#include <lib/kmem.h>
+
+// Output longs at address
+void kmemshow32(void* data, unsigned long length)
+{
+	unsigned long* ptr = data;
+	for(unsigned long i = 0; i < length; i++) {
+		uart_hex(*ptr);
+		ptr+=1;
+		if (i != length-1)
+			uart_char(' ');
+	}
+	uart_char('\n');
+}
+
+// Output bytes at address
+void kmemshow(void* data, unsigned long length)
+{
+	unsigned char* ptr = data;
+	for(unsigned long i = 0; i < length; i++) {
+		char tmp = *ptr>>4;
+		tmp += 0x30;
+		if (tmp > 0x39)
+			tmp += 0x7;
+		uart_char(tmp);
+		tmp = *ptr&0xF;
+		tmp += 0x30;
+		if (tmp > 0x39)
+			tmp += 0x7;
+		uart_char(tmp);
+		ptr+=1;
+		if (i != length-1)
+			uart_char(' ');
+	}
+	uart_char('\n');
+}
diff --git a/kernel/lib/mmu.S b/kernel/lib/mmu.S
new file mode 100644
index 0000000..faca3cc
--- /dev/null
+++ b/kernel/lib/mmu.S
@@ -0,0 +1,45 @@
+.section .text
+.globl mmu_start
+mmu_start:
+	mov r2, #0
+	// Invalidate Caches
+	mcr p15,0,r2,c7,c1,6 
+	// Invalidate TLB entries
+	mcr p15,0,r2,c8,c7,0 
+	// Data synchronisation barrier
+	mcr p15,0,r2,c7,c10,4 
+
+	// Set all domains to 0b11
+	mvn r2, #0
+	bic r2, #0xC
+	mcr p15,0,r2,c3,c0,0
+
+	// Set the translation table base address (remember to align 16 KiB!)
+	mcr p15,0,r0,c2,c0,0
+	mcr p15,0,r0,c2,c0,1
+	mov r3, #0
+	mcr p15,0,r3,c2,c0,2
+
+	// Set the bits mentioned above
+	mrc p15,0,r2,c1,c0,0
+	orr r2,r2,r1
+	mcr p15,0,r2,c1,c0,0
+	bx lr
+
+.globl mmu_stop
+mmu_stop:
+	mrc p15,0,r2,c1,c0,0
+	bic r2,#0x1000
+	bic r2,#0x0004
+	bic r2,#0x0001
+	mcr p15,0,r2,c1,c0,0
+	bx lr
+
+.globl tlb_invalidate
+tlb_invalidate:
+	mov r2, #0
+	// Invalidate Entries
+	mcr p15, 0, r2, c8, c7, 0
+	// DSB
+	mcr p15, 0, r2, c7, c10, 4
+	bx lr
diff --git a/kernel/lib/mmu.c b/kernel/lib/mmu.c
new file mode 100644
index 0000000..e9dda7a
--- /dev/null
+++ b/kernel/lib/mmu.c
@@ -0,0 +1,33 @@
+#include <lib/mmu.h>
+
+#define CACHABLE 0x08
+#define BUFFERABLE 0x04
+#define NO_PERMISSIONS_REQUIRED 0b11 << 10
+#define MMU_TABLE_BASE 0x00004000
+
+void mmu_start(unsigned long base, unsigned long flags);
+
+void mmu_section(unsigned long virtual, unsigned long physical, unsigned long flags)
+{
+	unsigned long offset = virtual >> 20;
+	unsigned long* entry = (unsigned long*)(MMU_TABLE_BASE | (offset << 2));
+	unsigned long physval = (physical & 0xFFF00000) | (flags & 0x7FFC) | 0x00C02;
+	*entry = physval;
+}
+
+extern unsigned long __bss_end;
+void mmu_init(void)
+{
+	for (unsigned long addr =  0x00000000;; addr += 0x00100000) {
+		if (addr < (unsigned long)&__bss_end + 0x00100000) {
+			mmu_section(addr, addr, CACHABLE | BUFFERABLE);
+		} else {
+			mmu_section(addr, addr, NO_PERMISSIONS_REQUIRED);
+		}
+		if (addr == 0x02000000)
+			mmu_section(addr, addr, CACHABLE | BUFFERABLE | NO_PERMISSIONS_REQUIRED);
+		if (addr == 0xFFF00000)
+			break;
+	}
+	mmu_start(MMU_TABLE_BASE,0x00000001|0x1000|0x0004);
+}
diff --git a/kernel/lib/queue.c b/kernel/lib/queue.c
new file mode 100644
index 0000000..1fc35f6
--- /dev/null
+++ b/kernel/lib/queue.c
@@ -0,0 +1,55 @@
+#include <lib/queue.h>
+
+void push_to_queue(struct Entry* e, struct Queue* q)
+{
+	q->end.next->next = e;
+	q->end.next = e;
+	e->next = &q->end;
+}
+
+void prepend_to_queue(struct Entry* e, struct Queue* q)
+{
+	e->next = q->start.next;
+	q->start.next = e;
+	if (e->next->entry_type == END_ENTRY)
+		q->end.next = e;
+}
+
+struct Entry* pop_from_queue(struct Queue* q)
+{
+	if (q->start.next->entry_type == END_ENTRY)
+		return 0;
+	struct Entry* e = q->start.next;
+	q->start.next = e->next;
+	if (e->next->entry_type == END_ENTRY)
+		q->end.next = &q->start;
+	return e;
+}
+
+struct Entry* remove_next_from_queue(struct Entry* e)
+{
+	struct Entry* prev = e;
+	struct Entry* remove = e->next;
+	struct Entry* next = remove->next;
+	if (remove->entry_type != VALUE_ENTRY)
+		return 0;
+	prev->next = next;
+	if (next->entry_type == END_ENTRY)
+		next->next = prev;
+	return remove;
+}
+
+struct Entry* find_value(void* value, struct Queue* q)
+{
+	struct Entry* prev;
+	struct Entry* entry;
+	prev = &q->start;
+	entry = prev->next;
+	while (entry->entry_type != END_ENTRY) {
+		if (entry->value == value)
+			return prev;
+		prev = entry;
+		entry = prev->next;
+	}
+	return 0;
+}
diff --git a/kernel/lib/strings.c b/kernel/lib/strings.c
new file mode 100644
index 0000000..674af19
--- /dev/null
+++ b/kernel/lib/strings.c
@@ -0,0 +1,119 @@
+#include <lib/kmem.h>
+#include <lib/strings.h>
+
+unsigned long strlen(string_t s)
+{
+	unsigned long len = 0;
+	while (s[len] != 0) {
+		len += 1;
+	}
+	return len;
+}
+
+void strcpy(string_t src, string_t dest)
+{
+	unsigned long idx = 0;
+	while (src[idx] != 0) {
+		dest[idx] = src[idx];
+		idx++;
+	}
+	dest[idx] = src[idx];
+}
+
+unsigned char strcmp(string_t a, string_t b)
+{
+	unsigned long idx = 0;
+	while (a[idx] != 0 && b[idx] != 0) {
+		if (a[idx] != b[idx]) {
+			return 0;
+		}
+		idx += 1;
+	}
+	return a[idx] == b[idx];
+}
+
+unsigned char strcmpn(string_t a, string_t b, unsigned int n)
+{
+	unsigned long idx = 0;
+	while (a[idx] != 0 && b[idx] != 0 && idx+1 < n) {
+		if (a[idx] != b[idx]) {
+			return 0;
+		}
+		idx += 1;
+	}
+	return a[idx] == b[idx];
+}
+
+char* zhex32_to_str(unsigned long value)
+{
+	static char data[10];
+	char tmp = 0;
+	char isz = -1;
+	for (int i = 0; i < 8; i++) {
+		tmp = (value >> 4*(8-i-1))&0xF;
+		if (isz == 0xFF && tmp != 0)
+			isz = i;
+		if(tmp > 0x9)
+			tmp += 7;
+		tmp += 0x30;
+		data[i] = tmp;
+	}
+	return data+isz;
+}
+
+char* hex32_to_str(unsigned long value)
+{
+	static char data[10];
+	char tmp = 0;
+	for (int i = 0; i < 8; i++) {
+		tmp = (value >> 4*(8-i-1))&0xF;
+		if(tmp > 0x9)
+			tmp += 7;
+		tmp += 0x30;
+		data[i] = tmp;
+	}
+	return data;
+}
+
+char* u32_to_str(unsigned long value)
+{
+	unsigned long t = value;
+	unsigned long c;
+	static char data[12];
+	char* dptr = data + 9;
+	for (int i = 0; i <= 10; i++) {
+		c = t%10;
+		*dptr = 0x30 + (c&0xF);
+		t /= 10;
+		if (t==0)
+			break;
+		dptr -= 1;
+	}
+	return dptr;
+}
+
+char* s32_to_str(unsigned long value)
+{
+	long t = value;
+	unsigned long c;
+	char is_neg = 0;
+	if (t < 0) {
+		t = -t;
+		is_neg = 1;
+	}
+	static char data[13];
+	char* dptr = data + 10;
+	for (int i = 0; i <= 10; i++) {
+		c = t%10;
+		*dptr = 0x30 + (c&0xF);
+		t /= 10;
+		if (t==0)
+			break;
+		dptr -= 1;
+	}
+	if (is_neg) {
+		dptr -= 1;
+		*dptr = '-';
+	}
+	return dptr;
+}
-- 
cgit v1.2.1