#include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/cpu.hpp" #include "kapi/devices.hpp" #include "kapi/interrupts.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" #include "kernel/devices/storage/management.hpp" #include "kernel/filesystem/device_inode.hpp" #include "kernel/filesystem/file_descriptor_table.hpp" #include "kernel/filesystem/filesystem.hpp" #include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/vfs.hpp" #include "kernel/memory.hpp" #include #include #include #include #include #include #include #include #include using namespace kstd::units_literals; auto test_device_names() -> void { auto storage_mgmt = kernel::devices::storage::management::get(); std::ranges::for_each(storage_mgmt.all_controllers(), [](auto const & controller) { std::ranges::for_each(controller->all_devices(), [](auto const & device) { kstd::println("{}", device->name().view()); }); }); } auto test_file_description_manually() -> void { // setup auto fd_table = kernel::filesystem::file_descriptor_table::get(); auto storage_mgmt = kernel::devices::storage::management::get(); auto device = storage_mgmt.device_by_major_minor(1, 0); auto dev_node = kstd::make_shared(device); auto ofd = kstd::make_shared(dev_node); auto fd_index = fd_table.add_file(ofd); // use: read two bytes and write two again auto fd = fd_table.get_file(fd_index); if (!fd) { kstd::os::panic("test code failed"); } kstd::vector buffer{2}; auto number_of_read_bytes = fd->read(buffer.data(), buffer.size()); kstd::println("read bytes: {}", number_of_read_bytes); kstd::println("buffer: {::#04x}", buffer); // write half of the file new auto const value1 = std::byte{0xAA}; auto const value2 = std::byte{0xBB}; kstd::vector write_buffer{value1, value2}; auto written_bytes = fd->write(write_buffer.data(), write_buffer.size()); kstd::println("written bytes: {}", written_bytes); fd_table.remove_file(fd_index); // use: read four bytes again -> two old bytes two new bytes auto ofd1 = kstd::make_shared(dev_node); fd_index = fd_table.add_file(ofd1); auto fd1 = fd_table.get_file(fd_index); if (!fd1) { kstd::os::panic("test code failed"); } kstd::vector buffer1{4}; number_of_read_bytes = fd1->read(buffer1.data(), buffer1.size()); kstd::println("read bytes: {}", number_of_read_bytes); kstd::println("buffer: {::#04x}", buffer1); } auto test_device_with_vfs() -> void { auto vfs = kernel::filesystem::vfs::get(); auto ofd = vfs.open("/dev/ram0"); if (!ofd) { kstd::os::panic("test code failed"); } auto fd_table = kernel::filesystem::file_descriptor_table::get(); auto fd = fd_table.add_file(ofd); kstd::vector buffer{2}; auto file = fd_table.get_file(fd); if (!file) { kstd::os::panic("test code failed"); } auto number_of_read_bytes = file->read(buffer.data(), buffer.size()); kstd::println("read bytes: {}", number_of_read_bytes); kstd::println("buffer: {::#04x}", buffer); } auto test_file_lookup() -> void { auto vfs = kernel::filesystem::vfs::get(); auto read_and_write_file = [&vfs](std::string_view path) { kstd::println("[TEST] Reading and writing file at path: {}", path); auto ofd = vfs.open(path); if (!ofd) { kstd::os::panic("test code failed"); } kstd::vector buffer{32}; auto number_of_read_bytes = ofd->read(buffer.data(), buffer.size()); kstd::println("read bytes: {}", number_of_read_bytes); kstd::println("buffer: {::#04x}", buffer); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), number_of_read_bytes}; kstd::println("buffer_as_str: {}", buffer_as_str); }; read_and_write_file("/info.txt"); read_and_write_file("/enclosures/info.txt"); read_and_write_file("/enclosures/aquarium/tank_1/fish_4.txt"); read_and_write_file("/enclosures/elephant_house/elephant_1.txt"); read_and_write_file( "/enclosures/aquarium/tank_2/" "this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_" "limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_30.txt"); auto storage_mgmt = kernel::devices::storage::management::get(); auto device_1 = storage_mgmt.device_by_major_minor(1, 16); auto fs_1 = kernel::filesystem::filesystem::probe_and_mount(device_1); vfs.do_mount("/enclosures/aquarium", fs_1); read_and_write_file("/enclosures/aquarium/closed.txt"); read_and_write_file("/enclosures/aquarium/information/info_2.txt"); vfs.unmount("/enclosures/aquarium"); read_and_write_file("/enclosures/aquarium/tank_1/fish_4.txt"); auto device_2 = storage_mgmt.device_by_major_minor(1, 32); auto fs_2 = kernel::filesystem::filesystem::probe_and_mount(device_2); vfs.do_mount("/enclosures/elephant_house", fs_2); read_and_write_file("/enclosures/elephant_house/monkey_house/infrastructure/info.txt"); vfs.do_mount("/enclosures/elephant_house/monkey_house", fs_1); read_and_write_file("/enclosures/elephant_house/monkey_house/information/info_2.txt"); auto result = vfs.unmount("/enclosures/elephant_house"); if (result == kernel::filesystem::vfs::operation_result::unmount_failed) { kstd::println("[TEST] Unmount failed as expected due to active child mount."); } vfs.unmount("/enclosures/elephant_house/monkey_house"); result = vfs.unmount("/enclosures/elephant_house"); if (result == kernel::filesystem::vfs::operation_result::success) { kstd::println("[TEST] Unmount succeeded after unmounting child mount."); } } auto run_test_code() -> void { kstd::println("[TEST] Running test code..."); kstd::println("[TEST] device names"); test_device_names(); kstd::println("---------------------------------"); kstd::println("[TEST] file description manually"); test_file_description_manually(); kstd::println("---------------------------------"); kstd::println("[TEST] device with VFS"); test_device_with_vfs(); kstd::println("---------------------------------"); kstd::println("[TEST] file lookup"); test_file_lookup(); kstd::println("---------------------------------"); } auto main() -> int { kapi::cio::init(); kstd::println("[OS] IO subsystem initialized."); kapi::cpu::init(); kapi::memory::init(); kernel::memory::init_heap(kapi::memory::heap_base); kapi::system::memory_initialized(); kapi::memory::init_mmio(kapi::memory::mmio_base, 1_GiB / kapi::memory::page::size); kstd::println("[OS] Memory subsystem initialized."); kapi::devices::init(); kstd::println("[OS] System root bus initialized."); kapi::devices::init_platform_devices(); kstd::println("[OS] Platform devices initialized."); kapi::interrupts::enable(); kstd::println("[OS] Interrupts enabled."); kapi::boot_modules::init(); kstd::println("[OS] Boot module registry initialized."); kernel::devices::storage::management::init(); kstd::println("[OS] Storage management initialized."); kernel::filesystem::file_descriptor_table::init(); kstd::println("[OS] Global file descriptor table initialized."); kernel::filesystem::vfs::init(); kstd::println("[OS] Virtual filesystem initialized."); run_test_code(); kstd::println("[TEST] All tests completed."); kapi::system::panic("Returning from kernel main!"); }