Carlos 10 роки тому
батько
коміт
293f556a7e

+ 47 - 0
22-malloc/Makefile

@@ -0,0 +1,47 @@
+C_SOURCES = $(wildcard kernel/*.c drivers/*.c cpu/*.c libc/*.c)
+HEADERS = $(wildcard kernel/*.h drivers/*.h cpu/*.h libc/*.h)
+# Nice syntax for file extension replacement
+OBJ = ${C_SOURCES:.c=.o cpu/interrupt.o} 
+
+# Change this if your cross-compiler is somewhere else
+CC = /usr/local/i386elfgcc/bin/i386-elf-gcc
+GDB = /usr/local/i386elfgcc/bin/i386-elf-gdb
+# -g: Use debugging symbols in gcc
+CFLAGS = -g -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs \
+		 -Wall -Wextra -Werror
+
+# First rule is run by default
+os-image.bin: boot/bootsect.bin kernel.bin
+	cat $^ > os-image.bin
+
+# '--oformat binary' deletes all symbols as a collateral, so we don't need
+# to 'strip' them manually on this case
+kernel.bin: boot/kernel_entry.o ${OBJ}
+	i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary
+
+# Used for debugging purposes
+kernel.elf: boot/kernel_entry.o ${OBJ}
+	i386-elf-ld -o $@ -Ttext 0x1000 $^ 
+
+run: os-image.bin
+	qemu-system-i386 -fda os-image.bin
+
+# Open the connection to qemu and load our kernel-object file with symbols
+debug: os-image.bin kernel.elf
+	qemu-system-i386 -s -fda os-image.bin -d guest_errors,int &
+	${GDB} -ex "target remote localhost:1234" -ex "symbol-file kernel.elf"
+
+# Generic rules for wildcards
+# To make an object, always compile from its .c
+%.o: %.c ${HEADERS}
+	${CC} ${CFLAGS} -ffreestanding -c $< -o $@
+
+%.o: %.asm
+	nasm $< -f elf -o $@
+
+%.bin: %.asm
+	nasm $< -f bin -o $@
+
+clean:
+	rm -rf *.bin *.dis *.o os-image.bin *.elf
+	rm -rf kernel/*.o boot/*.bin drivers/*.o boot/*.o cpu/*.o libc/*.o

+ 18 - 0
22-malloc/README.md

@@ -0,0 +1,18 @@
+*Concepts you may want to Google beforehand: malloc*
+
+**Goal: Implement a memory allocator**
+
+We will add a kernel memory allocator to `libc/mem.c`. It is 
+implemented as a simple pointer to free memory, which keeps
+growing.
+
+The `kmalloc()` function can be used to request an aligned page,
+and it will also return the real, physical address, for later use.
+
+We'll change the `kernel.c` leaving all the "shell" code there,
+Let's just try out the new `kmalloc()`, and check out that
+our first page starts at 0x10000 (as hardcoded on `mem.c`) and
+subsequent `kmalloc()`'s produce a new address which is
+aligned 4096 bytes or 0x1000 from the previous one.
+
+The rest of the files are unchanged from last lesson.

+ 1 - 0
22-malloc/boot

@@ -0,0 +1 @@
+../21-shell/boot

+ 1 - 0
22-malloc/cpu

@@ -0,0 +1 @@
+../21-shell/cpu

+ 1 - 0
22-malloc/drivers

@@ -0,0 +1 @@
+../21-shell/drivers

+ 36 - 0
22-malloc/kernel/kernel.c

@@ -0,0 +1,36 @@
+#include "../cpu/isr.h"
+#include "../drivers/screen.h"
+#include "kernel.h"
+#include "../libc/string.h"
+#include "../libc/mem.h"
+
+void main() {
+    isr_install();
+    irq_install();
+
+    kprint("Type something, it will go through the kernel\n"
+        "Type END to halt the CPU or PAGE to request a kmalloc()\n> ");
+}
+
+void user_input(char *input) {
+    if (strcmp(input, "END") == 0) {
+        kprint("Stopping the CPU. Bye!\n");
+        asm volatile("hlt");
+    } else if (strcmp(input, "PAGE") == 0) {
+        /* Lesson 22: Code to test kmalloc, the rest is unchanged */
+        u32 phys_addr;
+        u32 page = kmalloc(1000, 1, &phys_addr);
+        char page_str[16];
+        int_to_ascii(page, page_str);
+        char phys_str[16];
+        int_to_ascii(phys_addr, phys_str);
+        kprint("Page: ");
+        kprint(page_str);
+        kprint(", physical address: ");
+        kprint(phys_str);
+        kprint("\n");
+    }
+    kprint("You said: ");
+    kprint(input);
+    kprint("\n> ");
+}

+ 6 - 0
22-malloc/kernel/kernel.h

@@ -0,0 +1,6 @@
+#ifndef KERNEL_H
+#define KERNEL_H
+
+void user_input(char *input);
+
+#endif

+ 1 - 0
22-malloc/libc/function.h

@@ -0,0 +1 @@
+../../21-shell/libc/function.h

+ 33 - 0
22-malloc/libc/mem.c

@@ -0,0 +1,33 @@
+#include "mem.h"
+
+void memory_copy(u8 *source, u8 *dest, int nbytes) {
+    int i;
+    for (i = 0; i < nbytes; i++) {
+        *(dest + i) = *(source + i);
+    }
+}
+
+void memory_set(u8 *dest, u8 val, u32 len) {
+    u8 *temp = (u8 *)dest;
+    for ( ; len != 0; len--) *temp++ = val;
+}
+
+/* This should be computed at link time, but a hardcoded
+ * value is fine for now. Remember that our kernel starts
+ * at 0x1000 as defined on the Makefile */
+u32 free_mem_addr = 0x10000;
+/* Implementation is just a pointer to some free memory which
+ * keeps growing */
+u32 kmalloc(u32 size, int align, u32 *phys_addr) {
+    /* Pages are aligned to 4K, or 0x1000 */
+    if (align == 1 && (free_mem_addr & 0xFFFFF000)) {
+        free_mem_addr &= 0xFFFFF000;
+        free_mem_addr += 0x1000;
+    }
+    /* Save also the physical address */
+    if (phys_addr) *phys_addr = free_mem_addr;
+
+    u32 ret = free_mem_addr;
+    free_mem_addr += size; /* Remember to increment the pointer */
+    return ret;
+}

+ 12 - 0
22-malloc/libc/mem.h

@@ -0,0 +1,12 @@
+#ifndef MEM_H
+#define MEM_H
+
+#include "../cpu/types.h"
+
+void memory_copy(u8 *source, u8 *dest, int nbytes);
+void memory_set(u8 *dest, u8 val, u32 len);
+
+/* At this stage there is no 'free' implemented. */
+u32 kmalloc(u32 size, int align, u32 *phys_addr);
+
+#endif

+ 1 - 0
22-malloc/libc/string.c

@@ -0,0 +1 @@
+../../21-shell/libc/string.c

+ 1 - 0
22-malloc/libc/string.h

@@ -0,0 +1 @@
+../../21-shell/libc/string.h