Compare commits

...

27 Commits

Author SHA1 Message Date
Andrius Štikonas acbf7cc31a
Build posix-runner at the end of stage0-uefi. 2024-01-06 16:22:07 +00:00
Andrius Štikonas f5be5f91b5
Update M2libc with access() fix. 2024-01-06 00:30:21 +00:00
Andrius Štikonas 2d32522f45
Increase MAX_MEMORY_PER_PROC to 768 MiB. 2024-01-03 23:57:44 +00:00
Andrius Štikonas cc3db46d2c
Set FILEDES_MAX to 4096. 2024-01-03 23:51:46 +00:00
Andrius Štikonas 0660f25086
Add file descriptor map. 2024-01-03 22:52:48 +00:00
Andrius Štikonas 6bf7bafb50
Fix a typo. 2024-01-02 00:49:35 +00:00
Andrius Štikonas c0baf959ab
Make sure brk area is zeroed on start.
Some stage0 applications, e.g. M0 assume that newly allocated memory
is empty.

We also need to do that for forked processes but it's not part of this commit.
2024-01-02 00:47:32 +00:00
Andrius Štikonas c7c827a1e9
Fix _brk issues and workaround some M2-Planet assign on initialization bugs. 2024-01-01 22:22:37 +00:00
Andrius Štikonas 008899d565
Add memory allocation failure checks. 2024-01-01 12:28:29 +00:00
Andrius Štikonas a870103aad
Fix argc of the first process. 2024-01-01 00:55:28 +00:00
Andrius Štikonas a34bce78ba
Add sys_chroot. 2023-12-31 21:34:04 +00:00
Andrius Štikonas 0e5f18fa2f
Add sys_uname. 2023-12-31 21:29:04 +00:00
Andrius Štikonas 7ad5f2afac
Free memory of process that exited. 2023-12-31 21:18:01 +00:00
Andrius Štikonas 1cbca175a0
Fix pushing argv onto stack from execve calls. 2023-12-31 20:36:39 +00:00
Andrius Štikonas db2d001395
Simplify argc counting. 2023-12-31 20:05:09 +00:00
Andrius Štikonas ac13be4291
Initial version of sys_fork, sys_execve and sys_wait4.
It is not fully working yet, in particular child programs have broken
initial stack and argv returns garbage.
2023-12-30 23:45:10 +00:00
Andrius Štikonas 4f2a62fa34
Push envp onto a stack of new process. 2023-12-29 21:59:23 +00:00
Andrius Štikonas 1c12f7d869
Add sys_access, sys_chdir and sys_getcwd. 2023-12-29 01:09:00 +00:00
Andrius Štikonas 5385ab3c26
Add sys_unlink. 2023-12-29 00:37:34 +00:00
Andrius Štikonas 9d4a1e2159
Add sys_close. 2023-12-29 00:15:23 +00:00
Andrius Štikonas d9def6dd05
Add sys_mkdir. 2023-12-29 00:06:45 +00:00
Andrius Štikonas 29f38d943a
Just in case make sure to save and restore more registers. 2023-12-28 23:59:12 +00:00
Andrius Štikonas e61e1b16b4 Add sys_brk. 2023-12-28 23:59:04 +00:00
Andrius Štikonas e894942e52 Add sys_lseek. 2023-12-28 23:59:00 +00:00
Andrius Štikonas 572513c916
posix-runner: Add read,write and open syscalls. 2023-12-27 23:10:21 +00:00
Andrius Štikonas ebf61b2e9a Add syscall_table. 2023-12-26 23:57:20 +00:00
Andrius Štikonas ffe3f524a5 Initial version of posix-runner. 2023-12-26 21:30:19 +00:00
6 changed files with 496 additions and 21 deletions

@ -1 +1 @@
Subproject commit e6447d98cf4b2f41e816d8fd336f7251d21d15b2
Subproject commit 0479606ed5131a64cd1dd2dd3f257e73cd9dce68

2
M2libc

@ -1 +1 @@
Subproject commit ff47b1cca5fc6f7591b8572710eabf73198e2de2
Subproject commit c103ee8d5699c5313335d5798b63a8421fd62faa

5
after.kaem Normal file
View File

@ -0,0 +1,5 @@
cd /posix-runner
M2LIBC_PATH=${M2LIBC}
PATH=${BINDIR}
${BINDIR}/M2-Mesoplanet.efi --os UEFI --architecture ${ARCH} --file posix-runner.c --output ${BINDIR}/posix-runner.efi
cd ..

