Compare commits

...

2 Commits

Author SHA1 Message Date
Bananymous aaff5a65e1 Kernel/init: /dev/tty is now custom symlink to controlling terminal
kernel now passes the name of default console to init process so init
knows which file to open as stdio. before /dev/tty was referencing the
system wide current terminal which was inherited from cmdline. This
doesn't work anymore as we have pseudo terminals implemented that can
chage the current terminal during runtime :D
2024-11-17 22:38:52 +02:00
Bananymous 458a362f98 Kernel: Allow kernel to pass arguments to init process 2024-11-17 22:38:02 +02:00
5 changed files with 84 additions and 52 deletions

View File

@ -45,7 +45,7 @@ namespace Kernel
public:
static Process* create_kernel();
static Process* create_kernel(entry_t, void*);
static BAN::ErrorOr<Process*> create_userspace(const Credentials&, BAN::StringView);
static BAN::ErrorOr<Process*> create_userspace(const Credentials&, BAN::StringView path, BAN::Span<BAN::StringView> arguments);
~Process();
void cleanup_function();
@ -185,7 +185,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_load_keymap(const char* path);
TTY& tty() { ASSERT(m_controlling_terminal); return *m_controlling_terminal; }
BAN::RefPtr<TTY> controlling_terminal() { return m_controlling_terminal; }
static Process& current() { return Thread::current().process(); }

View File

@ -108,7 +108,7 @@ namespace Kernel
return process;
}
BAN::ErrorOr<Process*> Process::create_userspace(const Credentials& credentials, BAN::StringView path)
BAN::ErrorOr<Process*> Process::create_userspace(const Credentials& credentials, BAN::StringView path, BAN::Span<BAN::StringView> arguments)
{
auto* process = create_process(credentials, 0);
TRY(process->m_credentials.initialize_supplementary_groups());
@ -124,9 +124,13 @@ namespace Kernel
auto executable = TRY(ELF::load_from_inode(executable_inode, process->m_credentials, process->page_table()));
process->m_mapped_regions = BAN::move(executable.regions);
char** argv = nullptr;
char** argv_addr = nullptr;
{
size_t needed_bytes = sizeof(char*) * 2 + path.size() + 1;
size_t needed_bytes = sizeof(char*) + path.size() + 1;
for (auto argument : arguments)
needed_bytes += sizeof(char*) + argument.size() + 1;
needed_bytes += sizeof(char*);
if (auto rem = needed_bytes % PAGE_SIZE)
needed_bytes += PAGE_SIZE - rem;
@ -135,18 +139,33 @@ namespace Kernel
needed_bytes,
{ .start = 0x400000, .end = KERNEL_OFFSET },
MemoryRegion::Type::PRIVATE,
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present
PageTable::Flags::UserSupervisor | PageTable::Flags::Present
));
argv_addr = reinterpret_cast<char**>(argv_region->vaddr());
uintptr_t temp = argv_region->vaddr() + sizeof(char*) * 2;
MUST(argv_region->copy_data_to_region(0, (const uint8_t*)&temp, sizeof(char*)));
uintptr_t offset = sizeof(char*) * (1 + arguments.size() + 1);
for (size_t i = 0; i <= arguments.size(); i++)
{
const uintptr_t addr = argv_region->vaddr() + offset;
TRY(argv_region->copy_data_to_region(i * sizeof(char*), reinterpret_cast<const uint8_t*>(&addr), sizeof(char*)));
temp = 0;
MUST(argv_region->copy_data_to_region(sizeof(char*), (const uint8_t*)&temp, sizeof(char*)));
dprintln("argv[{}] = {H}", i * sizeof(char*), addr);
MUST(argv_region->copy_data_to_region(sizeof(char*) * 2, (const uint8_t*)path.data(), path.size()));
const auto current = (i == 0) ? path : arguments[i - 1];
TRY(argv_region->copy_data_to_region(offset, reinterpret_cast<const uint8_t*>(current.data()), current.size()));
MUST(process->m_mapped_regions.push_back(BAN::move(argv_region)));
dprintln(" argv[{}] = '{}'", offset, current);
const uint8_t zero = 0;
TRY(argv_region->copy_data_to_region(offset + current.size(), &zero, 1));
offset += current.size() + 1;
}
const uintptr_t zero = 0;
TRY(argv_region->copy_data_to_region((1 + arguments.size()) * sizeof(char*), reinterpret_cast<const uint8_t*>(&zero), sizeof(char*)));
TRY(process->m_mapped_regions.push_back(BAN::move(argv_region)));
}
if (executable_inode->mode().mode & +Inode::Mode::ISUID)
@ -164,8 +183,8 @@ namespace Kernel
process->m_is_userspace = true;
process->m_userspace_info.entry = executable.entry_point;
process->m_userspace_info.argc = 1;
process->m_userspace_info.argv = argv;
process->m_userspace_info.argc = 1 + arguments.size();
process->m_userspace_info.argv = argv_addr;
process->m_userspace_info.envp = nullptr;
auto* thread = MUST(Thread::create_userspace(process, process->page_table()));

