mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-16 07:57:13 -04:00
Add support for passing arguments to programs
This commit is contained in:
parent
7b204df77a
commit
ef95c110bd
@ -8,6 +8,7 @@
|
||||
#ifndef SCHEDULER_H
|
||||
#define SCHEDULER_H
|
||||
|
||||
#include <vector.hpp>
|
||||
#include <string.hpp>
|
||||
|
||||
#include "process.hpp"
|
||||
@ -24,7 +25,7 @@ void unblock_process(pid_t pid);
|
||||
|
||||
void init();
|
||||
|
||||
int64_t exec(const std::string& path);
|
||||
int64_t exec(const std::string& path, const std::vector<std::string>& params);
|
||||
|
||||
void kill_current_process();
|
||||
void await_termination(pid_t pid);
|
||||
|
@ -122,6 +122,7 @@ void setup_vesa(){
|
||||
vesa::vbe_info_block.signature[1] = 'B';
|
||||
vesa::vbe_info_block.signature[2] = 'E';
|
||||
vesa::vbe_info_block.signature[3] = '2';
|
||||
return;
|
||||
|
||||
uint16_t return_code;
|
||||
asm volatile ("int 0x10"
|
||||
|
@ -141,8 +141,10 @@ void gc_task(){
|
||||
|
||||
//TODO tsh should be configured somewhere
|
||||
void init_task(){
|
||||
std::vector<std::string> params;
|
||||
|
||||
while(true){
|
||||
auto pid = scheduler::exec("tsh");
|
||||
auto pid = scheduler::exec("tsh", params);
|
||||
scheduler::await_termination(pid);
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
@ -464,25 +466,84 @@ bool create_paging(char* buffer, scheduler::process_t& process){
|
||||
return true;
|
||||
}
|
||||
|
||||
void init_context(scheduler::process_t& process, const char* buffer){
|
||||
void init_context(scheduler::process_t& process, const char* buffer, const std::string& file, const std::vector<std::string>& params){
|
||||
auto header = reinterpret_cast<const elf::elf_header*>(buffer);
|
||||
|
||||
auto pages = scheduler::user_stack_size / paging::PAGE_SIZE;
|
||||
|
||||
physical_pointer phys_ptr(process.physical_user_stack, pages);
|
||||
|
||||
auto rsp = phys_ptr.get() + scheduler::user_stack_size - 8;
|
||||
rsp -= sizeof(interrupt::syscall_regs) * 8;
|
||||
//1. Compute the size of the arguments on the stack
|
||||
|
||||
//One pointer for each args
|
||||
size_t args_size = sizeof(size_t) * (1 + params.size());
|
||||
|
||||
//Add the size of the default argument (+ terminating char)
|
||||
args_size += file.size() + 1;
|
||||
|
||||
//Add the size of all the other arguments (+ terminating char)
|
||||
for(auto& param : params){
|
||||
args_size += param.size() + 1;
|
||||
}
|
||||
|
||||
//Align the size on 16 bytes
|
||||
if(args_size % 16 != 0){
|
||||
args_size = ((args_size / 16) + 1) * 16;
|
||||
}
|
||||
|
||||
//2. Modify the stack to add the args
|
||||
|
||||
auto rsp = phys_ptr.get() + scheduler::user_stack_size - 8;
|
||||
auto arrays_start = scheduler::user_rsp - sizeof(size_t) * (1 + params.size());
|
||||
|
||||
//Add pointer to each string
|
||||
size_t acc = 0;
|
||||
for(int64_t i = params.size() - 1; i >= 0; --i){
|
||||
auto& param = params[i];
|
||||
|
||||
acc += param.size();
|
||||
|
||||
*(reinterpret_cast<size_t*>(rsp)) = arrays_start - acc;
|
||||
rsp -= sizeof(size_t);
|
||||
|
||||
++acc;
|
||||
}
|
||||
|
||||
//Add pointer to the default argument string
|
||||
*(reinterpret_cast<size_t*>(rsp)) = arrays_start - acc - file.size();
|
||||
rsp -= sizeof(size_t);
|
||||
|
||||
//Add the strings of the arguments
|
||||
for(int64_t i = params.size() - 1; i >= 0; --i){
|
||||
auto& param = params[i];
|
||||
|
||||
*(reinterpret_cast<char*>(rsp--)) = '\0';
|
||||
for(int64_t j = param.size() - 1; j >= 0; --j){
|
||||
*(reinterpret_cast<char*>(rsp--)) = param[j];
|
||||
}
|
||||
}
|
||||
|
||||
//Add the the string of the default argument
|
||||
*(reinterpret_cast<char*>(rsp--)) = '\0';
|
||||
for(int64_t i = file.size() - 1; i >= 0; --i){
|
||||
*(reinterpret_cast<char*>(rsp--)) = file[i];
|
||||
}
|
||||
|
||||
//3. Modify the stack to configure the context
|
||||
|
||||
rsp = phys_ptr.get() + scheduler::user_stack_size - sizeof(interrupt::syscall_regs) - 8 - args_size;
|
||||
auto regs = reinterpret_cast<interrupt::syscall_regs*>(rsp);
|
||||
|
||||
regs->rsp = scheduler::user_rsp - sizeof(interrupt::syscall_regs) * 8; //Not sure about that
|
||||
regs->rsp = scheduler::user_rsp - sizeof(interrupt::syscall_regs) - args_size; //Not sure about that
|
||||
regs->rip = header->e_entry;
|
||||
regs->cs = gdt::USER_CODE_SELECTOR + 3;
|
||||
regs->ds = gdt::USER_DATA_SELECTOR + 3;
|
||||
regs->rflags = 0x200;
|
||||
|
||||
process.context = reinterpret_cast<interrupt::syscall_regs*>(scheduler::user_rsp - sizeof(interrupt::syscall_regs) * 8);
|
||||
regs->rdi = 1 + params.size(); //argc
|
||||
regs->rsi = scheduler::user_rsp - params.size() * sizeof(size_t); //argv
|
||||
|
||||
process.context = reinterpret_cast<interrupt::syscall_regs*>(scheduler::user_rsp - sizeof(interrupt::syscall_regs) - args_size);
|
||||
}
|
||||
|
||||
void start() __attribute__((noreturn));
|
||||
@ -519,7 +580,7 @@ void scheduler::init(){ //Create the idle task
|
||||
pcb[current_pid].state = scheduler::process_state::RUNNING;
|
||||
}
|
||||
|
||||
int64_t scheduler::exec(const std::string& file){
|
||||
int64_t scheduler::exec(const std::string& file, const std::vector<std::string>& params){
|
||||
//TODO Once shell removed, start will be called in init()
|
||||
if(!started){
|
||||
start();
|
||||
@ -559,7 +620,7 @@ int64_t scheduler::exec(const std::string& file){
|
||||
process.brk_start = program_break;
|
||||
process.brk_end = program_break;
|
||||
|
||||
init_context(process, buffer);
|
||||
init_context(process, buffer, file, params);
|
||||
|
||||
queue_process(process.pid);
|
||||
|
||||
|
@ -706,7 +706,8 @@ void readelf_command(const std::vector<std::string>& params){
|
||||
|
||||
void exec_command(const std::vector<std::string>&){
|
||||
//Fake exec just to start() the scheduler
|
||||
scheduler::exec("");
|
||||
std::vector<std::string> params;
|
||||
scheduler::exec("", params);
|
||||
}
|
||||
|
||||
void vesainfo_command(const std::vector<std::string>&){
|
||||
|
@ -42,7 +42,8 @@ void sc_sleep_ms(interrupt::syscall_regs* regs){
|
||||
void sc_exec(interrupt::syscall_regs* regs){
|
||||
auto file = reinterpret_cast<char*>(regs->rbx);
|
||||
|
||||
regs->rax = scheduler::exec(file);
|
||||
std::vector<std::string> params;
|
||||
regs->rax = scheduler::exec(file, params);
|
||||
}
|
||||
|
||||
void sc_await_termination(interrupt::syscall_regs* regs){
|
||||
|
Loading…
x
Reference in New Issue
Block a user