View File

@ -1,18 +1,19 @@
559629a1660cfd18c2399efa641489303f8384af8ba215f3670473d7e1b95553 amd64/bin/blood-elf.efi
eed56eb5f2d2310de367765588eea56d8b538d83312fae09effb42fd4e1c1e6d amd64/bin/catm.efi
8ef921e260361b59a4f6d1a89f1507f272f45f36a8c47549ff305f874e202db2 amd64/bin/chmod.efi
71e52f6e5e115cffdf8873a7bce3aef6fb91edd3cb6ed71eaec38a338982e095 amd64/bin/cp.efi
584ff2bbe12bf842e643c27cd23d9af877f7e9539101b39fc21f08131bc25b58 amd64/bin/get_machine.efi
1cc45ff9c4fd1bd1f3ad01eb4a336d15c66bfbbaa23efb402a9d302f2c90dc60 amd64/bin/hex2.efi
13e54d0ca87e30903058f4f2034dea4f8fce173b06e397866f8a9927bae192b3 amd64/bin/kaem.efi
d55697f2df4546dbcc188df30d2c12943f28f26c07bbe3b9db3d9ef7d496b1da amd64/bin/M1.efi
d5acba35bffddd577c4766be78c97c5537625e70f3ed5e073ccb3182acc9602f amd64/bin/M2-Mesoplanet.efi
a2d929b28f98c249a1b52880c57b670b659f405d5b13f444da2118d6feb7f5d9 amd64/bin/M2-Planet.efi
bdf18f12fe339491ab3570e9c73b44b2b812af9b778dd0eaf6eb11e4722aa0bc amd64/bin/match.efi
aa30d3a3cbaca514661fbd866402218628df7f733ddebf939337953eed5422c7 amd64/bin/mkdir.efi
3ffb47b2ce3efc7e455e9d64e7087e2c5582cda71f99171775c43515dfd365ba amd64/bin/replace.efi
65c6605828d91d5cc14c361634470f9fdc5c10ad9a60d4e74ae240eea2c1f095 amd64/bin/rm.efi
9146cb3a686d24650d8e1bff07599baecee1c3c3633451a0e6648cee305bb5f5 amd64/bin/sha256sum.efi
3312998cab45a4baa9946c68d09d9c2df0043ad579fd329532fa60671c6e6d6e amd64/bin/unbz2.efi
f3ed1e47c4bcf3f244d9d17a28dc98e526ce5744ce50286b9b6817408f626935 amd64/bin/ungz.efi
6dca66a518bba1ad484757fe728aad03e7e6000f9741f94d3896bf8ca3aed265 amd64/bin/untar.efi
f55f51d25cb520adcc811c98284d01af1fa19e96b4034b24af96c796791886ec amd64/bin/blood-elf.efi
8a7e900730aa29f186993d181fc4ac42d56914b2c7138f4dd441acf22622b97d amd64/bin/catm.efi
fe8a9f95d32aa48e48732e1076e7af06ab6ec9a7186f928c5141643264ec1f64 amd64/bin/chmod.efi
64df4d8a355ea6d96eadb6b2dcdbd1bd7d0b33f380fa13d218f19eb69200196a amd64/bin/cp.efi
45bfdaf8354b99017ce914fbf6a0b435c0baa7baa8e056fd84ed465e77f3cc07 amd64/bin/get_machine.efi
191946531f7e0ce33a633e997b2600cae32f386de469e33ecab799f250abb5e6 amd64/bin/hex2.efi
30452e0094ac95a20553776930bca825852612bba9bb0fa710a402702c66050a amd64/bin/kaem.efi
1407fb16c11bc621a03775ef2d8540d77853f1d5d5c245045d7e6e7394695158 amd64/bin/M1.efi
e7559c5aaf546acccf739d2d41f07185c3a6b07bb4b2602ce4621c4f2a254225 amd64/bin/M2-Mesoplanet.efi
c97c3d117a23e0c1b5916e2e1f0b08f1173829afbd0a0cf9d3539031d6c409a8 amd64/bin/M2-Planet.efi
b120fecb59025a3fe472cdf1b7b3ca7c6a234c12c5b1ce134dd159431076f1ef amd64/bin/match.efi
0efba4291b071c04086abd9ee4fa86ced33640341c7c0684323e77016f035ee9 amd64/bin/mkdir.efi
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 amd64/bin/placeholder
d0361b7f5b6554bd7c0352a0669f7311c4156c695410b1c098850157e256d0ee amd64/bin/replace.efi
f50990d93cdd8a58a50d1a94ee3e2156a174ea79f64cb788b03a69e429e6d3a6 amd64/bin/rm.efi
7af6cab98031a0fdc08c00732ca361dd35dff9aa67ca5b94bcfd9b3a09842362 amd64/bin/sha256sum.efi
fe7835923398f65b337c3966a98162f11bd9c7f55ea125b1e9fd55f7e00e7da1 amd64/bin/unbz2.efi
59e7e92605e808d1cce30554027dad5265bc7a72b9d19af28bda3b8daec97c4f amd64/bin/ungz.efi
53eaed2a1518b252996208eec9f42737971152b978ef91038e48490f4a74a566 amd64/bin/untar.efi