View File

@ -20,6 +20,42 @@
namespace Kernel
{
class DevTTY : public TmpInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<DevTTY>> create(mode_t mode, uid_t uid, gid_t gid)
{
return TRY(BAN::RefPtr<DevTTY>::create(mode | Inode::Mode::IFLNK, uid, gid));
}
protected:
BAN::ErrorOr<BAN::String> link_target_impl() override
{
auto terminal = Process::current().controlling_terminal();
if (!terminal)
return BAN::Error::from_errno(ENODEV);
return TRY(BAN::String::formatted("/dev/{}", terminal->name()));
}
bool can_read_impl() const override { return false; }
bool can_write_impl() const override { return false; }
bool has_error_impl() const override { return false; }
private:
DevTTY(mode_t mode, uid_t uid, gid_t gid)
: TmpInode(
DevFileSystem::get(),
MUST(DevFileSystem::get().allocate_inode(create_inode_info(mode, uid, gid))),
create_inode_info(mode, uid, gid)
)
{
ASSERT(this->mode().iflnk());
}
private:
friend class BAN::RefPtr<DevTTY>;
};
static BAN::RefPtr<TTY> s_tty;
static dev_t next_tty_rdev()
@ -51,20 +87,6 @@ namespace Kernel
{
s_tty = this;
clear();
auto inode_or_error = DevFileSystem::get().root_inode()->find_inode("tty"_sv);
if (inode_or_error.is_error())
{
if (inode_or_error.error().get_error_code() == ENOENT)
DevFileSystem::get().add_inode("tty"_sv, MUST(TmpSymlinkInode::create_new(DevFileSystem::get(), 0666, 0, 0, s_tty->name())));
else
dwarnln("{}", inode_or_error.error());
return;
}
auto inode = inode_or_error.release_value();
if (inode->mode().iflnk())
MUST(static_cast<TmpSymlinkInode&>(*inode.ptr()).set_link_target(name()));
}
BAN::ErrorOr<void> TTY::tty_ctrl(int command, int flags)
@ -138,6 +160,8 @@ namespace Kernel
auto* thread = MUST(Thread::create_kernel(&TTY::keyboard_task, nullptr, nullptr));
MUST(Processor::scheduler().add_thread(thread));
DevFileSystem::get().add_inode("tty", MUST(DevTTY::create(0666, 0, 0)));
initialized = true;
}

View File

@ -254,7 +254,11 @@ static void init2(void*)
TTY::initialize_devices();
MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"_sv));
MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"_sv, {}));
auto console_path = MUST(BAN::String::formatted("/dev/{}", cmdline.console));
auto console_path_sv = console_path.sv();
MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"_sv, BAN::Span<BAN::StringView>(&console_path_sv, 1)));
}
extern "C" void ap_main()

View File

@ -2,7 +2,6 @@
#include <BAN/Optional.h>
#include <BAN/Vector.h>
#include <ctype.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdio.h>
@ -11,18 +10,16 @@
#include <sys/banan-os.h>
#include <termios.h>
void initialize_stdio()
int main(int argc, char** argv)
{
const char* tty = "/dev/tty";
if (open(tty, O_RDONLY | O_TTY_INIT) != 0) _exit(1);
if (open(tty, O_WRONLY) != 1) _exit(1);
if (open(tty, O_WRONLY) != 2) _exit(1);
if (open("/dev/debug", O_WRONLY) != 3) _exit(1);
}
ASSERT(argc == 2);
int main()
{
initialize_stdio();
const char* tty_name = argv[1];
if (open(tty_name, O_RDONLY | O_TTY_INIT) != 0) _exit(1);
if (open(tty_name, O_WRONLY) != 1) _exit(1);
if (open(tty_name, O_WRONLY) != 2) _exit(1);
if (open("/dev/debug", O_WRONLY) != 3) _exit(1);
if (signal(SIGINT, [](int) {}) == SIG_ERR)
perror("signal");
@ -80,18 +77,6 @@ int main()
if (pwd == nullptr)
continue;
if (chown("/dev/tty", pwd->pw_uid, pwd->pw_gid) == -1)
{
perror("chown");
continue;
}
if (chmod("/dev/tty", 0600) == -1)
{
perror("chmod");
continue;
}
pid_t pid = fork();
if (pid == 0)
{