Hello user process

This commit is contained in:
2025-09-01 23:22:47 +02:00
parent 13ab117b1b
commit 2015e0e0aa
28 changed files with 744 additions and 65 deletions

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
/limine /limine
/iso_root /iso_root
/base_root
*.iso *.iso
*.img *.img

View File

@ -1,7 +1,10 @@
.PHONY: all clean prepare cleanall iso base .PHONY: clean prepare cleanall iso base kernel user
all: kernel:
make -C kernel all make -C kernel ROOT=$(PWD) all
user:
make -C user ROOT=$(PWD) all
prepare: prepare:
if [ ! -d limine ]; then \ if [ ! -d limine ]; then \
@ -13,10 +16,10 @@ prepare:
cleanall: cleanall:
make clean make clean
rm -rf limine rm -rf limine
rm -rf littlefs-fuse
clean: clean:
make -C kernel clean make -C kernel clean
make -C user clean
rm -f mop2.iso base.img rm -f mop2.iso base.img
base: base:

3
base/bin/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*
!.gitignore
!.gitkeep

0
base/bin/.gitkeep Normal file
View File

View File

@ -29,7 +29,7 @@ endif
include arch/$(ARCH)/$(ARCH).mk include arch/$(ARCH)/$(ARCH).mk
include extconf/extra.mk include extconf/extra.mk
LDFLAGS := -nostdlib -static -T arch/$(ARCH)/link.ld $(shell $(CC) -print-libgcc-file-name) LDFLAGS += -nostdlib -static -T arch/$(ARCH)/link.ld $(shell $(CC) -print-libgcc-file-name)
SRCFILES := $(wildcard *.c) \ SRCFILES := $(wildcard *.c) \
$(wildcard printf/*.c) \ $(wildcard printf/*.c) \

355
kernel/elf.h Normal file
View File

@ -0,0 +1,355 @@
#ifndef ELF_H_
#define ELF_H_
#include <stdint.h>
#define ELFCLASS64 2
#define ELFDATA2LSB 1
#define ELFOSABI_SYSV 0
#define EM_X86_64 62
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOBITS 8
#define SHT_DYNSYM 11
#define SHF_WRITE 1
#define SHF_ALLOC 2
#define SHF_EXECINSTR 4
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
typedef uint16_t Elf64_Half;
typedef uint32_t Elf64_Word;
typedef int32_t Elf64_Sword;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
typedef uint32_t Elf32_Addr;
typedef uint32_t Elf32_Off;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Word;
typedef int32_t Elf32_Sword;
typedef uint64_t Elf32_Xword;
typedef int64_t Elf32_Sxword;
#define EI_NIDENT (16)
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* ELF identification */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Machine type */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point address */
Elf32_Off e_phoff; /* Program header offset */
Elf32_Off e_shoff; /* Section header offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size */
Elf32_Half e_phentsize; /* Size of program header entry */
Elf32_Half e_phnum; /* Number of program header entries */
Elf32_Half e_shentsize; /* Size of section header entry */
Elf32_Half e_shnum; /* Number of section header entries */
Elf32_Half e_shstrndx; /* Section name string table index */
} Elf32_Ehdr;
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* ELF identification */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Machine type */
Elf64_Word e_version; /* Object file version */
Elf64_Addr e_entry; /* Entry point address */
Elf64_Off e_phoff; /* Program header offset */
Elf64_Off e_shoff; /* Section header offset */
Elf64_Word e_flags; /* Processor-specific flags */
Elf64_Half e_ehsize; /* ELF header size */
Elf64_Half e_phentsize; /* Size of program header entry */
Elf64_Half e_phnum; /* Number of program header entries */
Elf64_Half e_shentsize; /* Size of section header entry */
Elf64_Half e_shnum; /* Number of section header entries */
Elf64_Half e_shstrndx; /* Section name string table index */
} Elf64_Ehdr;
enum {
ET_NONE = 0,
ET_REL = 1,
ET_EXEC = 2,
ET_DYN = 3,
ET_CORE = 4,
};
enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1 };
typedef struct {
Elf64_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Half st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym;
enum { STB_GLOBAL = 1, STB_WEAK = 2, STB_GNU_UNIQUE = 10 };
enum { STT_OBJECT = 1, STT_FUNC = 2, STT_TLS = 6 };
enum {
R_X86_64_NONE = 0,
R_X86_64_64 = 1,
R_X86_64_COPY = 5,
R_X86_64_GLOB_DAT = 6,
R_X86_64_JUMP_SLOT = 7,
R_X86_64_RELATIVE = 8,
R_X86_64_DTPMOD64 = 16,
R_X86_64_DTPOFF64 = 17,
R_X86_64_TPOFF64 = 18,
};
enum {
R_AARCH64_ABS64 = 257,
R_AARCH64_COPY = 1024,
R_AARCH64_GLOB_DAT = 1025,
R_AARCH64_JUMP_SLOT = 1026,
R_AARCH64_RELATIVE = 1027,
R_AARCH64_TLS_TPREL = 1030,
R_AARCH64_TLSDESC = 1031
};
typedef struct {
Elf64_Addr r_offset;
uint64_t r_info;
} Elf64_Rel;
typedef struct {
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;
static inline Elf64_Xword ELF64_R_SYM(Elf64_Xword info) { return info >> 32; }
static inline Elf64_Xword ELF64_R_TYPE(Elf64_Xword info) {
return info & 0xFFFFFFFF;
}
enum {
PT_LOAD = 1,
PT_DYNAMIC = 2,
PT_INTERP = 3,
PT_NOTE = 4,
PT_PHDR = 6,
PT_TLS = 7,
PT_GNU_EH_FRAME = 0x6474E550,
PT_GNU_STACK = 0x6474E551,
PT_GNU_RELRO = 0x6474E552,
PT_GNU_PROPERTY = 0x6474E553,
};
enum { PF_X = 1, PF_W = 2, PF_R = 4 };
typedef struct {
Elf64_Word p_type; /* Type of segment */
Elf64_Word p_flags; /* Segment attributes */
Elf64_Off p_offset; /* Offset in file */
Elf64_Addr p_vaddr; /* Virtual address in memory */
Elf64_Addr p_paddr; /* Reserved */
Elf64_Xword p_filesz; /* Size of segment in file */
Elf64_Xword p_memsz; /* Size of segment in memory */
Elf64_Xword p_align; /* Alignment of segment */
} Elf64_Phdr;
enum {
DT_NULL = 0,
DT_NEEDED = 1,
DT_PLTRELSZ = 2,
DT_PLTGOT = 3,
DT_HASH = 4,
DT_STRTAB = 5,
DT_SYMTAB = 6,
DT_RELA = 7,
DT_RELASZ = 8,
DT_RELAENT = 9,
DT_STRSZ = 10,
DT_SYMENT = 11,
DT_INIT = 12,
DT_FINI = 13,
DT_SONAME = 14,
DT_RPATH = 15,
DT_SYMBOLIC = 16,
DT_REL = 17,
DT_BIND_NOW = 24,
DT_INIT_ARRAY = 25,
DT_FINI_ARRAY = 26,
DT_INIT_ARRAYSZ = 27,
DT_FINI_ARRAYSZ = 28,
DT_RUNPATH = 29,
DT_PLTREL = 20,
DT_DEBUG = 21,
DT_JMPREL = 23,
DT_FLAGS = 30,
DT_GNU_HASH = 0x6ffffef5,
DT_TLSDESC_PLT = 0x6ffffef6,
DT_TLSDESC_GOT = 0x6ffffef7,
DT_VERSYM = 0x6ffffff0,
DT_RELACOUNT = 0x6ffffff9,
DT_FLAGS_1 = 0x6ffffffb,
DT_VERDEF = 0x6ffffffc,
DT_VERDEFNUM = 0x6ffffffd,
DT_VERNEED = 0x6ffffffe,
DT_VERNEEDNUM = 0x6fffffff
};
enum {
// For DT_FLAGS.
DF_SYMBOLIC = 0x02,
DF_STATIC_TLS = 0x10,
// For DT_FLAGS_1.
DF_1_NOW = 0x00000001
};
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
typedef struct {
Elf64_Sxword d_tag;
union {
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
} Elf64_Dyn;
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct {
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
} Elf64_Shdr;
typedef struct {
Elf32_Word n_namesz;
Elf32_Word n_descsz;
Elf32_Word n_type;
} Elf32_Nhdr;
typedef struct {
Elf64_Word n_namesz;
Elf64_Word n_descsz;
Elf64_Word n_type;
} Elf64_Nhdr;
/* ST_TYPE (subfield of st_info) values (symbol type) */
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
/* ST_BIND (subfield of st_info) values (symbol binding) */
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
/* sh_type (section type) values */
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_INIT_ARRAY 14
#define SHT_FINI_ARRAY 15
#define SHT_SYMTAB_SHNDX 18
/* special section indices */
#define SHN_UNDEF 0
#define SHN_LORESERVE 0xff00
#define SHN_COMMON 0xfff2
#define SHN_XINDEX 0xffff
#define SHN_HIRESERVE 0xff00
/* values for e_machine */
#define EM_NONE 0
#define EM_SPARC 2
#define EM_386 3
#define EM_PPC 20
#define EM_PPC64 21
#define EM_X86_64 62
/* e_indent constants */
#define EI_MAG0 0
#define ELFMAG0 0x7f
#define EI_MAG1 1
#define ELFMAG1 'E'
#define EI_MAG2 2
#define ELFMAG2 'L'
#define EI_MAG3 3
#define ELFMAG3 'F'
#define EI_CLASS 4
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFCLASSNUM 3
#define EI_DATA 5
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define ELFDATANUM 3
#define AT_NULL 0
#define AT_IGNORE 1
#define AT_EXECFD 2
#define AT_PHDR 3
#define AT_PHENT 4
#define AT_PHNUM 5
#define AT_PAGESZ 6
#define AT_BASE 7
#define AT_FLAGS 8
#define AT_ENTRY 9
#define AT_NOTELF 10
#define AT_UID 11
#define AT_EUID 12
#define AT_GID 13
#define AT_EGID 14
typedef struct {
uint64_t entry;
uint64_t phdr;
uint64_t phent;
uint64_t phnum;
} ElfAuxval;
#endif // ELF_H_

View File

@ -8,6 +8,6 @@
#define E_OUTOFBOUNDS -4 #define E_OUTOFBOUNDS -4
#define E_UNKNOWN_SDTYPE -5 #define E_UNKNOWN_SDTYPE -5
#define E_TODO -6 #define E_TODO -6
#define E_GENERIC_ERROR -7 #define E_BADIO -7
#endif // ERRORS_H_ #endif // ERRORS_H_

View File

@ -27,6 +27,22 @@ int32_t kvfs_read(struct VfsMountPoint *vmp, const char *key, uint8_t *const buf
return E_OK; return E_OK;
} }
int32_t kvfs_stat(struct VfsMountPoint *vmp, const char *key, struct VfsStat *stat) {
KvfsNode *node = NULL;
spinlock_acquire(&vmp->spinlock);
HSHTB_GET(&vmp->fs.kvfs, nodes, (char *)key, key_, node);
spinlock_release(&vmp->spinlock);
if (node == NULL) {
return E_NOENTRY;
}
stat->type = VFS_TYPE_FILE;
stat->size = KVFS_BUFFER_SIZE;
return E_OK;
}
int32_t kvfs_write(struct VfsMountPoint *vmp, const char *key, const uint8_t *const buffer, size_t n, size_t off) { int32_t kvfs_write(struct VfsMountPoint *vmp, const char *key, const uint8_t *const buffer, size_t n, size_t off) {
KvfsNode *node = NULL; KvfsNode *node = NULL;
@ -85,7 +101,7 @@ int32_t kvfs_create(struct VfsMountPoint *vmp, const char *path, int32_t type) {
bool kvfs_check(void) { bool kvfs_check(void) {
int32_t ret; int32_t ret;
ret = vfs_create("tmpvars", "hello", VFS_CREATE_FILE); ret = vfs_create("tmpvars", "hello", VFS_TYPE_FILE);
if (ret != E_OK) return false; if (ret != E_OK) return false;
char *hello = "WAWAWAWA!!!"; char *hello = "WAWAWAWA!!!";

View File

@ -5,6 +5,7 @@
#include <stdbool.h> #include <stdbool.h>
struct VfsMountPoint; struct VfsMountPoint;
struct VfsStat;
#define KVFS_NODE_KEY_MAX 128 #define KVFS_NODE_KEY_MAX 128
#define KVFS_NODES_MAX 256 #define KVFS_NODES_MAX 256
@ -21,6 +22,7 @@ typedef struct {
} Kvfs; } Kvfs;
int32_t kvfs_read(struct VfsMountPoint *vmp, const char *key, uint8_t *const buffer, size_t n, size_t off); int32_t kvfs_read(struct VfsMountPoint *vmp, const char *key, uint8_t *const buffer, size_t n, size_t off);
int32_t kvfs_stat(struct VfsMountPoint *vmp, const char *key, struct VfsStat *stat);
int32_t kvfs_write(struct VfsMountPoint *vmp, const char *key, const uint8_t *const buffer, size_t n, size_t off); int32_t kvfs_write(struct VfsMountPoint *vmp, const char *key, const uint8_t *const buffer, size_t n, size_t off);
int32_t kvfs_remove(struct VfsMountPoint *vmp, const char *key); int32_t kvfs_remove(struct VfsMountPoint *vmp, const char *key);
int32_t kvfs_create(struct VfsMountPoint *vmp, const char *path, int32_t type); int32_t kvfs_create(struct VfsMountPoint *vmp, const char *path, int32_t type);

View File

@ -9,7 +9,6 @@
#define CHECK(err) \ #define CHECK(err) \
do { \ do { \
int ok = (err); \ int ok = (err); \
kprintf("ok = %d\n", ok); \
if (ok < 0) goto bad; \ if (ok < 0) goto bad; \
} while(0) } while(0)
@ -27,7 +26,29 @@ int32_t littlefs_read(struct VfsMountPoint *vmp, const char *path, uint8_t *cons
return E_OK; return E_OK;
bad: bad:
spinlock_release(&vmp->spinlock); spinlock_release(&vmp->spinlock);
return E_GENERIC_ERROR; return E_BADIO;
}
int32_t littlefs_stat(struct VfsMountPoint *vmp, const char *path, struct VfsStat *stat) {
spinlock_acquire(&vmp->spinlock);
LittleFs *fs = &vmp->fs.littlefs;
struct lfs_info stat1;
CHECK(lfs_stat(&fs->instance, path, &stat1));
if (stat1.type == LFS_TYPE_REG) {
stat->type = VFS_TYPE_FILE;
} else if (stat1.type == LFS_TYPE_DIR) {
stat->type = VFS_TYPE_DIR;
}
stat->size = stat1.size;
spinlock_release(&vmp->spinlock);
return E_OK;
bad:
spinlock_release(&vmp->spinlock);
return E_BADIO;
} }
int32_t littlefs_write(struct VfsMountPoint *vmp, const char *path, const uint8_t *const buffer, size_t n, size_t off) { int32_t littlefs_write(struct VfsMountPoint *vmp, const char *path, const uint8_t *const buffer, size_t n, size_t off) {
@ -44,7 +65,7 @@ int32_t littlefs_write(struct VfsMountPoint *vmp, const char *path, const uint8_
return E_OK; return E_OK;
bad: bad:
spinlock_release(&vmp->spinlock); spinlock_release(&vmp->spinlock);
return E_GENERIC_ERROR; return E_BADIO;
} }
int32_t littlefs_remove(struct VfsMountPoint *vmp, const char *path) { int32_t littlefs_remove(struct VfsMountPoint *vmp, const char *path) {
@ -57,7 +78,7 @@ int32_t littlefs_remove(struct VfsMountPoint *vmp, const char *path) {
return E_OK; return E_OK;
bad: bad:
spinlock_release(&vmp->spinlock); spinlock_release(&vmp->spinlock);
return E_GENERIC_ERROR; return E_BADIO;
} }
int32_t littlefs_cleanup(struct VfsMountPoint *vmp) { int32_t littlefs_cleanup(struct VfsMountPoint *vmp) {
@ -67,7 +88,7 @@ int32_t littlefs_cleanup(struct VfsMountPoint *vmp) {
return err; return err;
} }
err = lfs_unmount(&vmp->fs.littlefs.instance); err = lfs_unmount(&vmp->fs.littlefs.instance);
if (err < 0) { return E_GENERIC_ERROR; } if (err < 0) { return E_BADIO; }
return E_OK; return E_OK;
} }
@ -76,10 +97,10 @@ int32_t littlefs_create(struct VfsMountPoint *vmp, const char *path, int32_t typ
LittleFs *fs = &vmp->fs.littlefs; LittleFs *fs = &vmp->fs.littlefs;
switch (type) { switch (type) {
case VFS_CREATE_DIR: case VFS_TYPE_DIR:
CHECK(lfs_mkdir(&fs->instance, path)); CHECK(lfs_mkdir(&fs->instance, path));
break; break;
case VFS_CREATE_FILE: { case VFS_TYPE_FILE: {
lfs_file_t file; lfs_file_t file;
CHECK(lfs_file_open(&fs->instance, &file, path, LFS_O_CREAT | LFS_O_WRONLY)); CHECK(lfs_file_open(&fs->instance, &file, path, LFS_O_CREAT | LFS_O_WRONLY));
CHECK(lfs_file_close(&fs->instance, &file)); CHECK(lfs_file_close(&fs->instance, &file));
@ -90,7 +111,7 @@ int32_t littlefs_create(struct VfsMountPoint *vmp, const char *path, int32_t typ
return E_OK; return E_OK;
bad: bad:
spinlock_release(&vmp->spinlock); spinlock_release(&vmp->spinlock);
return E_GENERIC_ERROR; return E_BADIO;
} }
bool littlefs_check(void) { bool littlefs_check(void) {

View File

@ -8,12 +8,14 @@
#define LITTLEFS_BLOCK_SIZE 4096 #define LITTLEFS_BLOCK_SIZE 4096
struct VfsMountPoint; struct VfsMountPoint;
struct VfsStat;
typedef struct { typedef struct {
lfs_t instance; lfs_t instance;
} LittleFs; } LittleFs;
int32_t littlefs_read(struct VfsMountPoint *vmp, const char *path, uint8_t *const buffer, size_t n, size_t off); int32_t littlefs_read(struct VfsMountPoint *vmp, const char *path, uint8_t *const buffer, size_t n, size_t off);
int32_t littlefs_stat(struct VfsMountPoint *vmp, const char *path, struct VfsStat *stat);
int32_t littlefs_write(struct VfsMountPoint *vmp, const char *path, const uint8_t *const buffer, size_t n, size_t off); int32_t littlefs_write(struct VfsMountPoint *vmp, const char *path, const uint8_t *const buffer, size_t n, size_t off);
int32_t littlefs_remove(struct VfsMountPoint *vmp, const char *path); int32_t littlefs_remove(struct VfsMountPoint *vmp, const char *path);
int32_t littlefs_create(struct VfsMountPoint *vmp, const char *path, int32_t type); int32_t littlefs_create(struct VfsMountPoint *vmp, const char *path, int32_t type);

View File

@ -5,6 +5,8 @@
#include "bootinfo/bootinfo.h" #include "bootinfo/bootinfo.h"
#include "pmm/pmm.h" #include "pmm/pmm.h"
#include "paging.h" #include "paging.h"
#include "proc/proc.h"
#include "kprintf.h"
PgTable *KERNEL_CR3 = NULL; PgTable *KERNEL_CR3 = NULL;
@ -73,7 +75,7 @@ void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t si
} }
} }
void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags) { void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PG_PRESENT != 0) { if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PG_PRESENT != 0) {
return; return;
} }
@ -96,6 +98,21 @@ void hal_vmm_switch_pd(PgTable *cr3) {
hal_loadpd(cr3); hal_loadpd(cr3);
} }
PgTable *hal_vmm_userproc_pml4(Proc *proc) {
uint8_t *cr3 = pmm_alloc(1);
PgTable *pml4 = (PgTable *)VIRT(cr3);
hal_memset(pml4, 0, HAL_PAGE_SIZE);
PgTable *kcr3 = VIRT(KERNEL_CR3);
for (size_t i = 256; i < 512; i++) {
pml4->ents[i] = kcr3->ents[i];
}
return (PgTable *)cr3;
}
void hal_vmm_init(void) { void hal_vmm_init(void) {
KERNEL_CR3 = hal_vmm_current_cr3(); KERNEL_CR3 = hal_vmm_current_cr3();
kprintf("KERNEL_CR3 = %p\n", KERNEL_CR3);
} }

View File

@ -5,6 +5,8 @@
#include <stdbool.h> #include <stdbool.h>
#include "compiler/attr.h" #include "compiler/attr.h"
struct Proc;
enum { enum {
HAL_PG_PRESENT = 1<<0, HAL_PG_PRESENT = 1<<0,
HAL_PG_RW = 1<<1, HAL_PG_RW = 1<<1,
@ -43,6 +45,7 @@ void hal_vmm_unmap_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr);
void hal_vmm_map_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr, uint32_t flags); void hal_vmm_map_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr, uint32_t flags);
PgTable *hal_vmm_current_cr3(void); PgTable *hal_vmm_current_cr3(void);
void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags); void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags);
void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags); void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size);
PgTable *hal_vmm_userproc_pml4(struct Proc *proc);
#endif // HAL_VMM_H_ #endif // HAL_VMM_H_