View File

@ -36,7 +36,6 @@
-f ./M2libc/${ARCH}/${ARCH}_defs.M1 \
-f ./M2libc/${ARCH}/uefi/libc-full.M1 \
-f ./${ARCH_DIR}/artifact/M2-1.M1 \
-f ./${ARCH_DIR}/artifact/M2-1-footer.M1 \
-o ./${ARCH_DIR}/artifact/M2-1.hex2
./${ARCH_DIR}/bin/hex2.efi --architecture ${ARCH} \

470
posix-runner/posix-runner.c Normal file
View File

@ -0,0 +1,470 @@
/*
* SPDX-FileCopyrightText: 2023 Andrius Štikonas <andrius@stikonas.eu>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <bootstrappable.h>
#define MSR_EFER (0x60000080 + 0x60000000)
#define MSR_STAR (0x60000081 + 0x60000000)
#define MSR_LSTAR (0x60000082 + 0x60000000)
void* syscall_table;
#define MAX_MEMORY_PER_PROC (768 * 1024 * 1024)
#define __FILEDES_MAX 4096
struct mem_block {
void* address;
int length;
};
struct process {
struct process* parent;
void* entry_point;
void* brk;
void* saved_brk;
void* stack;
void* saved_stack_pointer;
mem_block program;
mem_block saved_stack;
mem_block saved_memory;
int child_exit_code;
int forked;
int fd_map[__FILEDES_MAX];
};
struct process* current_process;
void* _brk;
void* _get_stack()
{
asm("mov_rax,rsp");
}
void* get_stack()
{
/* Adjust to stack depth of _get_stack function */
return _get_stack() + (7 * sizeof(void *));
}
int extract_field(char* file_data, int position, int length)
{
void* data;
memcpy(&data, file_data + position, length);
return data;
}
int load_elf(FILE* file_in, struct process* current)
{
int file_size = fseek(file_in, 0, SEEK_END);
char* file_data = calloc(1, file_size + 0x1000); /* Allocate extra space in case application tries to use it */
if (file_data == NULL) {
fputs("Could not allocate memory to load ELF file.", stderr);
exit(1);
}
rewind(file_in);
fread(file_data, 1, file_size, file_in);
fclose(file_in);
if ((file_data[0] != 0x7F) || (file_data[1] != 'E') ||
(file_data[2] != 'L') || (file_data[3] != 'F')) {
return 1;
}
current->program.address = file_data;
current->program.length = file_size;
return 0;
}
void* entry_point(char* raw_elf)
{
int entry_point = extract_field(raw_elf, 24, 8);
int header_table = extract_field(raw_elf, 32, 8);
int base_address = extract_field(raw_elf, header_table + 0x10, 8);
return entry_point - base_address + raw_elf;
}
void jump(void* start_address, int argc, int argc0, char** argv, char** envp)
{
int argc_new;
current_process->stack = get_stack();
char* temp;
asm("push !0");
for (; *envp != 0; envp += sizeof(char *)) {
temp = *envp;
asm("push_rax");
}
int i;
for (i = argc; i >= argc0; i -= 1) {
temp = argv[i];
asm("push_rax");
}
argc_new = argc - argc0;
asm("push_rax");
asm("lea_rcx,[rbp+DWORD] %-8"
"mov_rcx,[rcx]"
"jmp_rcx"
);
}
void init_io()
{
current_process->fd_map[STDIN_FILENO] = STDIN_FILENO;
current_process->fd_map[STDOUT_FILENO] = STDOUT_FILENO;
current_process->fd_map[STDERR_FILENO] = STDERR_FILENO;
}
int find_free_fd()
{
int i;
for (i = 3; i < __FILEDES_MAX; i += 1) {
if (current_process->fd_map[i] == NULL) {
return i;
}
}
return -1;
}
int sys_read(int fd, char* buf, unsigned count, void, void, void)
{
return read(current_process->fd_map[fd], buf, count);
}
int sys_write(int fd, char* buf, unsigned count, void, void, void)
{
return write(current_process->fd_map[fd], buf, count);
}
int sys_open(char* name, int flag, int mode, void, void, void)
{
int rval;
int fd;
rval = open(name, flag, mode);
fd = find_free_fd();
current_process->fd_map[fd] = rval;
return fd;
}
int sys_close(int fd, void, void, void, void, void)
{
int rval;
rval = close(current_process->fd_map[fd]);
current_process->fd_map[fd] = NULL;
return rval;
}
int sys_lseek(int fd, int offset, int whence, void, void, void)
{
return lseek(current_process->fd_map[fd], offset, whence);
}
int sys_brk(void* addr, void, void, void, void, void)
{
if (current_process->brk == NULL) {
current_process->brk = _brk;
}
if (addr == NULL) {
return current_process->brk;
}
else {
current_process->brk = addr;
return current_process->brk;
}
}
int sys_access(char* pathname, int mode, void, void, void, void)
{
return access(pathname, mode);
}
int sys_fork(void, void, void, void, void, void)
{
current_process->saved_brk = current_process->brk;
current_process->saved_stack_pointer = get_stack();
current_process->forked = TRUE;
current_process->saved_stack.length = current_process->stack - current_process->saved_stack_pointer;
current_process->saved_stack.address = malloc(current_process->saved_stack.length);
if (current_process->saved_stack.address == NULL ) {
fputs("Could not allocate memory for saved process stack.", stderr);
exit(1);
}
memcpy(current_process->saved_stack.address, current_process->saved_stack_pointer, current_process->saved_stack.length);
current_process->saved_memory.length = current_process->brk - _brk;
current_process->saved_memory.address = malloc(current_process->saved_memory.length);
if (current_process->saved_stack.address == NULL ) {
fputs("Could not allocate memory for saved process memory.", stderr);
exit(1);
}
memcpy(current_process->saved_memory.address, _brk, current_process->saved_memory.length);
return 0; /* return as child */
}
int sys_execve(char* file_name, char** argv, char** envp, void, void, void)
{
if (current_process->forked) {
struct process* new;
new = calloc(1, sizeof(struct process));
if (new == NULL) {
fputs("Could not allocate memory for new process metadata.", stderr);
exit(1);
}
new->parent = current_process;
current_process->forked = FALSE; /* fork was handled */
current_process = new;
init_io();
}
// else {
// restore_stack(current_process->saved_stack); // FIXME
// }
FILE* file_in;
file_in = fopen(file_name, "r");
if (file_in == NULL) {
return -1;
}
int rval;
rval = load_elf(file_in, current_process);
if (rval == 1) {
return -1;
}
current_process->entry_point = entry_point(current_process->program.address);
int argc;
for(argc = 0; argv[argc] != 0; argc += 1) {}
jump(current_process->entry_point, argc, 0, argv, envp);
}
void sys_exit(unsigned value, void, void, void, void, void)
{
if (current_process->parent == NULL) {
exit(value);
}
current_process->parent->child_exit_code = value;
struct process* child;
child = current_process;
current_process = current_process->parent;
free(child);
memcpy(current_process->saved_stack_pointer, current_process->saved_stack.address, current_process->saved_stack.length);
memcpy(_brk, current_process->saved_memory.address, current_process->saved_memory.length);
free(current_process->saved_stack.address);
free(current_process->saved_memory.address);
current_process->brk = current_process->saved_brk;
current_process->saved_stack_pointer;
/* Simulate return from sys_fork() */
asm("mov_rsp,rax"
"mov_rax, %1"
"ret"
);
}
int sys_wait4(int pid, int* status_ptr, int options)
{
*status_ptr = current_process->child_exit_code << 8;
return 0;
}
int sys_uname(struct utsname* unameData)
{
return uname(unameData);
}
int sys_getcwd(char* buf, int size, void, void, void, void)
{
return getcwd(buf, size);
}
int sys_chdir(char* path, void, void, void, void, void)
{
return chdir(path);
}
int sys_fchdir(int fd, void, void, void, void, void)
{
return fchdir(current_process->fd_map[fd]);
}
int sys_mkdir(char const* a, mode_t b, void, void, void, void)
{
return mkdir(a, b);
}
int sys_unlink(char* filename, void, void, void, void, void)
{
return unlink(filename);
}
int sys_chroot(char const *path)
{
return chroot(path);
}
void init_syscalls()
{
syscall_table = calloc(300, sizeof(void *));
if (syscall_table == NULL) {
fputs("Could not allocate memory for syscall table.", stderr);
exit(1);
}
syscall_table[0] = sys_read;
syscall_table[1] = sys_write;
syscall_table[2] = sys_open;
syscall_table[3] = sys_close;
syscall_table[8] = sys_lseek;
syscall_table[12] = sys_brk;
syscall_table[21] = sys_access;
syscall_table[57] = sys_fork;
syscall_table[59] = sys_execve;
syscall_table[60] = sys_exit;
syscall_table[61] = sys_wait4;
syscall_table[63] = sys_uname;
syscall_table[79] = sys_getcwd;
syscall_table[80] = sys_chdir;
syscall_table[81] = sys_fchdir;
syscall_table[83] = sys_mkdir;
syscall_table[87] = sys_unlink;
syscall_table[161] = sys_chroot;
}
void wrmsr(unsigned msr, int low, int high)
{
asm("lea_rcx,[rbp+DWORD] %-8"
"mov_rcx,[rcx]"
"lea_rax,[rbp+DWORD] %-16"
"mov_rax,[rax]"
"lea_rdx,[rbp+DWORD] %-24"
"mov_rdx,[rdx]"
"wrmsr"
);
}
void wrmsrl(unsigned msr, long value)
{
wrmsr(msr, value && 0xFFFFFFFF, value >> 32);
}
ulong rdmsrl(unsigned msr)
{
asm("lea_rcx,[rbp+DWORD] %-8"
"mov_rcx,[rcx]"
"rdmsr"
"shr_rdx, !20"
"add_rax,rdx"
);
}
void _entry_syscall(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
{
FUNCTION process_syscall = syscall_table[syscall];
if (process_syscall != NULL) {
return process_syscall(arg1, arg2, arg3, arg4, arg5, arg6);
}
/* Unsupported syscall */
return 0;
}
void entry_syscall()
{
/* Fix SS register */
asm("push_rax"
"mov_rax, %0x30"
"mov_ss,eax"
"pop_rax"
);
/* Save registers */
asm("push_rcx"
"push_rbx"
"push_rbp"
"push_r12"
"push_r13"
"push_r14"
"push_r15"
);
asm("mov_rbp,rsp"
"push_rax"
"push_rdi"
"push_rsi"
"push_rdx"
"push_r10"
"push_r8"
"push_r9"
"call %FUNCTION__entry_syscall"
"pop_r9"
"pop_r8"
"pop_r10"
"pop_rdx"
"pop_rsi"
"pop_rdi"
"pop_rbx" /* rax is return code, do not overwrite it */
);
/* Restore registers */
asm("pop_r15"
"pop_r14"
"pop_r13"
"pop_r12"
"pop_rbp"
"pop_rbx"
"pop_rcx"
);
/* Jump back to POSIX program */
asm("jmp_rcx");
}
int main(int argc, char** argv, char** envp)
{
if (argc < 2) {
fputs("Usage: ", stderr);
fputs(argv[0], stderr);
fputs(" <elf file> [arguments]\n", stderr);
exit(1);
}
FILE* file_in = fopen(argv[1], "r");
if (file_in == NULL) {
fputs("Error opening input file.\n", stderr);
exit(2);
}
current_process = calloc(1, sizeof(struct process));
if (current_process == NULL) {
fputs("Could not allocate memory for current process metadata.", stderr);
exit(3);
}
init_io();
_brk = calloc(1, MAX_MEMORY_PER_PROC);
if (_brk == NULL) {
fputs("Could not allocate memory for brk area.", stderr);
exit(4);
}
/* Load binary into memory */
int rval = load_elf(file_in, current_process);
if (rval == 1) {
fputs("ELF magic header was not found.\n", stderr);
exit(5);
}
current_process->entry_point = entry_point(current_process->program.address);
ulong msr_efer = rdmsrl(MSR_EFER);
msr_efer |= 1; /* Enable syscalls */
ulong msr_star = rdmsrl(MSR_STAR);
msr_star |= 0x38 << 32;
wrmsrl(MSR_STAR, msr_star);
wrmsrl(MSR_EFER, msr_efer);
wrmsrl(MSR_LSTAR, entry_syscall);
init_syscalls();
int argc0 = 1; /* skip argv[0] since it contains the name of efi binary */
jump(current_process->entry_point, argc, argc0, argv, envp);
return 1;
}