Initial elf64 loading
This commit is contained in:
parent
993092a854
commit
dd2f204ab5
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,5 @@
|
|||||||
|
obj/src/
|
||||||
obj/
|
obj/
|
||||||
bin/
|
bin/
|
||||||
|
bin/os
|
||||||
|
image.hdd
|
||||||
|
|||||||
18
fortune
18
fortune
@ -1,2 +1,16 @@
|
|||||||
Many hands make light work.
|
_/I\_____________o______________o___/I\ l * / /_/ * __ ' .* l
|
||||||
-- John Heywood
|
I"""_____________l______________l___"""I\ l *// _l__l_ . *. l
|
||||||
|
[__][__][(******)__][__](******)[__][] \l l-\ ---//---*----(oo)----------l
|
||||||
|
[][__][__(******)][__][_(******)_][__] l l \\ // ____ >-( )-< / l
|
||||||
|
[__][__][_l l[__][__][l l][__][] l l \\)) ._****_.(......) .@@@:::l
|
||||||
|
[][__][__]l .l_][__][__] .l__][__] l l ll _(o_o)_ (@*_*@ l
|
||||||
|
[__][__][/ <_)[__][__]/ <_)][__][] l l ll ( / \ ) / / / ) l
|
||||||
|
[][__][ /..,/][__][__][/..,/_][__][__] l l / \\ _\ \_ / _\_\ l
|
||||||
|
[__][__(__/][__][__][_(__/_][__][__][] l l______________________________l
|
||||||
|
[__][__]] l , , . [__][__][] l
|
||||||
|
[][__][_] l . i. '/ , [][__][__] l /\**/\ season's
|
||||||
|
[__][__]] l O .\ / /, O [__][__][] l ( o_o )_) greetings
|
||||||
|
_[][__][_] l__l======='=l____[][__][__] l_______,(u u ,),__________________
|
||||||
|
[__][__]]/ /l\-------/l\ [__][__][]/ {}{}{}{}{}{}<R>
|
||||||
|
|
||||||
|
In Ellen's house it is warm and toasty while fuzzies play in the snow outside.
|
||||||
|
|||||||
2
limine
2
limine
@ -1 +1 @@
|
|||||||
Subproject commit e0e61c946933696453f591da525ab1f8a66a553d
|
Subproject commit eecf8d682a749701691e31b89f66f330f525c611
|
||||||
@ -19,11 +19,14 @@ make -C limine
|
|||||||
mformat -i image.hdd@@1M -F
|
mformat -i image.hdd@@1M -F
|
||||||
|
|
||||||
# Make relevant subdirectories.
|
# Make relevant subdirectories.
|
||||||
mmd -i image.hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine ::/fort
|
mmd -i image.hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine ::/fort ::/usr ::/usr/bin
|
||||||
|
|
||||||
|
#fortune -l > fortune
|
||||||
|
|
||||||
# Copy over the relevant files.
|
# Copy over the relevant files.
|
||||||
mcopy -i image.hdd@@1M bin/os ::/boot
|
mcopy -i image.hdd@@1M bin/os ::/boot
|
||||||
mcopy -i image.hdd@@1M limine.conf limine/limine-bios.sys ::/boot/limine
|
mcopy -i image.hdd@@1M limine.conf limine/limine-bios.sys ::/boot/limine
|
||||||
mcopy -i image.hdd@@1M limine/BOOTX64.EFI ::/EFI/BOOT
|
mcopy -i image.hdd@@1M limine/BOOTX64.EFI ::/EFI/BOOT
|
||||||
mcopy -i image.hdd@@1M limine/BOOTIA32.EFI ::/EFI/BOOT
|
mcopy -i image.hdd@@1M limine/BOOTIA32.EFI ::/EFI/BOOT
|
||||||
|
mcopy -i image.hdd@@1M mnt/usr/bin/test ::/usr/bin/test
|
||||||
mcopy -i image.hdd@@1M fortune ::/fort/fortu.ne
|
mcopy -i image.hdd@@1M fortune ::/fort/fortu.ne
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
obj/src/int.c.o: src/int.c src/apic.h src/common.h src/print.h src/kbd.h
|
obj/src/int.c.o: src/int.c src/apic.h src/common.h src/print.h src/kbd.h \
|
||||||
|
src/syscalls.h src/lib/sys.h src/int.h src/lib/stdio.h src/lib/malloc.h
|
||||||
src/apic.h:
|
src/apic.h:
|
||||||
src/common.h:
|
src/common.h:
|
||||||
src/print.h:
|
src/print.h:
|
||||||
src/kbd.h:
|
src/kbd.h:
|
||||||
|
src/syscalls.h:
|
||||||
|
src/lib/sys.h:
|
||||||
|
src/int.h:
|
||||||
|
src/lib/stdio.h:
|
||||||
|
src/lib/malloc.h:
|
||||||
|
|||||||
BIN
obj/src/int.c.o
BIN
obj/src/int.c.o
Binary file not shown.
@ -1,12 +1,12 @@
|
|||||||
obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \
|
obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \
|
||||||
src/prompt/file.h src/acpi.h src/common.h src/ahci.h src/alloc.h \
|
src/prompt/file.h src/prompt/file.h src/acpi.h src/common.h src/ahci.h \
|
||||||
src/apic.h src/fat32.h src/lib/ctype.h src/lib/string.h \
|
src/alloc.h src/apic.h src/fat32.h src/lib/ctype.h src/lib/string.h \
|
||||||
src/lib/../lib/stdio.h src/lib/../lib/malloc.h \
|
src/lib/../lib/stdio.h src/lib/../lib/malloc.h src/lib/../lib/../kbd.h \
|
||||||
src/lib/../lib/../common.h src/lib/../lib/../kbd.h \
|
src/lib/../lib/../print.h src/lib/elf/elf64.h
|
||||||
src/lib/../lib/../print.h src/lib/stdio.h src/print.h
|
|
||||||
src/../include/limine.h:
|
src/../include/limine.h:
|
||||||
src/prompt/lex.h:
|
src/prompt/lex.h:
|
||||||
src/prompt/file.h:
|
src/prompt/file.h:
|
||||||
|
src/prompt/file.h:
|
||||||
src/acpi.h:
|
src/acpi.h:
|
||||||
src/common.h:
|
src/common.h:
|
||||||
src/ahci.h:
|
src/ahci.h:
|
||||||
@ -17,8 +17,6 @@ src/lib/ctype.h:
|
|||||||
src/lib/string.h:
|
src/lib/string.h:
|
||||||
src/lib/../lib/stdio.h:
|
src/lib/../lib/stdio.h:
|
||||||
src/lib/../lib/malloc.h:
|
src/lib/../lib/malloc.h:
|
||||||
src/lib/../lib/../common.h:
|
|
||||||
src/lib/../lib/../kbd.h:
|
src/lib/../lib/../kbd.h:
|
||||||
src/lib/../lib/../print.h:
|
src/lib/../lib/../print.h:
|
||||||
src/lib/stdio.h:
|
src/lib/elf/elf64.h:
|
||||||
src/print.h:
|
|
||||||
|
|||||||
BIN
obj/src/main.c.o
BIN
obj/src/main.c.o
Binary file not shown.
15
src/fat32.h
15
src/fat32.h
@ -82,9 +82,7 @@ static u32 fat32_next(int port, fat32_vol_t* vol, u32 cluster) {
|
|||||||
u32 fat_sect = vol->fat_start + fat_off / TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE;
|
u32 fat_sect = vol->fat_start + fat_off / TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE;
|
||||||
u32 fat_idx = (fat_off & (TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE-1));
|
u32 fat_idx = (fat_off & (TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE-1));
|
||||||
|
|
||||||
printf("fat_next: cluster=%u fat_off=%u fat_sect=%u byte_off=%u\n",
|
|
||||||
cluster, fat_off, fat_sect, fat_off);
|
|
||||||
|
|
||||||
u8* buff = (u8*) alloc(4096);
|
u8* buff = (u8*) alloc(4096);
|
||||||
if(ahci_read(port, fat_sect, 2, buff) < 0) {
|
if(ahci_read(port, fat_sect, 2, buff) < 0) {
|
||||||
printf("fat_next: read failed at lba=%u\n", fat_sect);
|
printf("fat_next: read failed at lba=%u\n", fat_sect);
|
||||||
@ -192,7 +190,6 @@ static fat32_dirent_t* fat32_find(int port, fat32_vol_t* vol, u32 dir_cluster, c
|
|||||||
|
|
||||||
if (strneq(e->name, name83, 8) && strneq(e->ext, name83 + 8, 3)) {
|
if (strneq(e->name, name83, 8) && strneq(e->ext, name83 + 8, 3)) {
|
||||||
fat32_dirent_t* result = (fat32_dirent_t*) alloc(sizeof(fat32_dirent_t));
|
fat32_dirent_t* result = (fat32_dirent_t*) alloc(sizeof(fat32_dirent_t));
|
||||||
printf("\nFOUND: %.8s'.'%3s\n", e->name, e->ext);
|
|
||||||
*result = *e;
|
*result = *e;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -229,19 +226,16 @@ static FILE* fat32_find_path(int port, fat32_vol_t* vol, const char* path) {
|
|||||||
int len = 0;
|
int len = 0;
|
||||||
while (path[len] && path[len] != '/') len++;
|
while (path[len] && path[len] != '/') len++;
|
||||||
if (len > 11) return NULL; // can't possibly be valid 8.3
|
if (len > 11) return NULL; // can't possibly be valid 8.3
|
||||||
printn(path, len);
|
|
||||||
|
|
||||||
memcpy(part, path, len);
|
memcpy(part, path, len);
|
||||||
part[len] = '\0';
|
part[len] = '\0';
|
||||||
path += len;
|
path += len;
|
||||||
if (*path == '/') path++;
|
if (*path == '/') path++;
|
||||||
|
|
||||||
put('\n');
|
|
||||||
// convert component to 8.3
|
// convert component to 8.3
|
||||||
u8 name83[11];
|
u8 name83[11];
|
||||||
|
|
||||||
fat32_to_name83(part, name83);
|
fat32_to_name83(part, name83);
|
||||||
printf("\nNAME83: %.8s.%.3s\n", name83, name83+8);
|
|
||||||
|
|
||||||
fat32_dirent_t* e = fat32_find(port, vol, cluster, name83);
|
fat32_dirent_t* e = fat32_find(port, vol, cluster, name83);
|
||||||
if (!e) return NULL;
|
if (!e) return NULL;
|
||||||
@ -293,6 +287,7 @@ static u8* slurp(struct FILE* file) {
|
|||||||
sz *= TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE;
|
sz *= TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE;
|
||||||
u8* buff = (u8*) calloc(file->info.file_size, 1);
|
u8* buff = (u8*) calloc(file->info.file_size, 1);
|
||||||
|
|
||||||
|
printf("SLURP: Buffer Copied\n");
|
||||||
if(!buff) {
|
if(!buff) {
|
||||||
printf("fat32_slurp: %.8s'.'%.3s: Failed to allocate buffer of size %u\n", file->info.name, file->info.ext, file->info.file_size);
|
printf("fat32_slurp: %.8s'.'%.3s: Failed to allocate buffer of size %u\n", file->info.name, file->info.ext, file->info.file_size);
|
||||||
}
|
}
|
||||||
@ -305,4 +300,8 @@ static u8* slurp(struct FILE* file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern i8 read_active_port;
|
||||||
|
extern fat32_vol_t active_vol;
|
||||||
41
src/int.c
41
src/int.c
@ -5,9 +5,9 @@
|
|||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "kbd.h"
|
#include "kbd.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "syscalls.h"
|
||||||
// for trap debugging
|
#include "int.h"
|
||||||
u64 dbg_var = 0;
|
#include "lib/stdio.h"
|
||||||
|
|
||||||
pstruct int_desc {
|
pstruct int_desc {
|
||||||
u16 addr_low;
|
u16 addr_low;
|
||||||
@ -60,30 +60,29 @@ void load_idt(void *addr) {
|
|||||||
|
|
||||||
extern void draw(u8 vect);
|
extern void draw(u8 vect);
|
||||||
|
|
||||||
struct cpu_ctx {
|
struct cpu_ctx *interrupt_dispatch(struct cpu_ctx* ctx) {
|
||||||
u64 r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax;
|
if(ctx->vect == 0x21) {
|
||||||
|
|
||||||
u64 vect;
|
|
||||||
u64 err;
|
|
||||||
|
|
||||||
u64 iret_rip;
|
|
||||||
u64 iret_cs;
|
|
||||||
u64 iret_flags;
|
|
||||||
u64 iret_rsp;
|
|
||||||
u64 iret_ss;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cpu_ctx *interrupt_dispatch(struct cpu_ctx *ctx) {
|
|
||||||
if(ctx->vect = 0x21) {
|
|
||||||
kbd_handler();
|
kbd_handler();
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ctx->vect == 0x80) {
|
||||||
|
print("SYSCALL\n");
|
||||||
|
syscall_handler(ctx);
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
print("\n[IRQ ");
|
print("\n[IRQ ");
|
||||||
print8(ctx->vect);
|
print8(ctx->vect);
|
||||||
print("] with message: ");
|
print("] with err: ");
|
||||||
print64(dbg_var);
|
print64(ctx->err);
|
||||||
print("\n");
|
print("\n");
|
||||||
|
|
||||||
|
if(ctx->vect == 0x0D || ctx->vect == 0x0E) {
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,5 +301,7 @@ void init_idt(void) {
|
|||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
set_idt(i, isr_table[i], 0);
|
set_idt(i, isr_table[i], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_idt(0x80, isr128, 3);
|
||||||
load_idt(idt);
|
load_idt(idt);
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/int.h
Normal file
14
src/int.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct cpu_ctx {
|
||||||
|
u64 r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax;
|
||||||
|
|
||||||
|
u64 vect;
|
||||||
|
u64 err;
|
||||||
|
|
||||||
|
u64 iret_rip;
|
||||||
|
u64 iret_cs;
|
||||||
|
u64 iret_flags;
|
||||||
|
u64 iret_rsp;
|
||||||
|
u64 iret_ss;
|
||||||
|
};
|
||||||
264
src/lib/elf/elf64.h
Normal file
264
src/lib/elf/elf64.h
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../common.h"
|
||||||
|
#include "../../lib/stdio.h"
|
||||||
|
#include "../../lib/malloc.h"
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef struct elf64_header {
|
||||||
|
u32 MAGIC; /* '\x7FELF' */
|
||||||
|
enum : u8 { ELF32 = 1, ELF64 = 2} size; /* 1 for ELF32, 2 for ELF64 */
|
||||||
|
enum : u8 { ELF64_LE = 1, ELF64_BE = 2} endianness; /* 1 for little-endian, 2 for big-endian */
|
||||||
|
u8 version; /* ELF version */
|
||||||
|
u8 abi; /* ABI identification */
|
||||||
|
u8 abi_version; /* ABI version */
|
||||||
|
u8 padding[7]; /* Padding to align the structure */
|
||||||
|
|
||||||
|
enum : u16 {
|
||||||
|
ELF_RELOC = 1,
|
||||||
|
ELF_EXEC = 2,
|
||||||
|
ELF_SHARED = 3,
|
||||||
|
ELF_CORe = 4,
|
||||||
|
} type; /* 1 for relocatable, 2 for executable, 3 for shared, 4 for core */
|
||||||
|
u16 instruction_set; /* Architecture: e.g., EM_X86_64 = 62 */
|
||||||
|
u32 elf_version; /* Version of the ELF specification */
|
||||||
|
u64 prog_entry_offset; /* Entry point address */
|
||||||
|
u64 prog_header_table_offset; /* Program header table offset */
|
||||||
|
u64 sect_header_table_offset; /* Section header table offset */
|
||||||
|
u32 flags; /* Processor-specific flags */
|
||||||
|
u16 header_size; /* Size of this header */
|
||||||
|
u16 prog_entry_size; /* Size of program entry */
|
||||||
|
u16 prog_entry_count; /* Number of program entries */
|
||||||
|
u16 sect_entry_size; /* Size of section entry */
|
||||||
|
u16 sect_entry_count; /* Number of section entries */
|
||||||
|
u16 sect_index; /* Index of the section header string table */
|
||||||
|
} elf64_header_t;
|
||||||
|
|
||||||
|
typedef struct elf64_prog_header {
|
||||||
|
enum : u32 {
|
||||||
|
ELF64_IGNORE,
|
||||||
|
ELF64_LOAD,
|
||||||
|
ELF64_DYNAMIC,
|
||||||
|
ELF64_INTERP,
|
||||||
|
ELF64_NOTE,
|
||||||
|
} type;
|
||||||
|
enum : u32 { ELF64_X = 1, ELF64_W = 2, ELF64_R = 4} flags;
|
||||||
|
u64 data_offset;
|
||||||
|
u64* vmem_start;
|
||||||
|
u64 seg_phys;
|
||||||
|
u64 seg_filesize;
|
||||||
|
u64 seg_memsize;
|
||||||
|
u64 req_alignment;
|
||||||
|
} elf64_prog_header_t;
|
||||||
|
|
||||||
|
typedef struct elf64_sect_header {
|
||||||
|
u32 name_offset;
|
||||||
|
enum : u32 {
|
||||||
|
SHT_NULL = 0,
|
||||||
|
SHT_PROGBITS = 1,
|
||||||
|
SHT_SYMTAB = 2,
|
||||||
|
SHT_STRTAB = 3,
|
||||||
|
SHT_RELA = 4,
|
||||||
|
SHT_NOBITS = 8,
|
||||||
|
SHT_REL = 9,
|
||||||
|
} type;
|
||||||
|
u64 flags;
|
||||||
|
u64 addr;
|
||||||
|
u64 offset; // offset in file
|
||||||
|
u64 size;
|
||||||
|
u32 link; // for RELA: index of associated symbol table section
|
||||||
|
u32 info; // for RELA: index of section the relocations apply to
|
||||||
|
u64 addralign;
|
||||||
|
u64 entsize;
|
||||||
|
} elf64_sect_header_t;
|
||||||
|
|
||||||
|
typedef struct elf64_sym {
|
||||||
|
u32 name_offset;
|
||||||
|
u8 info; // binding (high 4) + type (low 4)
|
||||||
|
u8 other;
|
||||||
|
u16 sect_index;
|
||||||
|
u64 value; // offset within its section for relocatable files
|
||||||
|
u64 size;
|
||||||
|
} elf64_sym_t;
|
||||||
|
|
||||||
|
typedef struct elf64_rela {
|
||||||
|
u64 offset; // offset within the target section to patch
|
||||||
|
u64 info; // symbol index (high 32) + relocation type (low 32)
|
||||||
|
i64 addend;
|
||||||
|
} elf64_rela_t;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#define ELF_MAGIC 0x464C457F // '\x7FELF' as little-endian u32
|
||||||
|
#define R_X86_64_64 1 // S + A
|
||||||
|
#define R_X86_64_PC32 2 // S + A - P
|
||||||
|
#define R_X86_64_PLT32 4 // S + A - P (treat same as PC32 for static)
|
||||||
|
#define R_X86_64_32 10 // S + A (zero-extend to 64)
|
||||||
|
#define R_X86_64_32S 11 // S + A (sign-extend to 64)
|
||||||
|
|
||||||
|
#define RELA_SYM(info) ((info) >> 32)
|
||||||
|
#define RELA_TYPE(info) ((u32)(info))
|
||||||
|
|
||||||
|
static bool elf64_validate(const elf64_header_t *hdr) {
|
||||||
|
return !((hdr->MAGIC != ELF_MAGIC)
|
||||||
|
|| (hdr->size != ELF64)
|
||||||
|
|| (hdr->endianness != ELF64_LE)
|
||||||
|
|| (hdr->instruction_set != 62));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *elf_off(const elf64_header_t *hdr, u64 offset) {
|
||||||
|
return (void *)((u8 *)hdr + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline elf64_sect_header_t *elf_sect(const elf64_header_t *hdr, u64 i) {
|
||||||
|
return (elf64_sect_header_t *)((u8 *)hdr
|
||||||
|
+ hdr->sect_header_table_offset
|
||||||
|
+ i * hdr->sect_entry_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 (*elf64_resolve_entry(const elf64_header_t* hdr, void** sect_bases)) () {
|
||||||
|
u64 entry_offset = hdr->prog_entry_offset;
|
||||||
|
|
||||||
|
for(u64 i = 0; i < hdr->sect_entry_count; i++) {
|
||||||
|
elf64_sect_header_t* sh = elf_sect(hdr, i);
|
||||||
|
if(!sect_bases[i]) continue;
|
||||||
|
|
||||||
|
if(entry_offset >= sh->addr && entry_offset < sh->addr + sh->size)
|
||||||
|
return (u64 (*)())((u8*) sect_bases[i] + (entry_offset - sh->addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback: offset into sect 1 (.text)
|
||||||
|
printf("elf64_resolve_entry: using fallback offset into section 1 (.text)\n");
|
||||||
|
if (hdr->sect_entry_count > 1 && sect_bases[1])
|
||||||
|
return (u64 (*)())((u8 *)sect_bases[1] + entry_offset);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void elf64_alloc_section(const elf64_header_t *hdr,
|
||||||
|
const elf64_sect_header_t *sh,
|
||||||
|
void **out) {
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
|
if (sh->type != SHT_PROGBITS && sh->type != SHT_NOBITS) return;
|
||||||
|
if (sh->size == 0) return;
|
||||||
|
|
||||||
|
void *mem = calloc(sh->size, 1);
|
||||||
|
if (!mem) {
|
||||||
|
print("elf64: calloc failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sh->type == SHT_PROGBITS) {
|
||||||
|
u8 *src = (u8 *)elf_off(hdr, sh->offset);
|
||||||
|
u8 *dst = (u8 *)mem;
|
||||||
|
for (u64 b = 0; b < sh->size; b++)
|
||||||
|
dst[b] = src[b];
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void **elf64_alloc_sections(const elf64_header_t *hdr) {
|
||||||
|
u64 n = hdr->sect_entry_count;
|
||||||
|
|
||||||
|
void **bases = calloc(n, sizeof(void *));
|
||||||
|
if (!bases) {
|
||||||
|
print("elf64: calloc failed for section table\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u64 i = 0; i < n; i++)
|
||||||
|
elf64_alloc_section(hdr, elf_sect(hdr, i), &bases[i]);
|
||||||
|
|
||||||
|
return bases;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void elf64_apply_rela(const elf64_rela_t *rela,
|
||||||
|
const elf64_sym_t *symtab,
|
||||||
|
void **section_bases,
|
||||||
|
void *target_base) {
|
||||||
|
u64 sym_idx = RELA_SYM(rela->info);
|
||||||
|
u32 rel_type = RELA_TYPE(rela->info);
|
||||||
|
|
||||||
|
const elf64_sym_t* sym = &symtab[sym_idx];
|
||||||
|
|
||||||
|
u64 s = (sym->sect_index != 0 && section_bases[sym->sect_index])?
|
||||||
|
(u64)section_bases[sym->sect_index] + sym->value : 0;
|
||||||
|
|
||||||
|
i64 offset = rela->addend;
|
||||||
|
u64 reference = (u64)target_base + rela->offset;
|
||||||
|
|
||||||
|
switch(rel_type) {
|
||||||
|
case R_X86_64_64:
|
||||||
|
*(u64*)reference = (u64)(s+offset);
|
||||||
|
break;
|
||||||
|
case R_X86_64_32:
|
||||||
|
*(u32*)reference = (u32)(s+offset);
|
||||||
|
break;
|
||||||
|
case R_X86_64_32S:
|
||||||
|
*(i32*)reference = (i32)(s+offset);
|
||||||
|
break;
|
||||||
|
case R_X86_64_PC32:
|
||||||
|
case R_X86_64_PLT32:
|
||||||
|
*(i32*)reference = (i32)(s+offset - (i64)reference);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("elf64_apply_rela: unhandled relocation type\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void elf64_process_rela_section(const elf64_header_t *hdr,
|
||||||
|
const elf64_sect_header_t *rela_sh,
|
||||||
|
void **section_bases) {
|
||||||
|
u64 target_idx = rela_sh->info;
|
||||||
|
if (!section_bases[target_idx]) return;
|
||||||
|
|
||||||
|
elf64_sect_header_t *sym_sh = elf_sect(hdr, rela_sh->link);
|
||||||
|
elf64_sym_t *symtab = (elf64_sym_t *)elf_off(hdr, sym_sh->offset);
|
||||||
|
elf64_rela_t *relas = (elf64_rela_t *)elf_off(hdr, rela_sh->offset);
|
||||||
|
u64 n_relas = rela_sh->size / sizeof(elf64_rela_t);
|
||||||
|
|
||||||
|
for (u64 r = 0; r < n_relas; r++)
|
||||||
|
elf64_apply_rela(&relas[r], symtab, section_bases, section_bases[target_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void elf64_relocate(const elf64_header_t *hdr, void **section_bases) {
|
||||||
|
for (u64 i = 0; i < hdr->sect_entry_count; i++) {
|
||||||
|
elf64_sect_header_t *sh = elf_sect(hdr, i);
|
||||||
|
if (sh->type == SHT_RELA)
|
||||||
|
elf64_process_rela_section(hdr, sh, section_bases);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 elf64_load(elf64_header_t* hdr) {
|
||||||
|
if(!hdr || !elf64_validate(hdr)) {
|
||||||
|
printf("elf64_load: Invalid ELF64 header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void** sect_bases = elf64_alloc_sections(hdr);
|
||||||
|
if(!sect_bases) {
|
||||||
|
printf("elf64_load: Failed to allocate sections.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
elf64_relocate(hdr, sect_bases);
|
||||||
|
|
||||||
|
u64 (*entry)() = elf64_resolve_entry(hdr, sect_bases);
|
||||||
|
|
||||||
|
if(!entry) {
|
||||||
|
printf("elf64_load: failed to resolve entry point\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < 64; i++) {
|
||||||
|
char c = ((char*)entry)[i];
|
||||||
|
print8(c);
|
||||||
|
put(((i & 7) == 7)? '\n' : ' ');
|
||||||
|
}
|
||||||
|
printf("elf64_load: jumping to entry\n");
|
||||||
|
u64 ret = entry();
|
||||||
|
printf("elf64_load: returning");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
6
src/lib/sys.h
Normal file
6
src/lib/sys.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define SYS_OPEN 0
|
||||||
|
#define SYS_SLURP 1
|
||||||
|
|
||||||
|
|
||||||
46
src/main.c
46
src/main.c
@ -16,6 +16,7 @@ void print_tok(struct token* tok);
|
|||||||
#include "fat32.h"
|
#include "fat32.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "lib/stdio.h"
|
#include "lib/stdio.h"
|
||||||
|
#include "lib/elf/elf64.h"
|
||||||
|
|
||||||
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup
|
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup
|
||||||
// code
|
// code
|
||||||
@ -265,24 +266,24 @@ void kmain() {
|
|||||||
|
|
||||||
ahci_init();
|
ahci_init();
|
||||||
|
|
||||||
i8 port = -1;
|
read_active_port = -1;
|
||||||
for(u8 i = 0; i < 32; i++) {
|
for(u8 i = 0; i < 32; i++) {
|
||||||
if(ahci_port_active(i)) {
|
if(ahci_port_active(i)) {
|
||||||
// assume we want the first port
|
// assume we want the first port
|
||||||
if(port < 0)
|
if(read_active_port < 0)
|
||||||
port = i;
|
read_active_port = i;
|
||||||
printf("Port %d is active!\n", i);
|
printf("Port %d is active!\n", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(port < 0) {
|
if(read_active_port < 0) {
|
||||||
printf("Couldn't find a port to read the FS from :(\n");
|
printf("Couldn't find a port to read the FS from :(\n");
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fat32_mbr_t* mbr = alloc(1<<12);
|
fat32_mbr_t* mbr = alloc(1<<12);
|
||||||
ahci_read(port, 0, 1, mbr);
|
ahci_read(read_active_port, 0, 1, mbr);
|
||||||
|
|
||||||
i8 bootpart = -1;
|
i8 bootpart = -1;
|
||||||
fat32_mbr_partition_t bpart;
|
fat32_mbr_partition_t bpart;
|
||||||
@ -307,33 +308,23 @@ void kmain() {
|
|||||||
printf("Failed to find boot partition :(\n");
|
printf("Failed to find boot partition :(\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// reuse buffer
|
// reuse buffer
|
||||||
fat32_bpb_t* bpb = (fat32_bpb_t*) mbr;
|
fat32_bpb_t* bpb = (fat32_bpb_t*) mbr;
|
||||||
mbr = NULL;
|
mbr = NULL;
|
||||||
|
|
||||||
// hardcode for now :(
|
// hardcode for now :(
|
||||||
u32 part_lba = 2048;
|
u32 part_lba = 2048;
|
||||||
ahci_read(port, part_lba, 1, bpb);
|
ahci_read(read_active_port, part_lba, 1, bpb);
|
||||||
|
|
||||||
fat32_vol_t vol = vol_from_bpb(bpb, part_lba);
|
active_vol = vol_from_bpb(bpb, part_lba);
|
||||||
|
|
||||||
u64 root_lba = fat32_cluster_to_lba(&vol, vol.root_cluster);
|
u64 root_lba = fat32_cluster_to_lba(&active_vol, active_vol.root_cluster);
|
||||||
printf("root_lba=%u\n", (u32)root_lba);
|
printf("root_lba=%u\n", (u32)root_lba);
|
||||||
|
|
||||||
u8 *raw = alloc(4096);
|
u8 *raw = alloc(4096);
|
||||||
ahci_read(port, root_lba, vol.sectors_per_cluster, raw);
|
ahci_read(read_active_port, root_lba, active_vol.sectors_per_cluster, raw);
|
||||||
printf("raw: ");
|
|
||||||
for(int i = 0; i < 64; i++)
|
|
||||||
printf("%x ", raw[i]);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
ls(port, 0, &vol, vol.root_cluster);
|
struct FILE* fortune = fat32_find_path(read_active_port, &active_vol, "fort/fortu.ne");
|
||||||
|
|
||||||
struct FILE* fortune = fat32_find_path(port, &vol, "fort/fortu.ne");
|
|
||||||
|
|
||||||
|
|
||||||
printf("Fortune size: %d\n", fortune->info.file_size);
|
|
||||||
|
|
||||||
u8* fort = slurp(fortune);
|
u8* fort = slurp(fortune);
|
||||||
|
|
||||||
@ -341,5 +332,20 @@ void kmain() {
|
|||||||
|
|
||||||
free(fort);
|
free(fort);
|
||||||
|
|
||||||
|
FILE* execfile = fat32_find_path(read_active_port, &active_vol, "/usr/bin/test");
|
||||||
|
|
||||||
|
if(!execfile) {
|
||||||
|
printf("Didn't find executable :(");
|
||||||
|
} else {
|
||||||
|
printf("Found:\n");
|
||||||
|
elf64_header_t* hdr = (elf64_header_t*) slurp(execfile);
|
||||||
|
char* ret = (char*)elf64_load(hdr);
|
||||||
|
printf("AFTER:\n");
|
||||||
|
print64((u64)ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1);
|
||||||
|
|
||||||
|
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,8 +28,8 @@ void print_init(struct limine_framebuffer *fb) {
|
|||||||
static void scrollback() {
|
static void scrollback() {
|
||||||
memmove((void *)fb_scr, (void *)(fb_scr + fb_width * GLYPH_HEIGHT),
|
memmove((void *)fb_scr, (void *)(fb_scr + fb_width * GLYPH_HEIGHT),
|
||||||
fb_width * (fb_height - GLYPH_HEIGHT) * sizeof(u32));
|
fb_width * (fb_height - GLYPH_HEIGHT) * sizeof(u32));
|
||||||
size_t last_row_start = (term_height - 1) * fb_width;
|
size_t last_row_start = (term_height - 1) * GLYPH_HEIGHT * fb_width;
|
||||||
for (size_t i = 0; i < fb_width; i++) {
|
for (size_t i = 0; i < fb_width * GLYPH_HEIGHT; i++) {
|
||||||
fb_scr[last_row_start + i] = bg;
|
fb_scr[last_row_start + i] = bg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
146
src/syscalls.c
Normal file
146
src/syscalls.c
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#include "syscalls.h"
|
||||||
|
#include "int.h"
|
||||||
|
#include "fat32.h"
|
||||||
|
#include "lib/stdio.h"
|
||||||
|
|
||||||
|
static FILE* filetable[256];
|
||||||
|
size_t file_idx = 0;
|
||||||
|
|
||||||
|
|
||||||
|
i8 read_active_port = -1;
|
||||||
|
fat32_vol_t active_vol;
|
||||||
|
|
||||||
|
static void sys_open_impl(struct cpu_ctx* ctx) {
|
||||||
|
printf("Open called on %s\n", ctx->rdi);
|
||||||
|
if(file_idx >= 256) {
|
||||||
|
printf("sys_open: ran out of files");
|
||||||
|
ctx->rax = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filetable[file_idx] = fat32_find_path(read_active_port, &active_vol, (u8*)ctx->rdi);
|
||||||
|
|
||||||
|
if(!filetable[file_idx]) {
|
||||||
|
printf("sys_open: could not find path: %s\n", ctx->rdi);
|
||||||
|
ctx->rax = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->rax = file_idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sys_slurp_impl(struct cpu_ctx* ctx) {
|
||||||
|
printf("SLURP CALLED\n");
|
||||||
|
i64 fd = ctx->rdi;
|
||||||
|
if(fd >= (i64)file_idx || fd < 0) {
|
||||||
|
printf("sys_slurp: ran out of files\m");
|
||||||
|
ctx->rax = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->rax = (u64) slurp(filetable[fd]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static syscall_t syscalls[] = {
|
||||||
|
[SYS_OPEN] sys_open_impl,
|
||||||
|
[SYS_SLURP] sys_slurp_impl,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to dump the contents of cpu_ctx
|
||||||
|
void dump_cpu_ctx(struct cpu_ctx *ctx) {
|
||||||
|
print("CPU Context Dump:\n");
|
||||||
|
|
||||||
|
print("r15: ");
|
||||||
|
print64(ctx->r15);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("r14: ");
|
||||||
|
print64(ctx->r14);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("r13: ");
|
||||||
|
print64(ctx->r13);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("r12: ");
|
||||||
|
print64(ctx->r12);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("r11: ");
|
||||||
|
print64(ctx->r11);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("r10: ");
|
||||||
|
print64(ctx->r10);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("r9: ");
|
||||||
|
print64(ctx->r9);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("r8: ");
|
||||||
|
print64(ctx->r8);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("rdi: ");
|
||||||
|
print64(ctx->rdi);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("rsi: ");
|
||||||
|
print64(ctx->rsi);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("rdx: ");
|
||||||
|
print64(ctx->rdx);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("rcx: ");
|
||||||
|
print64(ctx->rcx);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("rbx: ");
|
||||||
|
print64(ctx->rbx);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("rax: ");
|
||||||
|
print64(ctx->rax);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("vect: ");
|
||||||
|
print64(ctx->vect);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("err: ");
|
||||||
|
print64(ctx->err);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("iret_rip: ");
|
||||||
|
print64(ctx->iret_rip);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("iret_cs: ");
|
||||||
|
print64(ctx->iret_cs);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("iret_flags: ");
|
||||||
|
print64(ctx->iret_flags);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("iret_rsp: ");
|
||||||
|
print64(ctx->iret_rsp);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("iret_ss: ");
|
||||||
|
print64(ctx->iret_ss);
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void syscall_handler(struct cpu_ctx* ctx) {
|
||||||
|
|
||||||
|
dump_cpu_ctx(ctx);
|
||||||
|
|
||||||
|
if(ctx->rax < 2)
|
||||||
|
syscalls[ctx->rax](ctx);
|
||||||
|
|
||||||
|
printf("SYSCALL COMPLETE\n");
|
||||||
|
}
|
||||||
8
src/syscalls.h
Normal file
8
src/syscalls.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "common.h"
|
||||||
|
#include "lib/sys.h"
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
typedef void (*syscall_t)(struct cpu_ctx*);
|
||||||
|
|
||||||
|
void syscall_handler(struct cpu_ctx* ctx);
|
||||||
Loading…
x
Reference in New Issue
Block a user