Compare commits
3 Commits
e399ec6a46
...
935564c4b2
| Author | SHA1 | Date | |
|---|---|---|---|
| 935564c4b2 | |||
|
c00a247ead
|
|||
|
ccb6ca89f1
|
@@ -23,6 +23,8 @@ LD := x86_64-elf-ld
|
|||||||
$(ELFFILE): $(BUILDDIR) $(OBJFILES)
|
$(ELFFILE): $(BUILDDIR) $(OBJFILES)
|
||||||
nasm -f bin user/hello.S -o $(BUILDDIR)/hello
|
nasm -f bin user/hello.S -o $(BUILDDIR)/hello
|
||||||
nasm -f bin user/pedicel.S -o $(BUILDDIR)/pedicel
|
nasm -f bin user/pedicel.S -o $(BUILDDIR)/pedicel
|
||||||
|
tar cvf $(BUILDDIR)/initfs.tar -C $(BUILDDIR) hello pedicel
|
||||||
|
|
||||||
nasm -f elf64 src/arch/x86/idt.S -o $(BUILDDIR)/idt_stub.o
|
nasm -f elf64 src/arch/x86/idt.S -o $(BUILDDIR)/idt_stub.o
|
||||||
$(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o
|
$(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o
|
||||||
# Get the symbols for debugging
|
# Get the symbols for debugging
|
||||||
@@ -43,14 +45,15 @@ limine/limine:
|
|||||||
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1
|
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1
|
||||||
$(MAKE) -C limine
|
$(MAKE) -C limine
|
||||||
|
|
||||||
|
initfs:
|
||||||
|
|
||||||
build-iso: limine/limine $(ELFFILE)
|
build-iso: limine/limine $(ELFFILE)
|
||||||
rm -rf iso_root
|
rm -rf iso_root
|
||||||
mkdir -p iso_root/boot
|
mkdir -p iso_root/boot
|
||||||
cp -v $(ELFFILE) iso_root/boot
|
cp -v $(ELFFILE) iso_root/boot
|
||||||
mkdir -p iso_root/boot/limine
|
mkdir -p iso_root/boot/limine
|
||||||
cp -v limine.conf iso_root/boot/limine
|
cp -v limine.conf iso_root/boot/limine
|
||||||
cp $(BUILDDIR)/hello iso_root/boot/
|
cp $(BUILDDIR)/initfs.tar iso_root/boot/
|
||||||
cp $(BUILDDIR)/pedicel iso_root/boot/
|
|
||||||
mkdir -p iso_root/EFI/BOOT
|
mkdir -p iso_root/EFI/BOOT
|
||||||
cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
|
cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
|
||||||
cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/
|
cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief PS/2 Keyboard driver
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INITFS_H
|
||||||
|
#define INITFS_H
|
||||||
|
|
||||||
|
#include <limine.h>
|
||||||
|
|
||||||
|
int initfs_init(struct limine_file* tar_file);
|
||||||
|
int tar_lookup(unsigned char* archive, char* filename, char** out);
|
||||||
|
|
||||||
|
#endif
|
||||||
+4
-1
@@ -10,7 +10,8 @@
|
|||||||
#include "limine.h"
|
#include "limine.h"
|
||||||
enum ErrorCodes {
|
enum ErrorCodes {
|
||||||
ENOMEM,
|
ENOMEM,
|
||||||
EIO
|
EIO,
|
||||||
|
ENOENT
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLEAR_INTERRUPTS __asm__ volatile("cli")
|
#define CLEAR_INTERRUPTS __asm__ volatile("cli")
|
||||||
@@ -46,6 +47,8 @@ void debug_stack_trace(unsigned int max_frames);
|
|||||||
const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset);
|
const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset);
|
||||||
void boot_mem_display(void);
|
void boot_mem_display(void);
|
||||||
|
|
||||||
|
int loader_load_raw();
|
||||||
|
|
||||||
#define assert(check) do { if(!(check)) hcf(); } while(0)
|
#define assert(check) do { if(!(check)) hcf(); } while(0)
|
||||||
|
|
||||||
struct boot_context {
|
struct boot_context {
|
||||||
|
|||||||
@@ -39,5 +39,6 @@ void process_exit(void);
|
|||||||
void process_display_list(struct process* processes_list);
|
void process_display_list(struct process* processes_list);
|
||||||
|
|
||||||
void process_create_user(struct limine_file* file, char* name);
|
void process_create_user(struct limine_file* file, char* name);
|
||||||
|
void process_create_user_raw(char* file, int size, char* name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ char *strcpy(char *dest, const char *src);
|
|||||||
char *strcat(char *dest, const char *src);
|
char *strcat(char *dest, const char *src);
|
||||||
void strncpy(char* dst, const char* src, size_t n);
|
void strncpy(char* dst, const char* src, size_t n);
|
||||||
int strncmp(const char* s1, const char* s2, size_t n);
|
int strncmp(const char* s1, const char* s2, size_t n);
|
||||||
|
size_t strlen(const char* str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+1
-2
@@ -6,5 +6,4 @@ interface_branding: Welcome to the PepperOS disk!
|
|||||||
|
|
||||||
comment: Default configuration (warning: spicy)
|
comment: Default configuration (warning: spicy)
|
||||||
path: boot():/boot/pepperk
|
path: boot():/boot/pepperk
|
||||||
module_path: boot():/boot/hello
|
module_path: boot():/boot/initfs.tar
|
||||||
module_path: boot():/boot/pedicel
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Initial TAR filesystem (read-only)
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sched/process.h>
|
||||||
|
#include <limine.h>
|
||||||
|
#include <fs/initfs.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <mem/utils.h>
|
||||||
|
#include <string/string.h>
|
||||||
|
|
||||||
|
void* archive_start_addr;
|
||||||
|
uint64_t archive_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tar_oct2bin - convert octal size string to an integer
|
||||||
|
* @str: octal size string
|
||||||
|
* @size: size of string
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* $n - file size as an integer
|
||||||
|
*/
|
||||||
|
int tar_oct2bin(unsigned char* str, int size)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
unsigned char* c = str;
|
||||||
|
while (size-- > 0) {
|
||||||
|
n *= 8;
|
||||||
|
n += *c - '0';
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tar_lookup - lookup a file in the TAR file
|
||||||
|
* @archive: pointer to beginning of the archive
|
||||||
|
* @filename: file to lookup (absolute path)
|
||||||
|
* @out: where to store file data if found
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* $filesize - size of the file, if found
|
||||||
|
* $0 - file not found
|
||||||
|
*/
|
||||||
|
int tar_lookup(unsigned char* archive, char* filename, char** out)
|
||||||
|
{
|
||||||
|
unsigned char *ptr = archive;
|
||||||
|
|
||||||
|
while (!memcmp(ptr + 257, "ustar", 5)) {
|
||||||
|
int filesize = tar_oct2bin(ptr + 0x7c, 11);
|
||||||
|
if (!memcmp(ptr, filename, strlen(filename) + 1)) {
|
||||||
|
*out = (char*)(ptr + 512);
|
||||||
|
return filesize;
|
||||||
|
}
|
||||||
|
ptr += (((filesize + 511) / 512) + 1) * 512;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initfs_init - initialize the TAR initial filesystem
|
||||||
|
* @tar_file: pointer to the Limine-loaded archive
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* $0 - on success
|
||||||
|
*/
|
||||||
|
int initfs_init(struct limine_file* tar_file)
|
||||||
|
{
|
||||||
|
archive_start_addr = tar_file->address;
|
||||||
|
archive_size = tar_file->size;
|
||||||
|
|
||||||
|
DEBUG("Loaded TAR initial filesystem (initfs.tar)");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+7
-1
@@ -51,7 +51,8 @@ void pedicel_main(void* arg)
|
|||||||
"pf - trigger a page fault\r\n"
|
"pf - trigger a page fault\r\n"
|
||||||
"now - get current date\r\n"
|
"now - get current date\r\n"
|
||||||
"smash - smash the stack\r\n"
|
"smash - smash the stack\r\n"
|
||||||
"mem - get used heap info\r\n");
|
"mem - get used heap info\r\n"
|
||||||
|
"load - load an user executable\r\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +97,11 @@ void pedicel_main(void* arg)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strncmp(input_buf, "load", 4) == 0) {
|
||||||
|
loader_load_raw();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
printf("%s: command not found\r\n", input_buf);
|
printf("%s: command not found\r\n", input_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Executable loader
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <fs/initfs.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <sched/process.h>
|
||||||
|
#include <io/kbd/ps2.h>
|
||||||
|
#include <string/string.h>
|
||||||
|
|
||||||
|
extern void* archive_start_addr;
|
||||||
|
|
||||||
|
int loader_load_raw()
|
||||||
|
{
|
||||||
|
char input_buf[PEDICEL_INPUT_SIZE] = {0};
|
||||||
|
do {
|
||||||
|
printf("file> ");
|
||||||
|
keyboard_getline(input_buf, PEDICEL_INPUT_SIZE);
|
||||||
|
} while (strncmp(input_buf, "", 1) == 0);
|
||||||
|
|
||||||
|
char* data = NULL;
|
||||||
|
int sz = tar_lookup(archive_start_addr, input_buf,&data);
|
||||||
|
if (sz > 0) {
|
||||||
|
process_create_user_raw(data, sz, input_buf);
|
||||||
|
return 0; // TODO: should return something else on error
|
||||||
|
}
|
||||||
|
printf("Couldn't load file '%s'\r\n", input_buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
+5
-8
@@ -25,6 +25,7 @@
|
|||||||
#include <io/term/flanterm_backends/fb.h>
|
#include <io/term/flanterm_backends/fb.h>
|
||||||
#include <arch/x86.h>
|
#include <arch/x86.h>
|
||||||
#include <boot/boot.h>
|
#include <boot/boot.h>
|
||||||
|
#include <fs/initfs.h>
|
||||||
|
|
||||||
// Limine version used
|
// Limine version used
|
||||||
__attribute__((used, section(".limine_requests")))
|
__attribute__((used, section(".limine_requests")))
|
||||||
@@ -120,16 +121,12 @@ void kmain()
|
|||||||
idle_proc = process_create("idle", (void*)idle_main, 0);
|
idle_proc = process_create("idle", (void*)idle_main, 0);
|
||||||
|
|
||||||
if (!boot_ctx.module) {
|
if (!boot_ctx.module) {
|
||||||
panic(NULL, "could not load 'hello' executable :(");
|
panic(NULL, "could not load initfs.tar :(");
|
||||||
}
|
}
|
||||||
if (boot_ctx.module->module_count == 2) {
|
if (boot_ctx.module->module_count == 1) {
|
||||||
file = boot_ctx.module->modules[0];
|
initfs_init(boot_ctx.module->modules[0]);
|
||||||
DEBUG("file: addr=%p size=%u", file->address, file->size);
|
|
||||||
process_create_user(file, "hello");
|
|
||||||
|
|
||||||
file = boot_ctx.module->modules[1];
|
|
||||||
process_create_user(file, "pedicel");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
process_create("kshell", (void*)pedicel_main, 0);
|
process_create("kshell", (void*)pedicel_main, 0);
|
||||||
scheduler_init();
|
scheduler_init();
|
||||||
|
|
||||||
|
|||||||
+44
-4
@@ -222,10 +222,6 @@ void process_jump_to_user(uintptr_t stack_top, uintptr_t user_code)
|
|||||||
" :: "r"(stack_top), "r"(user_code));
|
" :: "r"(stack_top), "r"(user_code));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kernel stack used for interrupts from userland process.
|
|
||||||
// Should be set in TSS.RSP0 when switching to userland process.
|
|
||||||
uint8_t interrupt_stack[0x8000];
|
|
||||||
|
|
||||||
extern struct tss tss;
|
extern struct tss tss;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -276,6 +272,50 @@ void process_create_user(struct limine_file* file, char* name)
|
|||||||
memcpy((uint64_t*)code, exec_addr, exec_size);
|
memcpy((uint64_t*)code, exec_addr, exec_size);
|
||||||
load_cr3(VIRT_TO_PHYS((uint64_t)kernel_pml4));
|
load_cr3(VIRT_TO_PHYS((uint64_t)kernel_pml4));
|
||||||
|
|
||||||
|
process_add(&processes_list, proc);
|
||||||
|
DEBUG("user process '%s' (pid=%u) enqueued for scheduling", name, proc->pid);
|
||||||
|
SET_INTERRUPTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as above but for a raw data pointer (pointing to raw binary, no ELF)
|
||||||
|
void process_create_user_raw(char* file, int size, char* name)
|
||||||
|
{
|
||||||
|
CLEAR_INTERRUPTS;
|
||||||
|
struct process* proc = (struct process*)kmalloc(sizeof(struct process));
|
||||||
|
struct cpu_status* ctx = (struct cpu_status*)kmalloc(sizeof(struct cpu_status));
|
||||||
|
|
||||||
|
if (!proc || !ctx) panic(NULL, "out of memory while creating user process");
|
||||||
|
|
||||||
|
strncpy(proc->name, name, PROCESS_NAME_MAX);
|
||||||
|
memset(ctx, 0, sizeof(struct cpu_status)); // set GP registers to zero
|
||||||
|
proc->pid = next_free_pid++;
|
||||||
|
proc->status = READY;
|
||||||
|
proc->next = 0;
|
||||||
|
proc->context = ctx;
|
||||||
|
proc->context->iret_ss = USER_DATA_SEGMENT | 3;
|
||||||
|
proc->context->iret_cs = USER_CODE_SEGMENT | 3;
|
||||||
|
proc->context->iret_flags = 0x202; // Interrupt Flag set
|
||||||
|
|
||||||
|
void* exec_addr = (void*)file;
|
||||||
|
uint64_t exec_size = size;
|
||||||
|
|
||||||
|
uint64_t* user_pml4 = vmm_create_address_space();
|
||||||
|
if (!user_pml4) panic(NULL, "failed to create user address space");
|
||||||
|
proc->root_page_table = user_pml4;
|
||||||
|
|
||||||
|
uintptr_t stack_top = vmm_alloc_user_stack(user_pml4);
|
||||||
|
uint64_t code = vmm_alloc_user_code(user_pml4, exec_addr, exec_size);
|
||||||
|
|
||||||
|
proc->context->iret_rsp = stack_top;
|
||||||
|
proc->context->iret_rip = code;
|
||||||
|
proc->kernel_stack = kalloc_stack();
|
||||||
|
if (!proc->kernel_stack) panic(NULL, "failed to allocate kernel stack");
|
||||||
|
|
||||||
|
// Copy code into user pages; for that we need to temporarily switch to the user pml4
|
||||||
|
load_cr3(VIRT_TO_PHYS((uint64_t)user_pml4));
|
||||||
|
memcpy((uint64_t*)code, exec_addr, exec_size);
|
||||||
|
load_cr3(VIRT_TO_PHYS((uint64_t)kernel_pml4));
|
||||||
|
|
||||||
process_add(&processes_list, proc);
|
process_add(&processes_list, proc);
|
||||||
DEBUG("user process '%s' (pid=%u) enqueued for scheduling", name, proc->pid);
|
DEBUG("user process '%s' (pid=%u) enqueued for scheduling", name, proc->pid);
|
||||||
SET_INTERRUPTS;
|
SET_INTERRUPTS;
|
||||||
|
|||||||
@@ -98,4 +98,12 @@ int strncmp(const char* s1, const char* s2, size_t n)
|
|||||||
else {
|
else {
|
||||||
return ( *(unsigned char *)s1 - *(unsigned char *)s2 );
|
return ( *(unsigned char *)s1 - *(unsigned char *)s2 );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BSD implementation
|
||||||
|
size_t strlen(const char* str)
|
||||||
|
{
|
||||||
|
const char* s;
|
||||||
|
for (s = str; *s; ++s);
|
||||||
|
return (s - str);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user