summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-07-07 20:19:23 +1000
committerJake Mannens <jake72360@gmail.com>2018-07-07 20:19:23 +1000
commitec4f58e8e362e371718f656923c2d234f8ac215c (patch)
treeb84655b06de314c13007382b53a0f624cef2df6b
parentfbbcb04f9e3197976d6ab4a79c45aa0a84e39aba (diff)
Added '-g' flag for GCC to all makefiles to ensure debugging information
is produced. This may change later. Added the new directory 'lib' to the source tree which build lib.a, an archive containing common library routines for both the kernel and userspace code to use. Added the file string.c to the lib directory (as well as the appropriate headers in /include) which provides some basic functions from the standard C string library. Added a physical memory manager which is now located in memory.c. This memory manager tracks free pages from 1MB-8MB with a simple table and allocates memory in blocks of 4KB pages. Multiple pages can be allocated in which they are returned as a linked list. Added a 'page window' in memory.c which allows the temporary mapping of a single page at a time into the current address space. Moved all paging routines that were previously located in page.s over to memory.c where they have been re-implemented as a mixture of C and inline assembly. Moved the primative userspace routines from usrspace.s over to the new sched.c. The only remaining routine, usrcall is now located in asm.s as 'switch_to' which takes two arguments, pointers to the task structure and task state structure of the new task which is being switched to. Pages for userspace are now allocated dynamically. The user binary is loaded in at 1GB upwards. The user stack is located at the end of the 4GB address space with the lower 1GB being reserved for the kernel. Updated the link.ld file for the userspace binary to include the new starting address 0x40000000 (1GB). Renamed the symbols for the user binary blob to make them shorter.
-rw-r--r--Makefile5
-rw-r--r--include/asm/io.h4
-rw-r--r--include/asm/system.h3
-rw-r--r--include/kernel/memory.h18
-rw-r--r--include/kernel/sched.h26
-rw-r--r--include/string.h37
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/asm.s60
-rw-r--r--kernel/boot.s4
-rw-r--r--kernel/kmain.c5
-rw-r--r--kernel/memory.c129
-rw-r--r--kernel/page.s55
-rw-r--r--kernel/sched.c131
-rw-r--r--kernel/usrspace.s45
-rw-r--r--lib/Makefile29
-rw-r--r--lib/string.c173
-rw-r--r--usrbin/Makefile7
-rw-r--r--usrbin/link.ld2
18 files changed, 625 insertions, 110 deletions
diff --git a/Makefile b/Makefile
index c45c277..c29b673 100644
--- a/Makefile
+++ b/Makefile
@@ -10,15 +10,18 @@ build: $(TARGET)
$(TARGET): .FORCE
$(MAKE) -C kernel
+ $(MAKE) -C lib
$(MAKE) -C usrbin
- $(LD) -o $(TARGET) kernel/kernel.o usrbin/usrbin_blob.o
+ $(LD) -o $(TARGET) kernel/kernel.o usrbin/usrbin_blob.o lib/lib.a
clean:
$(MAKE) -C kernel clean
+ $(MAKE) -C lib clean
$(MAKE) -C usrbin clean
rm -f $(TARGET)
run: $(TARGET)
qemu-system-x86_64 -s -kernel $(TARGET)
+ # qemu-system-x86_64 -s -S -kernel $(TARGET)
.FORCE:
diff --git a/include/asm/io.h b/include/asm/io.h
index 6ca5bbc..1c2e5bc 100644
--- a/include/asm/io.h
+++ b/include/asm/io.h
@@ -6,9 +6,9 @@
#define inb(port) ({ \
unsigned char _val; \
- asm volatile ("inb %%dx, %%al" : "=a" (_val) : "d" (port)); \
+ __asm__ volatile ("inb %%dx, %%al" : "=a" (_val) : "d" (port)); \
_val; \
})
#define outb(port, val) \
- asm volatile ("outb %%al, %%dx" : : "d" (port), "a" (val));
+ __asm__ volatile ("outb %%al, %%dx" : : "d" (port), "a" (val));
diff --git a/include/asm/system.h b/include/asm/system.h
new file mode 100644
index 0000000..02c2f62
--- /dev/null
+++ b/include/asm/system.h
@@ -0,0 +1,3 @@
+#include <kernel/sched.h>
+
+volatile void switch_to(struct task_struct*, struct task_state*);
diff --git a/include/kernel/memory.h b/include/kernel/memory.h
new file mode 100644
index 0000000..7217427
--- /dev/null
+++ b/include/kernel/memory.h
@@ -0,0 +1,18 @@
+#include <stdint.h>
+
+#define PGENT 1024
+
+typedef uint32_t pte_t;
+typedef uint32_t __attribute__((aligned (4096))) ptab_t[PGENT];
+typedef uint32_t pde_t;
+typedef uint32_t __attribute__((aligned (4096))) pdir_t[PGENT];
+
+extern ptab_t ktab;
+
+void *alloc_physical_page(void);
+int free_physical_page(void*);
+void *alloc_physical_pages(unsigned int);
+
+void *map_page(void*);
+
+void paging_init(void);
diff --git a/include/kernel/sched.h b/include/kernel/sched.h
new file mode 100644
index 0000000..fa8e036
--- /dev/null
+++ b/include/kernel/sched.h
@@ -0,0 +1,26 @@
+#ifndef _SCHED_H
+#define _SCHED_H
+
+#include <stdint.h>
+
+struct task_state {
+ uint32_t ss;
+ uint32_t esp;
+ uint32_t eflags;
+ uint32_t cs;
+ uint32_t eip;
+ uint32_t eax;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t ebx;
+ uint32_t esp_garbage;
+ uint32_t ebp;
+ uint32_t esi;
+ uint32_t edi;
+} __attribute__((packed));
+
+struct task_struct {
+ struct task_state state;
+} __attribute__((packed));
+
+#endif
diff --git a/include/string.h b/include/string.h
new file mode 100644
index 0000000..72c2b2e
--- /dev/null
+++ b/include/string.h
@@ -0,0 +1,37 @@
+#ifndef STRING_H
+#define STRING_H
+
+#include <stdint.h>
+
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef uint32_t size_t;
+#endif
+
+void* memchr(const void*, int, size_t);
+int memcmp(const void*, const void*, size_t);
+void* memcpy(void*, const void*, size_t);
+void* memmove(void*, const void*, size_t);
+void* memset(void*, int, size_t);
+
+size_t strlen(const char*);
+char* strcat(char*, const char*);
+char* strncat(char*, const char*, size_t);
+char* strchr(const char*, int);
+char* strrchr(char*, int);
+int strcmp(const char*, const char*);
+int strncmp(const char*, const char*, size_t);
+char* strcpy(char*, const char*);
+char* strncpy(char*, const char*, size_t);
+size_t strcspn(const char*, const char*);
+size_t strspn(const char*, const char*);
+char* strpbrk(const char*, const char*);
+char* strstr(const char*, const char*);
+char* strtok(char*, const char*);
+size_t strxfrm(char*, const char*, size_t);
+
+#endif
diff --git a/kernel/Makefile b/kernel/Makefile
index c6cf24e..29b5566 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -4,7 +4,7 @@ SRCS = $(wildcard *.c)
ASMS = $(wildcard *.s)
OBJS = $(SRCS:.c=.o) $(ASMS:.s=.o)
-CFLAGS = -m32 -I../include -ffreestanding -nostdinc -nostdlib -fno-stack-protector -fno-pie -gstabs+
+CFLAGS = -m32 -I../include -ffreestanding -nostdinc -nostdlib -fno-stack-protector -fno-pie -gstabs+ -g
LDFLAGS = -m elf_i386 -r
ASMFLAGS = -f elf32
diff --git a/kernel/asm.s b/kernel/asm.s
new file mode 100644
index 0000000..4abe607
--- /dev/null
+++ b/kernel/asm.s
@@ -0,0 +1,60 @@
+global switch_to
+extern ctask
+extern tss
+
+switch_to:
+ push ebp
+ mov ebp, esp
+ mov eax, [ebp+8]
+ mov [ctask], eax
+ mov esi, [ebp+12]
+ mov ecx, 13
+.loop:
+ lodsd
+ push eax
+ dec ecx
+ jz .end
+ jmp .loop
+.end:
+ mov ax, 0x23
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ popa
+ iret
+
+; uint32_t ss;
+; uint32_t esp;
+; uint32_t eflags;
+; uint32_t cs;
+; uint32_t eip;
+; uint32_t eax;
+; uint32_t ecx;
+; uint32_t edx;
+; uint32_t ebx;
+; uint32_t esp_garbage;
+; uint32_t ebp;
+; uint32_t esi;
+; uint32_t edi;
+
+; switch_to:
+ ; push ebp
+ ; mov ebp, esp
+ ; cli
+ ; mov ax, 0x23
+ ; mov ds, ax
+ ; mov es, ax
+ ; mov fs, ax
+ ; mov gs, ax
+ ; mov eax, esp
+ ; ; save ESP in the TSS
+ ; mov [tss+4], eax
+ ; push dword 0x23
+ ; push dword 0x00180000
+ ; pushf
+ ; push dword 0x1B
+ ; push dword 0x00100000
+ ; iret
+ ; pop ebp
+ ; ret
diff --git a/kernel/boot.s b/kernel/boot.s
index 80f8be9..9d948cf 100644
--- a/kernel/boot.s
+++ b/kernel/boot.s
@@ -22,6 +22,8 @@ section .text
kboot:
cli
; put the stack pointer near the end of conventional memory
+ ; WARNING: don't change this without changing the corresponding
+ ; entry in the TSS
mov esp, 0x80000
; setup descriptor tables
call flush_gdt
@@ -37,7 +39,7 @@ kboot:
tss:
dd 0
- dd 0 ; kernel stack pointer
+ dd 0x80000 ; kernel stack pointer
dd 0x10 ; kernel stack segment
times 60 db 0
dd 0x13 ; ES segment
diff --git a/kernel/kmain.c b/kernel/kmain.c
index ece7012..558df42 100644
--- a/kernel/kmain.c
+++ b/kernel/kmain.c
@@ -1,12 +1,13 @@
#include <kernel/con.h>
+#include <kernel/memory.h>
#include <kernel/sys.h>
#include <stdint.h>
#include <sys/types.h>
-uint32_t ticks = 0;
-
extern void userspace_init(void);
+uint32_t ticks = 0;
+
void kmain(void) {
con_init();
diff --git a/kernel/memory.c b/kernel/memory.c
new file mode 100644
index 0000000..465b44f
--- /dev/null
+++ b/kernel/memory.c
@@ -0,0 +1,129 @@
+#include <kernel/memory.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+static char __attribute__((aligned (4096))) mapped_page[4096];
+
+static pdir_t kpdir;
+
+ptab_t ktab;
+
+static ptab_t flow;
+static ptab_t fupp;
+
+void *alloc_physical_page(void) {
+ int i;
+ void *ret;
+
+ for(i = 0; i < PGENT; i++) {
+ if(flow[i] & 1) {
+ ret = (void*) (flow[i] & ~1);
+ flow[i] = 0;
+ return ret;
+ }
+
+ if(fupp[i] & 1) {
+ ret = (void*) (fupp[i] & ~1);
+ fupp[i] = 0;
+ return ret;
+ }
+ }
+
+ return NULL;
+}
+
+int free_physical_page(void *page) {
+ int i;
+ page = (void*) ((uint32_t) page & ~0xFFF);
+
+ for(int i = 0; i < PGENT; i++) {
+ if(!(flow[i] & 1)) {
+ flow[i] = (uint32_t) page | 1;
+ return 0;
+ }
+
+ if(!(fupp[i] & 1)) {
+ fupp[i] = (uint32_t) page | 1;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+void *alloc_physical_pages(unsigned int n) {
+ void *p = NULL;
+ void *last = NULL;
+ void **page;
+
+ while(n--) {
+ p = alloc_physical_page();
+ if(p == NULL) {
+ page = &last;
+ while(*page) {
+ free_physical_page(*page);
+ page = *page;
+ }
+ return NULL;
+ }
+
+ map_page(p);
+ *((void**) mapped_page) = last;
+ last = p;
+ }
+
+ return p;
+}
+
+void *map_page(void *page) {
+ uint32_t p = (uint32_t) mapped_page;
+
+ /* enforce 4KB page alignment */
+ page = (void*) ((uint32_t) page & ~0xFFF);
+
+ ktab[(p >> 12) & 0x3FF] = (uint32_t) page | 0x003;
+ /*
+ * invalidate any cached entries for
+ * the mapped page window.
+ */
+ __asm__ ("invlpg %0" :: "m" (mapped_page));
+
+ return mapped_page;
+}
+
+void paging_init(void) {
+ int i;
+
+ /* empty the page directory */
+ for(i = 0; i < PGENT; i++)
+ kpdir[i] = 0;
+
+ /* populate the free page tables */
+ for(i = 0; i < PGENT; i++) {
+ /* populate the lower table */
+ flow[i] = (i << 12);
+ /* only pages >1MB can be allocated */
+ if(i >= 0x100)
+ flow[i] |= 0x001;
+ /* populate the upper table */
+ fupp[i] = ((i << 12) + 0x400000) | 0x001;
+ }
+
+ /* populate the kernel's page table */
+ for(i = 0; i < PGENT; i++) {
+ ktab[i] = 0;
+ if(i < 256)
+ ktab[i] = (i << 12) | 0x003;
+ }
+
+ /* populate the kernel's page directory */
+ kpdir[0] = ((pde_t) ktab) | 0x007;
+
+ __asm__ (
+ "mov %%eax, %%cr3\n"
+ "mov %%cr0, %%eax\n"
+ "or $0x80000000, %%eax\n"
+ "mov %%eax, %%cr0\n"
+ :: "a" (&kpdir)
+ :);
+}
diff --git a/kernel/page.s b/kernel/page.s
deleted file mode 100644
index 4e40822..0000000
--- a/kernel/page.s
+++ /dev/null
@@ -1,55 +0,0 @@
-global paging_init
-
-align 4096
-page_dir:
- times 4096 db 0
-
-align 4096
-page_tables:
- ; two page tables
- times 4096 db 0
- times 4096 db 0
-.end:
-
-; here, we initialize paging. since the IDT
-; has yet to be populated, we must take extra
-; care as we can't afford to trigger a page
-; fault.
-paging_init:
- push ebp
- mov ebp, esp
- push ebx
- ; populate the page directory
- mov eax, page_tables
- or eax, 0x007
- mov [page_dir], eax
- mov eax, (page_tables+4096)
- or eax, 0x007
- mov [page_dir+4], eax
- ; populate the page tables
- mov ebx, page_tables
- mov ecx, ((page_tables.end-page_tables)/4)
- mov edx, 0
-.loop:
- mov eax, edx
- or eax, 0x003
- cmp edx, 0x100000
- jb .skip
- or eax, 0x004
-.skip:
- mov [ebx], eax
- dec ecx
- jz .end
- add ebx, 4
- add edx, 4096
- jmp .loop
-.end:
- ; load the page directory and enable paging
- mov eax, page_dir
- mov cr3, eax
- mov eax, cr0
- or eax, 0x80000000
- mov cr0, eax
- pop ebx
- pop ebp
- ret
diff --git a/kernel/sched.c b/kernel/sched.c
new file mode 100644
index 0000000..f0b79fc
--- /dev/null
+++ b/kernel/sched.c
@@ -0,0 +1,131 @@
+#include <asm/system.h>
+#include <kernel/con.h>
+#include <kernel/memory.h>
+#include <kernel/sched.h>
+#include <string.h>
+#include <sys/types.h>
+
+#define USRSTART ((void*) 0x40000000)
+
+#define pages(n) \
+ ((n / 4096) + 1)
+
+#define tables(n) \
+ ((n / 1024) + 1)
+
+#define getpage(name, p) ({\
+ void **_next; \
+ _next = map_page(p); \
+ name = p; \
+ p = *_next; \
+ })
+
+extern char _usrbin_start;
+extern char _usrbin_size;
+
+struct task_struct *ctask;
+
+static struct task_struct task;
+
+static inline void empty_table(void *t) {
+ int i;
+
+ for(i = 0; i < PGENT; i++)
+ ((uint32_t*) t)[i] = 0;
+}
+
+void userspace_init(void) {
+ int i, j;
+ int c;
+ size_t totpages, npages, ntables;
+ void *p, *page, *tab, *map;
+ void *pdir, *stackt, *stackp;
+
+ size_t usrsize = (size_t) &_usrbin_size;
+
+ npages = pages(usrsize);
+ ntables = tables(pages(usrsize));
+ totpages = npages + ntables + 3;
+
+ /* here we allocate pages to setup the process'
+ * address space. in addition to the pages that
+ * will hold the binary image, the following
+ * pages are allocated:
+ * - page directory (1 page)
+ * - page tables
+ * - stack page (1 page)
+ * - stack table (1 page)
+ */
+ p = alloc_physical_pages(totpages);
+ printf("Allocating %x pages for userspace process\n", totpages);
+ if(p == NULL) {
+ printf("Failed to allocate memory for userspace!\n");
+ return;
+ }
+
+ getpage(pdir, p);
+ getpage(stackt, p);
+ getpage(stackp, p);
+ printf(" Page directory: 0x%08x\n", (uint32_t) pdir);
+ printf(" Stack table: 0x%08x\n", (uint32_t) stackt);
+ printf(" Stack page: 0x%08x\n", (uint32_t) stackp);
+ printf(" Page tables:\n");
+
+ /* populate the page directory */
+ c = npages;
+ map = map_page(pdir);
+ empty_table(map);
+ for(i = 0; i < ntables; i++) {
+ /* add the table entry to the directory */
+ getpage(tab, p);
+ printf(" 0x%08x\n", (uint32_t) tab);
+ map = map_page(pdir);
+ ((uint32_t*) map)[i + (PGENT / 4)] = (uint32_t) tab | 0x007;
+
+ /* populate the page table */
+ map = map_page(tab);
+ for(j = 0; j < PGENT; j++) {
+ ((uint32_t*) map)[j] = 0;
+ if(c <= 0)
+ continue;
+
+ getpage(page, p);
+ map = map_page(tab);
+ ((uint32_t*) map)[j] = (uint32_t) page | 0x007;
+ c--;
+ }
+ }
+
+ /* populate the stack table */
+ map = map_page(stackt);
+ empty_table(map);
+ ((uint32_t*) map)[PGENT - 1] = (uint32_t) stackp | 0x007;
+
+ /* add the stack page table to the directory */
+ map = map_page(pdir);
+ ((uint32_t*) map)[PGENT - 1] = (uint32_t) stackt | 0x007;
+ /* add the kernel's page table to the directory */
+ ((uint32_t*) map)[0] = (uint32_t) ktab | 0x003;
+
+ __asm__ volatile ("mov %%eax, %%cr3" :: "a" (pdir));
+
+ memcpy(USRSTART, &_usrbin_start, usrsize);
+
+ /*
+ * here we initialize the task struct.
+ * currently, we only setup state information
+ * necessary to begin execution.
+ */
+ memset(&task, 0, sizeof(task));
+ task.state.cs = 0x1B;
+ task.state.ss = 0x23;
+ task.state.eip = (uint32_t) USRSTART;
+ task.state.esp = 0xFFFFFFFF;
+ __asm__ (
+ "pushf\n" \
+ "pop %%eax" \
+ : "=a" (task.state.eflags) \
+ ::);
+
+ switch_to(&task, &task.state);
+}
diff --git a/kernel/usrspace.s b/kernel/usrspace.s
deleted file mode 100644
index 1d20f71..0000000
--- a/kernel/usrspace.s
+++ /dev/null
@@ -1,45 +0,0 @@
-global userspace_init
-extern _binary_usrbin_bin_size
-extern _binary_usrbin_bin_start
-extern tss
-
-userspace_init:
- push ebp
- mov ebp, esp
- push esi
- push edi
- mov ecx, _binary_usrbin_bin_size
- mov esi, _binary_usrbin_bin_start
- mov edi, 0x100000
-.loop:
- movsb
- dec ecx
- jz .end
- jmp .loop
-.end:
- pop edi
- pop esi
- call usrcall
- pop ebp
- ret
-
-usrcall:
- push ebp
- mov ebp, esp
- cli
- mov ax, 0x23
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov eax, esp
- ; save ESP in the TSS
- mov [tss+4], eax
- push dword 0x23
- push dword 0x00180000
- pushf
- push dword 0x1B
- push dword 0x00100000
- iret
- pop ebp
- ret
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..13c92f2
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,29 @@
+TARGET = lib.a
+
+SRCS = $(wildcard *.c)
+ASMS = $(wildcard *.s)
+OBJS = $(SRCS:.c=.o) $(ASMS:.s=.o)
+
+CFLAGS = -m32 -I../include -ffreestanding -nostdinc -nostdlib -fno-stack-protector -fno-pie -gstabs+ -g
+ASMFLAGS = -f elf32
+
+AR = ar
+CC = gcc $(CFLAGS)
+ASM = nasm $(ASMFLAGS)
+
+all: build
+
+build: $(TARGET)
+
+.s.o:
+ $(ASM) -o $*.o $^
+
+.c.o:
+ $(CC) -c -o $*.o $^
+
+$(TARGET): $(OBJS)
+ $(AR) rc $(TARGET) $(OBJS)
+
+clean:
+ rm -f $(OBJS)
+ rm -f $(TARGET)
diff --git a/lib/string.c b/lib/string.c
new file mode 100644
index 0000000..0e8fbeb
--- /dev/null
+++ b/lib/string.c
@@ -0,0 +1,173 @@
+#include <string.h>
+
+void* memchr(const void* s, int c, size_t n) {
+ unsigned char *p = (unsigned char*) s;
+ while(n--) {
+ if(*p != (unsigned char) c) {
+ p++;
+ } else {
+ return p;
+ }
+ }
+ return 0;
+}
+
+int memcmp(const void* s1, const void* s2, size_t n) {
+ const unsigned char* p1 = (const unsigned char*) s1;
+ const unsigned char* p2 = (const unsigned char*) s2;
+ while(n--) {
+ if(*p1 != *p2) {
+ return *p1 - *p2;
+ } else {
+ p1++, p2++;
+ }
+ }
+ return 0;
+}
+
+void* memcpy(void* dest, const void* src, size_t n) {
+ char *dp = (char*) dest;
+ const char *sp = (const char*) src;
+ while(n--) *dp++ = *sp++;
+ return dest;
+}
+
+void* memmove(void* dest, const void* src, size_t n) {
+ unsigned char tmp[n];
+ memcpy(tmp, src, n);
+ memcpy(dest, tmp, n);
+ return dest;
+}
+
+void* memset(void* s, int c, size_t n) {
+ unsigned char* p = (unsigned char*) s;
+ while(n--) *p++ = (unsigned char) c;
+ return s;
+}
+
+size_t strlen(const char* str) {
+ const char* s;
+ for(s = str; *s; ++s) {}
+ return (s - str);
+}
+
+char* strcat(char* dest, const char* src) {
+ size_t dest_len = strlen(dest);
+ size_t i;
+
+ for(i = 0; src[i] != '\0'; i++) {
+ dest[dest_len + i] = src[i];
+ }
+ dest[dest_len + i] = '\0';
+ return dest;
+}
+
+char* strncat(char* dest, const char* src, size_t n) {
+ size_t dest_len = strlen(dest);
+ size_t i;
+
+ for(i = 0; i < n && src[i] != '\0'; i++) {
+ dest[dest_len + i] = src[i];
+ }
+ dest[dest_len + i] = '\0';
+ return dest;
+}
+
+char* strchr(const char* s, int c) {
+ while(*s != (char) c) {
+ if(!*s++) return 0;
+ }
+ return (char*) s;
+}
+
+char* strrchr(char* s, int c) {
+ char* ret = 0;
+ do {
+ if(*s == (char) c) ret = s;
+ } while(*s++);
+ return ret;
+}
+
+int strcmp(const char* s1, const char* s2) {
+ while(*s1 && (*s1 == *s2)) s1++, s2++;
+ return *(const unsigned char*) s1 - *(const unsigned char*) s2;
+}
+
+int strncmp(const char* s1, const char* s2, size_t n) {
+ while(n--) {
+ if(*s1++ != *s2++) {
+ return *(unsigned char*) (s1 - 1) - *(unsigned char*) (s2 - 1);
+ }
+ }
+ return 0;
+}
+
+char* strcpy(char* dest, const char* src) {
+ char* ret = dest;
+ while(*dest++ = *src++);
+ return ret;
+}
+
+char* strncpy(char* dest, const char* src, size_t n) {
+ char* ret = dest;
+ do {
+ if(!n--) return ret;
+ } while (*dest++ = *src++);
+ while(n--) *dest++ = 0;
+ return ret;
+}
+
+size_t strcspn(const char* s1, const char* s2) {
+ size_t ret = 0;
+ while(*s1) {
+ if(strchr(s2, *s1)) {
+ return ret;
+ } else {
+ s1++, ret++;
+ }
+ }
+ return ret;
+}
+
+size_t strspn(const char* s1, const char* s2) {
+ size_t ret = 0;
+ while(*s1 && strchr(s2, *s1++)) ret++;
+ return ret;
+}
+
+char* strpbrk(const char* s1, const char* s2) {
+ while(*s1) {
+ if(strchr(s2, *s1++)) return (char*) --s1;
+ }
+ return 0;
+}
+
+char* strstr(const char* s1, const char* s2) {
+ size_t n = strlen(s2);
+ while(*s1) {
+ if(!memcmp(s1++, s2, n)) {
+ return (char*) (s1 - 1);
+ }
+ }
+ return 0;
+}
+
+char* strtok(char* str, const char* delim) {
+ static char* p = 0;
+ if(str) {
+ p = str;
+ } else if(!p) {
+ return 0;
+ }
+ str = p + strspn(p, delim);
+ p = str + strcspn(str, delim);
+ if(p == str) return p = 0;
+ p = *p ? *p = 0, p + 1 : 0;
+ return str;
+}
+
+size_t strxfrm(char* dest, const char* src, size_t n) {
+ size_t n2 = strlen(src);
+ if(n > n2) strcpy(dest, src);
+ return n2;
+}
diff --git a/usrbin/Makefile b/usrbin/Makefile
index 16a607f..9a40cbc 100644
--- a/usrbin/Makefile
+++ b/usrbin/Makefile
@@ -4,7 +4,7 @@ SRCS = $(wildcard *.c)
ASMS = $(wildcard *.s)
OBJS = $(SRCS:.c=.o) $(ASMS:.s=.o)
-CFLAGS = -m32 -I../include -ffreestanding -nostdinc -nostdlib -fno-stack-protector -fno-pie
+CFLAGS = -m32 -I../include -ffreestanding -nostdinc -nostdlib -fno-stack-protector -fno-pie -g
LDFLAGS = -m elf_i386 -T link.ld
ASMFLAGS = -f elf32
@@ -24,7 +24,10 @@ build: $(TARGET)
$(TARGET): $(OBJS)
$(LD) -o usrbin.bin $(OBJS)
- objcopy -I binary -O elf32-i386 -B i386 usrbin.bin $(TARGET)
+ objcopy -I binary -O elf32-i386 -B i386 usrbin.bin $(TARGET) \
+ --redefine-sym _binary_usrbin_bin_start=_usrbin_start \
+ --redefine-sym _binary_usrbin_bin_end=_usrbin_end \
+ --redefine-sym _binary_usrbin_bin_size=_usrbin_size
clean:
rm -f usrbin.bin
diff --git a/usrbin/link.ld b/usrbin/link.ld
index c1a7a42..57edac9 100644
--- a/usrbin/link.ld
+++ b/usrbin/link.ld
@@ -1,7 +1,7 @@
OUTPUT_FORMAT(binary)
SECTIONS
{
- . = 0x100000;
+ . = 0x40000000;
.text : { *(.entry); .*(.text) }
.data : { *(.data) }
.bss : { *(.bss) }