mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-28 16:17:51 +01:00
TarFs: janky tarfs for initramfs
This commit is contained in:
@@ -60,6 +60,9 @@ void PS2Keyboard::this_pooler() {
|
||||
case 0x34:
|
||||
r = 'g';
|
||||
break;
|
||||
case 0x4A:
|
||||
r = '/';
|
||||
break;
|
||||
case 0x3C:
|
||||
r = 'u';
|
||||
break;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <FbTty.hpp>
|
||||
#include <LimineFramebuffer.hpp>
|
||||
#include <TarFs.hpp>
|
||||
|
||||
void templates_tester() {
|
||||
// GlobalTtyManager.all_tty_putstr("Testing templates\n");
|
||||
@@ -53,31 +54,33 @@ void ktask_main() {
|
||||
|
||||
(new Task(Task::TaskMode::TASKMODE_KERN, templates_tester, "templates_tester"))->start();
|
||||
(new Task(Task::TaskMode::TASKMODE_KERN, templates_tester, "templates_tester2"))->start();
|
||||
VFSGlobals::mounts.add_mount(new MemFs(&VFSGlobals::root));
|
||||
(new Task(Task::TaskMode::TASKMODE_KERN, vfs_tester, "vfs_tester"))->start();
|
||||
Task *init;
|
||||
// (new Task(Task::TaskMode::TASKMODE_KERN, vfs_tester, "vfs_tester"))->start();
|
||||
for (int i = 0; i < saved_modules_size; i++) {
|
||||
auto &mod = saved_modules[i];
|
||||
|
||||
VFSApi::touch(StrToPath(saved_modules_names[i]));
|
||||
FDT::FD fd = VFSApi::open(StrToPath(saved_modules_names[i]));
|
||||
File *f = VFSApi::get(fd);
|
||||
f->write(static_cast<const char *>(mod.address), mod.size);
|
||||
|
||||
if (strcmp(saved_modules_names[i], "/init") == 0) {
|
||||
Vector<char> read_data(mod.size);
|
||||
memcpy(read_data.begin(), mod.address, mod.size);
|
||||
ElfParser elfParser(std::move(read_data));
|
||||
|
||||
init = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), saved_modules_names[i]);
|
||||
if (!elfParser.copy_to(init))
|
||||
assert2(false, "Init couldn't be loaded!");
|
||||
if (strcmp(saved_modules_names[i], "/sysroot.tar") == 0) {
|
||||
VFSGlobals::mounts.add_mount(new TarFs((char *) mod.address, mod.size, &VFSGlobals::root));
|
||||
}
|
||||
|
||||
VFSApi::close(fd);
|
||||
}
|
||||
GlobalTtyManager.all_tty_putstr("Setup finished \n");
|
||||
GlobalTtyManager.all_tty_putstr("Starting init \n");
|
||||
|
||||
Task *init;
|
||||
FDT::FD fd = VFSApi::open(StrToPath("/init"));
|
||||
File *f = VFSApi::get(fd);
|
||||
|
||||
{
|
||||
Vector<char> read_data(f->size());
|
||||
f->read(read_data.data(), f->size());
|
||||
ElfParser elfParser(std::move(read_data));
|
||||
|
||||
init = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), "/init");
|
||||
if (!elfParser.copy_to(init))
|
||||
assert2(false, "Init couldn't be loaded!");
|
||||
}
|
||||
|
||||
VFSApi::close(fd);
|
||||
|
||||
init->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,13 @@ add_custom_target(iso_limine)
|
||||
|
||||
add_custom_target(iso
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/isodir/
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/initramfs/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/limine.cfg ${CMAKE_CURRENT_BINARY_DIR}/isodir/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:kernel.elf> ${CMAKE_CURRENT_BINARY_DIR}/isodir/ficus.elf
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:init> ${CMAKE_CURRENT_BINARY_DIR}/isodir/init
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:hello2> ${CMAKE_CURRENT_BINARY_DIR}/isodir/hello2
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:init> ${CMAKE_CURRENT_BINARY_DIR}/initramfs/init
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:hello2> ${CMAKE_CURRENT_BINARY_DIR}/initramfs/hello2
|
||||
# TODO: this might not work when there are special symbols in path...
|
||||
COMMAND pax -wvf ${CMAKE_CURRENT_BINARY_DIR}/isodir/sysroot.tar -s ":^${CMAKE_CURRENT_BINARY_DIR}/initramfs/::" ${CMAKE_CURRENT_BINARY_DIR}/initramfs
|
||||
COMMAND xorriso -as mkisofs -b limine-bios-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot limine-uefi-cd.bin -efi-boot-part --efi-boot-image --protective-msdos-label ${CMAKE_CURRENT_BINARY_DIR}/isodir -o ${CMAKE_CURRENT_BINARY_DIR}/ficus.iso
|
||||
COMMAND ${tools}/limine/prefix/bin/limine bios-install ${CMAKE_CURRENT_BINARY_DIR}/ficus.iso
|
||||
VERBATIM
|
||||
|
||||
@@ -8,9 +8,7 @@ TIMEOUT=1
|
||||
|
||||
# Path to the kernel to boot. boot:/// represents the partition on which limine.cfg is located.
|
||||
KERNEL_PATH=boot:///ficus.elf
|
||||
|
||||
MODULE_PATH=boot:///init
|
||||
MODULE_PATH=boot:///hello2
|
||||
MODULE_PATH=boot:///sysroot.tar
|
||||
|
||||
# Same thing, but without KASLR.
|
||||
:ficus (KASLR off)
|
||||
@@ -20,5 +18,4 @@ TIMEOUT=1
|
||||
KASLR=no
|
||||
|
||||
KERNEL_PATH=boot:///ficus.elf
|
||||
MODULE_PATH=boot:///init
|
||||
MODULE_PATH=boot:///hello2
|
||||
MODULE_PATH=boot:///sysroot.tar
|
||||
|
||||
@@ -13,4 +13,5 @@ target_sources(kernel.elf PRIVATE
|
||||
File.cpp
|
||||
PipeFs.cpp
|
||||
TtyPipe.cpp
|
||||
TarFs.cpp
|
||||
)
|
||||
147
src/kernel/vfs/TarFs.cpp
Normal file
147
src/kernel/vfs/TarFs.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 01.05.2024.
|
||||
//
|
||||
|
||||
#include "TarFs.hpp"
|
||||
|
||||
#include <TtyManager.hpp>
|
||||
|
||||
|
||||
TarFs::TarFs(char *backing, size_t backing_size, NodeDir *mounted_on) : Filesystem(mounted_on), _backing((tar_header *) backing), _backing_size(backing_size) {
|
||||
int i = 2;
|
||||
|
||||
const tar_header *header = _backing;
|
||||
|
||||
SkipListMap<String, ino_t> dir_map;
|
||||
|
||||
dir_map.emplace("", 1);
|
||||
_dir_map.emplace(1, Vector<DirEntry>());
|
||||
|
||||
// FIXME: all this is extremely inefficient
|
||||
// Also recheck that directories are handled correctly
|
||||
while (true) {
|
||||
if (header->filename[0] == '\0')
|
||||
break;
|
||||
unsigned int size = header_size(header);
|
||||
|
||||
int new_ino = i++;
|
||||
_off_map.emplace(new_ino, header);
|
||||
|
||||
String pref = "";
|
||||
String name = "";
|
||||
|
||||
{
|
||||
Path p = StrToPath(header->filename);
|
||||
if (p.size() > 1) {
|
||||
pref += p[0];
|
||||
for (int i = 1; i < p.size() - 1; i++) {
|
||||
pref += "/";
|
||||
pref += p[i];
|
||||
}
|
||||
}
|
||||
name = p.back();
|
||||
}
|
||||
|
||||
if (header->typeflag[0] == '5') {
|
||||
String fullname;
|
||||
if (pref.length() > 0) {
|
||||
fullname += pref;
|
||||
fullname += "/";
|
||||
}
|
||||
fullname += name;
|
||||
if (dir_map.find(fullname) == dir_map.end()) {
|
||||
dir_map.emplace(fullname, new_ino);
|
||||
_dir_map.emplace(new_ino, Vector<DirEntry>());
|
||||
}
|
||||
if (dir_map.find(pref) == dir_map.end()) {
|
||||
int dir_ino = i++;
|
||||
dir_map.emplace(pref, dir_ino);
|
||||
_dir_map.emplace(dir_ino, Vector<DirEntry>());
|
||||
}
|
||||
auto p = dir_map.find(pref);
|
||||
auto d = _dir_map.find(p->second);
|
||||
d->second.emplace_back(name, new_ino);
|
||||
} else if (header->typeflag[0] == '\0' || header->typeflag[0] == '0') {
|
||||
if (dir_map.find(pref) == dir_map.end()) {
|
||||
int dir_ino = i++;
|
||||
dir_map.emplace(pref, dir_ino);
|
||||
_dir_map.emplace(dir_ino, Vector<DirEntry>());
|
||||
}
|
||||
auto p = dir_map.find(pref);
|
||||
auto d = _dir_map.find(p->second);
|
||||
d->second.emplace_back(name, new_ino);
|
||||
} else {
|
||||
GlobalTtyManager.all_tty_putstr("Skipping tar: ");
|
||||
GlobalTtyManager.all_tty_putstr(pref.c_str());
|
||||
GlobalTtyManager.all_tty_putstr("/");
|
||||
GlobalTtyManager.all_tty_putstr(name.c_str());
|
||||
GlobalTtyManager.all_tty_putstr("\n");
|
||||
}
|
||||
|
||||
header = (const tar_header *) (((char *) (header)) + ((size / 512) + 1) * 512);
|
||||
|
||||
if (size % 512)
|
||||
header = (const tar_header *) (((char *) (header)) + 512);
|
||||
}
|
||||
}
|
||||
|
||||
SharedPtr<NodeDir> TarFs::root() {
|
||||
return static_ptr_cast<NodeDir>(get_node(1));
|
||||
}
|
||||
|
||||
SharedPtr<Node> TarFs::get_node(ino_t inode) {
|
||||
if (_dir_map.find(inode) != _dir_map.end()) {
|
||||
return static_ptr_cast<Node>(TarFsNodeDir::create(this, inode));
|
||||
} else {
|
||||
return static_ptr_cast<Node>(TarFsNodeFile::create(this, inode));
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
Vector<DirEntry> TarFs::TarFsNodeDir::children() {
|
||||
return static_cast<TarFs *>(_fs)->_dir_map.find(_ino)->second;
|
||||
}
|
||||
|
||||
ino_t TarFs::TarFsNodeDir::mkdir(const String &name) {
|
||||
return -1;
|
||||
}
|
||||
ino_t TarFs::TarFsNodeDir::mkfile(const String &name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t TarFs::TarFsNodeFile::read(char *buf, size_t start, size_t num) {
|
||||
TarFs *tar_fs = static_cast<TarFs *>(_fs);
|
||||
|
||||
if (auto entry = tar_fs->_off_map.find(_ino); entry != tar_fs->_off_map.end()) {
|
||||
num = std::min(num, size() - start);
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
buf[i] = (((char *) entry->second) + 512)[start + i];
|
||||
}
|
||||
return num;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
int64_t TarFs::TarFsNodeFile::write(const char *buf, size_t start, size_t num) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t TarFs::TarFsNodeFile::size() {
|
||||
TarFs *tar_fs = static_cast<TarFs *>(_fs);
|
||||
|
||||
if (auto entry = tar_fs->_off_map.find(_ino); entry != tar_fs->_off_map.end()) {
|
||||
return header_size(entry->second);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
size_t TarFs::header_size(const tar_header *hdr) {
|
||||
int size = 0;
|
||||
|
||||
size_t count = 1;
|
||||
for (int j = 11; j > 0; j--, count *= 8)
|
||||
size += ((hdr->size[j - 1] - '0') * count);
|
||||
|
||||
return size;
|
||||
}
|
||||
79
src/kernel/vfs/TarFs.hpp
Normal file
79
src/kernel/vfs/TarFs.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 01.05.2024.
|
||||
//
|
||||
|
||||
#ifndef TARFS_HPP
|
||||
#define TARFS_HPP
|
||||
|
||||
#include <Filesystem.hpp>
|
||||
|
||||
class TarFs : public Filesystem {
|
||||
public:
|
||||
TarFs(char *backing, size_t backing_size, NodeDir *mounted_on);
|
||||
~TarFs() override = default;
|
||||
|
||||
SharedPtr<NodeDir> root() override;
|
||||
SharedPtr<Node> get_node(ino_t inode) override;
|
||||
|
||||
|
||||
struct TarFsNodeDir : public ::NodeDir {
|
||||
public:
|
||||
~TarFsNodeDir() override = default;
|
||||
|
||||
Vector<DirEntry> children() override;
|
||||
ino_t mkdir(const String &name) override;
|
||||
ino_t mkfile(const String &name) override;
|
||||
|
||||
static SharedPtr<TarFsNodeDir> create(Filesystem *fs, ino_t id) {
|
||||
auto shared = SharedPtr(new TarFsNodeDir(fs, id));
|
||||
shared->_self_weak = static_ptr_cast<Node>(shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
private:
|
||||
TarFsNodeDir(Filesystem *fs, ino_t id) : ::NodeDir(fs, id) {}
|
||||
};
|
||||
|
||||
struct TarFsNodeFile : public ::NodeFile {
|
||||
public:
|
||||
~TarFsNodeFile() override = default;
|
||||
|
||||
int64_t read(char *buf, size_t start, size_t num) override;
|
||||
int64_t write(const char *buf, size_t start, size_t num) override;
|
||||
size_t size() override;
|
||||
bool is_tty() override { return false; }
|
||||
|
||||
static SharedPtr<TarFsNodeFile> create(Filesystem *fs, ino_t id) {
|
||||
auto shared = SharedPtr(new TarFsNodeFile(fs, id));
|
||||
shared->_self_weak = static_ptr_cast<Node>(shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
private:
|
||||
TarFsNodeFile(Filesystem *fs, ino_t id) : ::NodeFile(fs, id) {}
|
||||
};
|
||||
|
||||
private:
|
||||
struct tar_header {
|
||||
char filename[100];
|
||||
char mode[8];
|
||||
char uid[8];
|
||||
char gid[8];
|
||||
char size[12];
|
||||
char mtime[12];
|
||||
char chksum[8];
|
||||
char typeflag[1];
|
||||
} __attribute__((packed));
|
||||
|
||||
const tar_header *_backing;
|
||||
size_t _backing_size;
|
||||
|
||||
SkipListMap<ino_t, const tar_header *> _off_map;
|
||||
SkipListMap<ino_t, Vector<DirEntry>> _dir_map;
|
||||
// SkipListMap<ino_t, SharedPtr<Node>> _vnode_map;
|
||||
|
||||
static size_t header_size(const tar_header *hdr);
|
||||
};
|
||||
|
||||
|
||||
#endif //TARFS_HPP
|
||||
Reference in New Issue
Block a user