View File

@ -1,5 +1,6 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include "hal/hal.h" #include "hal/hal.h"
#include "vmm/vmm.h" #include "vmm/vmm.h"
#include "spinlock/spinlock.h" #include "spinlock/spinlock.h"
@ -8,6 +9,10 @@
#include "pmm/pmm.h" #include "pmm/pmm.h"
#include "util/util.h" #include "util/util.h"
#include "kprintf.h" #include "kprintf.h"
#include "elf.h"
#include "errors.h"
#include "vfs/vfs.h"
#include "bootinfo/bootinfo.h"
#define PROC_REAPER_FREQ 30 #define PROC_REAPER_FREQ 30
@ -22,7 +27,66 @@ uint64_t sched_ticks = 0;
Procs PROCS; Procs PROCS;
bool proc_checkelf(uint8_t *elf) {
if (elf[0] != 0x7f || elf[1] != 'E' || elf[2] != 'L' || elf[3] != 'F') {
return false;
}
return true;
}
ElfAuxval proc_load_elf_segs(Proc *proc, uint8_t *data) {
#if defined(__x86_64__)
PgTable *vas = proc->platformdata.cr3;
#endif
ElfAuxval aux = {0};
Elf64_Ehdr *elfhdr = (Elf64_Ehdr *)data;
aux.entry = elfhdr->e_entry;
aux.phnum = elfhdr->e_phnum;
aux.phent = elfhdr->e_phentsize;
for (uint64_t seg = 0; seg < elfhdr->e_phnum; seg++) {
Elf64_Phdr *phdr = (Elf64_Phdr *)(data + elfhdr->e_phoff + (elfhdr->e_phentsize * seg));
switch (phdr->p_type) {
case PT_PHDR: {
aux.phdr = (uint64_t)phdr->p_vaddr;
} break;
case PT_LOAD: {
uint64_t off = phdr->p_vaddr & (HAL_PAGE_SIZE - 1);
uint64_t blocks = (phdr->p_memsz / HAL_PAGE_SIZE) + 1;
uint8_t *physaddr = pmm_alloc(blocks);
uint8_t *virtaddr = (uint8_t *)(phdr->p_vaddr - off);
hal_memset(VIRT(physaddr), 0, phdr->p_memsz);
hal_memcpy(VIRT(physaddr) + off, (data + phdr->p_offset), phdr->p_filesz);
#if defined(__x86_64__)
uint32_t pgflags = HAL_PG_USER | HAL_PG_RW | HAL_PG_PRESENT;
hal_vmm_map_range(VIRT(vas), virtaddr, physaddr, blocks * HAL_PAGE_SIZE, pgflags);
#endif
VasRange *range = dlmalloc(sizeof(*range));
range->virtstart = virtaddr;
range->physstart = physaddr;
range->size = blocks * HAL_PAGE_SIZE;
#if defined(__x86_64__)
range->pgflags = pgflags;
#endif
LL_APPEND(proc->vas, range);
} break;
}
}
return aux;
}
Proc *proc_spawnkern(void (*ent)(void), char *name) { Proc *proc_spawnkern(void (*ent)(void), char *name) {
if (pids >= PROC_MAX) {
return NULL;
}
Proc *proc = dlmalloc(sizeof(*proc)); Proc *proc = dlmalloc(sizeof(*proc));
if (proc == NULL) { if (proc == NULL) {
return NULL; return NULL;
@ -51,6 +115,56 @@ Proc *proc_spawnkern(void (*ent)(void), char *name) {
return proc; return proc;
} }
Proc *proc_spawnuser(char *mountpoint, char *path) {
VfsStat stat;
if (vfs_stat(mountpoint, path, &stat) != E_OK) {
return NULL;
}
if (stat.type != VFS_TYPE_FILE) {
return NULL;
}
uint8_t *data = dlmalloc(stat.size);
if (vfs_read(mountpoint, path, data, stat.size, 0) != E_OK) {
return NULL;
}
Proc *proc = dlmalloc(sizeof(*proc));
hal_memset(proc, 0, sizeof(*proc));
ksprintf(proc->name, "%s:%s", mountpoint, path);
uint8_t *sp = (uint8_t *)pmm_alloc(PROC_STACKBLOCKS) + PROC_STACKSIZE;
uint8_t *spbase = sp - PROC_STACKSIZE;
#if defined(__x86_64__)
proc->platformdata.kstack = sp;
hal_memset(&proc->platformdata.trapframe, 0, sizeof(proc->platformdata.trapframe));
proc->platformdata.cr3 = hal_vmm_userproc_pml4(proc);
uint32_t flags = HAL_PG_RW | HAL_PG_USER | HAL_PG_PRESENT;
hal_vmm_map_range(VIRT(proc->platformdata.cr3), spbase, spbase, PROC_STACKSIZE, flags);
VasRange *range = dlmalloc(sizeof(*range));
range->virtstart = spbase;
range->physstart = spbase;
range->size = PROC_STACKSIZE;
range->pgflags = flags;
LL_APPEND(proc->vas, range);
ElfAuxval aux = proc_load_elf_segs(proc, data);
proc->platformdata.trapframe.ss = 0x20 | 0x3;
proc->platformdata.trapframe.rsp = (uint64_t)VIRT(sp);
proc->platformdata.trapframe.rflags = 0x202;
proc->platformdata.trapframe.cs = 0x18 | 0x3;
proc->platformdata.trapframe.rip = aux.entry;
#endif
proc->state = PROC_READY;
proc->pid = pids++;
return proc;
}
void proc_register(Proc *proc) { void proc_register(Proc *proc) {
spinlock_acquire(&PROCS.spinlock); spinlock_acquire(&PROCS.spinlock);
LL_APPEND(PROCS.procs, proc); LL_APPEND(PROCS.procs, proc);
@ -63,24 +177,53 @@ Proc *proc_nextready(void) {
return proc; return proc;
} }
void proc_reaper(void) {
Proc *head = PROCS.procs;
while (head) {
if (head->state == PROC_ZOMBIE) {
Proc *zombie = head;
head = head->next;
LL_REMOVE(PROCS.procs, zombie);
#if defined(__x86_64__)
pmm_free((uintptr_t)(zombie->platformdata.kstack - PROC_STACKSIZE), PROC_STACKBLOCKS);
#endif
if (!zombie->kern) {
VasRange *vashead = zombie->vas;
size_t i = 0;
while (vashead) {
VasRange *tmp = vashead;
vashead = vashead->next;
#if defined(__x86_64__)
hal_vmm_unmap_range(zombie->platformdata.cr3, tmp->virtstart, tmp->physstart, tmp->size);
#endif
// first pmm mapping is for the elf itself
if (i == 0) {
pmm_free((uintptr_t)tmp->physstart, tmp->size / HAL_PAGE_SIZE);
}
dlfree(tmp);
i++;
}
#if defined(__x86_64__)
pmm_free((uintptr_t)zombie->platformdata.cr3, 1);
#endif
}
dlfree(zombie);
} else {
head = head->next;
}
}
}
void proc_sched(void *cpustate) { void proc_sched(void *cpustate) {
hal_intr_disable(); hal_intr_disable();
sched_ticks++; sched_ticks++;
if (sched_ticks % PROC_REAPER_FREQ == 0) { if (sched_ticks % PROC_REAPER_FREQ == 0) {
Proc *head = PROCS.procs; proc_reaper();
while (head) {
if (head->state == PROC_ZOMBIE) {
Proc *zombie = head;
head = head->next;
LL_REMOVE(PROCS.procs, zombie);
pmm_free((uintptr_t)(zombie->platformdata.kstack - PROC_STACKSIZE), PROC_STACKBLOCKS);
dlfree(zombie);
} else {
head = head->next;
}
}
} }
#if defined(__x86_64__) #if defined(__x86_64__)
@ -116,31 +259,18 @@ void proc_idle(void) {
} }
} }
int a = 0; void proc_status(void) {
void proc_print(void) {
for (;;) { for (;;) {
hal_wait(1 * 1000); spinlock_acquire(&PROCS.spinlock);
Proc *head = PROCS.procs;
/* if (a == 10) { */ while (head) {
/* PROC_DIE(); */ kprintf("%s %s\n", head->kern ? "kern" : "user", head->name);
/* } */ head = head->next;
kprintf("A"); }
a++; kprintf("\n\n");
} spinlock_release(&PROCS.spinlock);
}
hal_wait(3 * 1000);
int b = 0;
void proc_print2(void) {
for (;;) {
hal_wait(2 * 1000);
/* if (b == 20) { */
/* PROC_DIE(); */
/* } */
kprintf("B");
b++;
} }
} }
@ -152,8 +282,8 @@ void proc_init(void) {
proc_register(idle); proc_register(idle);
PROCS.current = idle; PROCS.current = idle;
proc_register(proc_spawnkern(&proc_print, "print")); proc_register(proc_spawnkern(&proc_status, "status"));
proc_register(proc_spawnkern(&proc_print2, "print")); proc_register(proc_spawnuser("base", "/bin/hello"));
#if defined(__x86_64__) #if defined(__x86_64__)
hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3); hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3);

View File

@ -12,6 +12,8 @@
#define PROC_STACKBLOCKS 32 #define PROC_STACKBLOCKS 32
#define PROC_STACKSIZE (PROC_STACKBLOCKS * BITMAP_BLOCK_SIZE) #define PROC_STACKSIZE (PROC_STACKBLOCKS * BITMAP_BLOCK_SIZE)
#define PROC_MAX 0x100 // max amount of processes
enum { enum {
PROC_READY, PROC_READY,
PROC_RUNNING, PROC_RUNNING,
@ -38,7 +40,9 @@ typedef struct {
extern Procs PROCS; extern Procs PROCS;
void proc_init(void); void proc_init(void);
void proc_register(Proc *proc);
Proc *proc_spawnkern(void (*ent)(void), char *name); Proc *proc_spawnkern(void (*ent)(void), char *name);
Proc *proc_spawnuser(char *mountpoint, char *path);
void proc_sched(void *cpustate); void proc_sched(void *cpustate);
#endif // PROC_PROC_H_ #endif // PROC_PROC_H_

View File

@ -18,6 +18,7 @@ VfsTable VFS_TABLE;
void vfs_init_kvfs(VfsMountPoint *mp) { void vfs_init_kvfs(VfsMountPoint *mp) {
mp->read = &kvfs_read; mp->read = &kvfs_read;
mp->stat = &kvfs_stat;
mp->write = &kvfs_write; mp->write = &kvfs_write;
mp->remove = &kvfs_remove; mp->remove = &kvfs_remove;
mp->check = &kvfs_check; mp->check = &kvfs_check;
@ -52,6 +53,7 @@ void vfs_init_littlefs(VfsMountPoint *mp) {
} }
mp->read = &littlefs_read; mp->read = &littlefs_read;
mp->stat = &littlefs_stat;
mp->write = &littlefs_write; mp->write = &littlefs_write;
mp->remove = &littlefs_remove; mp->remove = &littlefs_remove;
mp->check = &littlefs_check; mp->check = &littlefs_check;
@ -123,6 +125,20 @@ int32_t vfs_read(char *mountpoint, const char *path, uint8_t *const buffer, size
return mp->read(mp, path, buffer, n, off); return mp->read(mp, path, buffer, n, off);
} }
int32_t vfs_stat(char *mountpoint, const char *path, VfsStat *stat) {
VfsMountPoint *mp = NULL;
spinlock_acquire(&VFS_TABLE.spinlock);
HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp);
spinlock_release(&VFS_TABLE.spinlock);
if (mp == NULL) {
return E_NOENTRY;
}
return mp->stat(mp, path, stat);
}
int32_t vfs_create(char *mountpoint, const char *path, int32_t type) { int32_t vfs_create(char *mountpoint, const char *path, int32_t type) {
VfsMountPoint *mp = NULL; VfsMountPoint *mp = NULL;

View File

@ -23,10 +23,15 @@ static const char *vfs_strings[] = {
}; };
enum { enum {
VFS_CREATE_DIR, VFS_TYPE_DIR,
VFS_CREATE_FILE, VFS_TYPE_FILE,
}; };
typedef struct VfsStat {
size_t size;
int32_t type;
} VfsStat;
typedef struct VfsMountPoint { typedef struct VfsMountPoint {
bool taken; bool taken;
uint8_t label[VFS_MOUNTPOINT_LABEL_MAX]; uint8_t label[VFS_MOUNTPOINT_LABEL_MAX];
@ -34,6 +39,7 @@ typedef struct VfsMountPoint {
StoreDev *backingsd; StoreDev *backingsd;
int32_t (*read)(struct VfsMountPoint *vmp, const char *path, uint8_t *const buffer, size_t n, size_t off); int32_t (*read)(struct VfsMountPoint *vmp, const char *path, uint8_t *const buffer, size_t n, size_t off);
int32_t (*stat)(struct VfsMountPoint *vmp, const char *path, struct VfsStat *stat);
int32_t (*write)(struct VfsMountPoint *vmp, const char *path, const uint8_t *const buffer, size_t n, size_t off); int32_t (*write)(struct VfsMountPoint *vmp, const char *path, const uint8_t *const buffer, size_t n, size_t off);
int32_t (*remove)(struct VfsMountPoint *vmp, const char *path); int32_t (*remove)(struct VfsMountPoint *vmp, const char *path);
int32_t (*create)(struct VfsMountPoint *vmp, const char *path, int32_t type); int32_t (*create)(struct VfsMountPoint *vmp, const char *path, int32_t type);
@ -56,9 +62,11 @@ extern VfsTable VFS_TABLE;
void vfs_init(void); void vfs_init(void);
int32_t vfs_read(char *mountpoint, const char *path, uint8_t *const buffer, size_t n, size_t off); int32_t vfs_read(char *mountpoint, const char *path, uint8_t *const buffer, size_t n, size_t off);
int32_t vfs_stat(char *mountpoint, const char *path, VfsStat *stat);
int32_t vfs_write(char *mountpoint, const char *path, const uint8_t *const buffer, size_t n, size_t off); int32_t vfs_write(char *mountpoint, const char *path, const uint8_t *const buffer, size_t n, size_t off);
int32_t vfs_remove(char *mountpoint, const char *path); int32_t vfs_remove(char *mountpoint, const char *path);
int32_t vfs_create(char *mountpoint, const char *path, int32_t type); int32_t vfs_create(char *mountpoint, const char *path, int32_t type);
int32_t vfs_unmount(char *mountpoint); int32_t vfs_unmount(char *mountpoint);
#endif // VFS_VFS_H_ #endif // VFS_VFS_H_

View File

@ -35,10 +35,10 @@ void vmm_map_kern_range(void *virtstart, void *physstart, size_t size, uint32_t
spinlock_release(&VIRT_MEM.spinlock); spinlock_release(&VIRT_MEM.spinlock);
} }
void vmm_unmap_kern_range(void *virtstart, void *physstart, size_t size, uint32_t flags) { void vmm_unmap_kern_range(void *virtstart, void *physstart, size_t size) {
spinlock_acquire(&VIRT_MEM.spinlock); spinlock_acquire(&VIRT_MEM.spinlock);
#if defined(__x86_64__) #if defined(__x86_64__)
hal_vmm_unmap_range(KERNEL_CR3, virtstart, physstart, size, flags); hal_vmm_unmap_range(KERNEL_CR3, virtstart, physstart, size);
#endif #endif
spinlock_release(&VIRT_MEM.spinlock); spinlock_release(&VIRT_MEM.spinlock);
} }

View File

@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
make -B && make base && make iso make -B kernel && make -B user && make base && make iso

View File

@ -1,6 +1,5 @@
#!/bin/sh #!/bin/sh
rm -f base.img rm -f base.img
rm -rf base_root cat user/FILES.txt | while read line; do cp -v $line base/bin; done
mkdir -p base_root mklittlefs -c base -b 4096 -s $((1<<20)) base.img
mklittlefs -c base_root -b 4096 -s $((1<<20)) base.img

1
user/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
FILES.txt

14
user/Makefile Normal file
View File

@ -0,0 +1,14 @@
CURRENT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
.PHONY: all clean
APP_DIR := $(shell find . -mindepth 1 -maxdepth 1 -type d -not -path "./arch")
all:
rm -f FILES.txt
touch FILES.txt
for dir in $(APP_DIR); do make -C $$dir FILES=$(CURRENT_DIR)/FILES.txt all; done
clean:
for dir in $(APP_DIR); do make -C $$dir clean; done

9
user/Makefile.inc Normal file
View File

@ -0,0 +1,9 @@
ARCH ?= x86_64
CFLAGS := -ffreestanding -Wall -Wextra -g -fcommon -nostdinc
CURRENT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
include $(CURRENT_DIR)/arch/$(ARCH)/$(ARCH).mk
LDFLAGS += -nostdlib -static $(shell $(CC) -print-libgcc-file-name) -T $(CURRENT_DIR)/arch/$(ARCH)/link.ld

26
user/arch/x86_64/link.ld Normal file
View File

@ -0,0 +1,26 @@
ENTRY(_start)
SECTIONS {
/* . = 0xffff000000000000; */
. = 0x0000000000000000;
.rodata ALIGN(4K):
{
*(.rodata .rodata.*)
}
.text ALIGN(4K):
{
*(.text .text.*)
}
.data ALIGN(4K):
{
*(.data .data.*)
}
.bss ALIGN(4K):
{
*(.bss .bss.*)
}
}

View File

@ -0,0 +1,22 @@
CC := x86_64-elf-gcc
LD := x86_64-elf-ld
CFLAGS += -m64 \
-fPIE \
-mno-80387 \
-mno-mmx \
-mno-sse \
-nostartfiles \
-nostdlib \
-mno-sse2 \
-mno-red-zone \
-fno-stack-protector \
-fno-stack-check \
-Os \
LDFLAGS += -m elf_x86_64 \
-pie \
--no-dynamic-linker \
-z text \
-z max-page-size=0x1000

2
user/hello/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.o
hello

21
user/hello/Makefile Normal file
View File

@ -0,0 +1,21 @@
include ../Makefile.inc
.PHONY: all clean
TARGET := hello
SRCFILES := $(wildcard *.s)
ASFILES := $(filter %.s,$(SRCFILES))
OBJ := $(patsubst %.s,%.o,$(ASFILES))
%.o: %.s
$(CC) $(CFLAGS) -c $< -o $@
all: $(TARGET)
hello: $(OBJ)
$(LD) $^ $(LDFLAGS) -o $@
echo "$(realpath $@)" >> $(FILES)
clean:
rm -f $(OBJ) $(TARGET)

6
user/hello/hello.s Normal file
View File

@ -0,0 +1,6 @@
.global _start
_start:
.spin:
jmp .spin