From aa2aee684b14126aa6e9971b52c2021ffaa6e858 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 11 Apr 2023 23:25:21 +0300 Subject: [PATCH] Kernel: remove message from BAN::Error We don't store the error message anymore in BAN::Error. Instead we store a error code that can be mapped into a string. This allows BAN::Error to only take 4 bytes instead of 128. We should also make some kernel initialization just panic instead of returning errors since they are required for succesfull boot anyway. --- BAN/include/BAN/Errors.h | 69 +++++++--------- kernel/CMakeLists.txt | 1 + kernel/include/kernel/Errors.h | 39 +++++++++ kernel/kernel/ACPI.cpp | 12 +-- kernel/kernel/Errors.cpp | 40 +++++++++ kernel/kernel/FS/Ext2.cpp | 6 +- kernel/kernel/FS/VirtualFileSystem.cpp | 12 ++- kernel/kernel/Font.cpp | 12 +-- kernel/kernel/Input/PS2Controller.cpp | 25 +++--- kernel/kernel/Process.cpp | 21 ++--- kernel/kernel/Shell.cpp | 103 +++++++++++++++++++----- kernel/kernel/Storage/ATABus.cpp | 23 +++--- kernel/kernel/Storage/ATADevice.cpp | 2 +- kernel/kernel/Storage/StorageDevice.cpp | 12 +-- libc/include/errno.h | 1 + libc/string.cpp | 3 + 16 files changed, 258 insertions(+), 123 deletions(-) create mode 100644 kernel/include/kernel/Errors.h create mode 100644 kernel/kernel/Errors.cpp diff --git a/BAN/include/BAN/Errors.h b/BAN/include/BAN/Errors.h index 1af4cdbb..86dc7675 100644 --- a/BAN/include/BAN/Errors.h +++ b/BAN/include/BAN/Errors.h @@ -8,6 +8,7 @@ #if defined(__is_kernel) #include + #include #define MUST(expr) ({ auto e = expr; if (e.is_error()) Kernel::panic("{}", e.error()); e.release_value(); }) #else #define MUST(expr) ({ auto e = expr; assert(!e.is_error()); e.release_value(); }) @@ -20,43 +21,38 @@ namespace BAN class Error { + private: + static constexpr uint32_t kernel_error_mask = 0x80000000; + public: - static Error from_c_string(const char* message) + static Error from_error_code(Kernel::ErrorCode error) { - Error result; - strncpy(result.m_message, message, sizeof(Error::m_message)); - result.m_message[sizeof(Error::m_message) - 1] = '\0'; - result.m_error_code = 0xFF; - return result; - } - template - static Error from_format(const char* format, Args&&... args) - { - char buffer[sizeof(Error::m_message)] {}; - size_t index = 0; - auto putc = [&](char ch) - { - if (index < sizeof(buffer) - 1) - buffer[index++] = ch; - }; - Formatter::print(putc, format, forward(args)...); - return from_c_string(buffer); + return Error((uint32_t)error | kernel_error_mask); } static Error from_errno(int error) { - Error result; - strncpy(result.m_message, strerror(error), sizeof(Error::m_message)); - result.m_message[sizeof(Error::m_message) - 1] = '\0'; - result.m_error_code = error; - return result; + return Error(error); } - uint8_t get_error_code() const { return m_error_code; } - const char* get_message() const { return m_message; } + Kernel::ErrorCode kernel_error() const + { + return (Kernel::ErrorCode)(m_error_code & ~kernel_error_mask); + } + + uint32_t get_error_code() const { return m_error_code; } + BAN::StringView get_message() const + { + if (m_error_code & kernel_error_mask) + return Kernel::error_string(kernel_error()); + return strerror(m_error_code); + } private: - char m_message[128]; - uint8_t m_error_code; + Error(uint32_t error) + : m_error_code(error) + {} + + uint32_t m_error_code; }; template @@ -82,7 +78,7 @@ namespace BAN const T& value() const { return m_data.template get(); } T& value() { return m_data.template get(); } - Error release_error() { return move(error()); m_data.clear(); } + Error release_error() { return move(error()); m_data.clear(); } T release_value() { return move(value()); m_data.clear(); } private: @@ -102,12 +98,12 @@ namespace BAN const Error& error() const { return m_data; } void value() { } - Error release_error() { return move(m_data); m_data = Error(); } - void release_value() { m_data = Error(); } + Error release_error() { return move(m_data); } + void release_value() { } private: - Error m_data; - bool m_has_error = false; + Error m_data { Error::from_error_code(Kernel::ErrorCode::None) }; + bool m_has_error { false }; }; } @@ -115,11 +111,8 @@ namespace BAN namespace BAN::Formatter { template - void print_argument(F putc, const Error& error, const ValueFormat&) + void print_argument(F putc, const Error& error, const ValueFormat& format) { - if (error.get_error_code() == 0xFF) - print(putc, error.get_message()); - else - print(putc, "{} ({})", error.get_message(), error.get_error_code()); + print_argument(putc, error.get_message(), format); } } diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index e6b06302..09cc6fa1 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -17,6 +17,7 @@ set(KERNEL_SOURCES kernel/Debug.cpp kernel/Device.cpp kernel/DeviceManager.cpp + kernel/Errors.cpp kernel/Font.cpp kernel/FS/Ext2.cpp kernel/FS/VirtualFileSystem.cpp diff --git a/kernel/include/kernel/Errors.h b/kernel/include/kernel/Errors.h new file mode 100644 index 00000000..b815f0e8 --- /dev/null +++ b/kernel/include/kernel/Errors.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace Kernel +{ + + enum class ErrorCode : uint32_t + { + None, + ACPI_NoRootSDT, + ACPI_NoSuchHeader, + ACPI_RootInvalid, + PS2_Timeout, + PS2_SelfTest, + PS2_Reset, + PS2_UnsupportedDevice, + Ext2_Invalid, + Ext2_Corrupted, + Ext2_NoInodes, + Storage_Boundaries, + Storage_GPTHeader, + ATA_NoLBA, + ATA_AMNF, + ATA_TKZNF, + ATA_ABRT, + ATA_MCR, + ATA_IDNF, + ATA_MC, + ATA_UNC, + ATA_BBK, + Font_FileTooSmall, + Font_Unsupported, + Count + }; + + BAN::StringView error_string(ErrorCode); + +} \ No newline at end of file diff --git a/kernel/kernel/ACPI.cpp b/kernel/kernel/ACPI.cpp index 2c784ac9..c5694bd9 100644 --- a/kernel/kernel/ACPI.cpp +++ b/kernel/kernel/ACPI.cpp @@ -100,7 +100,7 @@ namespace Kernel { const RSDP* rsdp = locate_rsdp(); if (rsdp == nullptr) - return BAN::Error::from_c_string("Could not find RSDP"); + return BAN::Error::from_error_code(ErrorCode::ACPI_NoRootSDT); if (rsdp->revision >= 2) { @@ -109,9 +109,9 @@ namespace Kernel BAN::ScopeGuard _([xsdt] { MMU::get().unallocate_page((uintptr_t)xsdt); }); if (memcmp(xsdt->signature, "XSDT", 4) != 0) - return BAN::Error::from_c_string("XSDT has invalid signature"); + return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid); if (!is_valid_std_header(xsdt)) - return BAN::Error::from_c_string("XSDT has invalid checksum"); + return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid); m_header_table = (uintptr_t)xsdt->entries; m_entry_size = 8; @@ -124,9 +124,9 @@ namespace Kernel BAN::ScopeGuard _([rsdt] { MMU::get().unallocate_page((uintptr_t)rsdt); }); if (memcmp(rsdt->signature, "RSDT", 4) != 0) - return BAN::Error::from_c_string("RSDT has invalid signature"); + return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid); if (!is_valid_std_header(rsdt)) - return BAN::Error::from_c_string("RSDT has invalid checksum"); + return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid); m_header_table = (uintptr_t)rsdt->entries; m_entry_size = 4; @@ -148,7 +148,7 @@ namespace Kernel return header; unmap_header(header); } - return BAN::Error::from_format("Could not find ACPI header '{}'", BAN::StringView(signature, 4)); + return BAN::Error::from_error_code(ErrorCode::ACPI_NoSuchHeader); } void ACPI::unmap_header(const ACPI::SDTHeader* header) diff --git a/kernel/kernel/Errors.cpp b/kernel/kernel/Errors.cpp new file mode 100644 index 00000000..38c1d9e9 --- /dev/null +++ b/kernel/kernel/Errors.cpp @@ -0,0 +1,40 @@ +#include + +namespace Kernel +{ + + static BAN::StringView s_error_strings[] { + "No Error"sv, + "ACPI could not find root SDT header"sv, + "ACPI no such header"sv, + "ACPI root invalid", + "PS/2 device timeout"sv, + "PS/2 controller self test failed"sv, + "PS/2 reset failed"sv, + "PS/2 unsupported device"sv, + "Invalid ext2 filesystem"sv, + "Ext2 filesystem corrupted"sv, + "Ext2 filesystem out of inodes"sv, + "Attempted to access outside of device boundaries"sv, + "Device has invalid GPT header"sv, + "Device does not support LBA addressing"sv, + "Address mark not found"sv, + "Track zero not found"sv, + "Aborted command"sv, + "Media change request"sv, + "ID not found"sv, + "Media changed"sv, + "Uncorrectable data error"sv, + "Bad Block detected"sv, + "Font file too small"sv, + "Unsupported font format"sv, + }; + static_assert(sizeof(s_error_strings) / sizeof(*s_error_strings) == (size_t)ErrorCode::Count); + + BAN::StringView error_string(ErrorCode error) + { + ASSERT((uint32_t)error < (uint32_t)ErrorCode::Count); + return s_error_strings[(uint32_t)error]; + } + +} \ No newline at end of file diff --git a/kernel/kernel/FS/Ext2.cpp b/kernel/kernel/FS/Ext2.cpp index 58bdd31e..0237ee1e 100644 --- a/kernel/kernel/FS/Ext2.cpp +++ b/kernel/kernel/FS/Ext2.cpp @@ -463,7 +463,7 @@ namespace Kernel } if (m_superblock.magic != 0xEF53) - return BAN::Error::from_c_string("Not an ext2 filesystem"); + return BAN::Error::from_error_code(ErrorCode::Ext2_Invalid); if (m_superblock.rev_level < 1) { @@ -475,7 +475,7 @@ namespace Kernel uint32_t number_of_block_groups = BAN::Math::div_round_up(superblock().inodes_count, superblock().inodes_per_group); uint32_t number_of_block_groups_check = BAN::Math::div_round_up(superblock().blocks_count, superblock().blocks_per_group); if (number_of_block_groups != number_of_block_groups_check) - return BAN::Error::from_c_string("Ambiguous number of block groups"); + return BAN::Error::from_error_code(ErrorCode::Ext2_Corrupted); ASSERT(!(m_superblock.feature_incompat & Ext2::Enum::FEATURE_INCOMPAT_COMPRESSION)); //ASSERT(!(m_superblock.feature_incompat & Ext2::Enum::FEATURE_INCOMPAT_FILETYPE)); @@ -546,7 +546,7 @@ namespace Kernel } } - return BAN::Error::from_c_string("No free inodes available in the whole filesystem"); + return BAN::Error::from_error_code(ErrorCode::Ext2_NoInodes); } void Ext2FS::read_block(uint32_t block, BAN::Span buffer) diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index fb62776f..d22c7544 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -18,8 +18,7 @@ namespace Kernel return BAN::Error::from_errno(ENOMEM); BAN::ScopeGuard guard([] { delete s_instance; s_instance = nullptr; } ); - if (root.size() < 5 || root.substring(0, 5) != "/dev/") - return BAN::Error::from_c_string("root must be in /dev/"); + ASSERT(root.size() >= 5 && root.substring(0, 5) == "/dev/"sv);; root = root.substring(5); auto partition_inode = TRY(DeviceManager::get().read_directory_inode(root)); @@ -43,11 +42,11 @@ namespace Kernel { auto partition_file = TRY(file_from_absolute_path(partition)); if (partition_file.inode->inode_type() != Inode::InodeType::Device) - return BAN::Error::from_c_string("Not a partition"); + return BAN::Error::from_errno(ENOTBLK); Device* device = (Device*)partition_file.inode.ptr(); - if (device->device_type() != Device::DeviceType::Partition) - return BAN::Error::from_c_string("Not a partition"); + if (device->device_type() != Device::DeviceType::BlockDevice) + return BAN::Error::from_errno(ENOTBLK); auto* file_system = TRY(Ext2FS::create(*(Partition*)device)); return mount(file_system, target); @@ -90,8 +89,7 @@ namespace Kernel ASSERT(path.front() == '/'); auto inode = root_inode(); - if (!inode) - return BAN::Error::from_c_string("No root inode available"); + ASSERT(inode); BAN::String canonical_path; diff --git a/kernel/kernel/Font.cpp b/kernel/kernel/Font.cpp index c165c6d5..8f2fff09 100644 --- a/kernel/kernel/Font.cpp +++ b/kernel/kernel/Font.cpp @@ -48,7 +48,7 @@ namespace Kernel TRY(Process::current()->read(fd, file_data.data(), st.st_size)); if (file_data.size() < 4) - return BAN::Error::from_c_string("Font file is too small"); + return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); if (file_data[0] == PSF1_MAGIC0 && file_data[1] == PSF1_MAGIC1) return TRY(parse_psf1(file_data.span())); @@ -56,13 +56,13 @@ namespace Kernel if (file_data[0] == PSF2_MAGIC0 && file_data[1] == PSF2_MAGIC1 && file_data[2] == PSF2_MAGIC2 && file_data[3] == PSF2_MAGIC3) return TRY(parse_psf2(file_data.span())); - return BAN::Error::from_c_string("Unsupported font format"); + return BAN::Error::from_error_code(ErrorCode::Font_Unsupported); } BAN::ErrorOr Font::parse_psf1(BAN::Span font_data) { if (font_data.size() < 4) - return BAN::Error::from_c_string("Font file is too small"); + return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); struct PSF1Header { @@ -77,7 +77,7 @@ namespace Kernel uint32_t glyph_data_size = glyph_size * glyph_count; if (font_data.size() < sizeof(PSF1Header) + glyph_data_size) - return BAN::Error::from_c_string("Font file is too small"); + return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); BAN::Vector glyph_data; TRY(glyph_data.resize(glyph_data_size)); @@ -155,14 +155,14 @@ namespace Kernel }; if (font_data.size() < sizeof(PSF2Header)) - return BAN::Error::from_c_string("Font file is too small"); + return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); const PSF2Header& header = *(const PSF2Header*)font_data.data(); uint32_t glyph_data_size = header.glyph_count * header.glyph_size; if (font_data.size() < glyph_data_size + header.header_size) - return BAN::Error::from_c_string("Font file is too small"); + return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); BAN::Vector glyph_data; TRY(glyph_data.resize(glyph_data_size)); diff --git a/kernel/kernel/Input/PS2Controller.cpp b/kernel/kernel/Input/PS2Controller.cpp index 8d65bc08..30608694 100644 --- a/kernel/kernel/Input/PS2Controller.cpp +++ b/kernel/kernel/Input/PS2Controller.cpp @@ -116,7 +116,7 @@ namespace Kernel::Input return {}; } } - return BAN::Error::from_c_string("PS/2 device timeout"); + return BAN::Error::from_error_code(ErrorCode::PS2_Timeout); } static BAN::ErrorOr device_read_byte() @@ -125,7 +125,7 @@ namespace Kernel::Input while (PIT::ms_since_boot() < timeout) if (IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_FULL) return IO::inb(PS2::IOPort::DATA); - return BAN::Error::from_c_string("PS/2 device timeout"); + return BAN::Error::from_error_code(ErrorCode::PS2_Timeout); } static BAN::ErrorOr device_wait_ack() @@ -175,15 +175,7 @@ namespace Kernel::Input // FIXME // Step 2: Determine if the PS/2 Controller Exists - if (false) - { - const ACPI::FADT* fadt = (const ACPI::FADT*)TRY(ACPI::get().get_header("FACP")); - bool ps2_exists = fadt->iapc_boot_arch & (1 << 1); - ACPI::get().unmap_header(fadt); - - if (!ps2_exists) - return BAN::Error::from_c_string("PS2 Controller does not exist"); - } + // FIXME // Step 3: Disable Devices controller_send_command(PS2::Command::DISABLE_FIRST_PORT); @@ -203,7 +195,7 @@ namespace Kernel::Input // Step 6: Perform Controller Self Test controller_send_command(PS2::Command::TEST_CONTROLLER); if (wait_and_read() != PS2::Response::TEST_CONTROLLER_PASS) - return BAN::Error::from_c_string("PS/2 Controller self test failed"); + return BAN::Error::from_error_code(ErrorCode::PS2_SelfTest); // NOTE: self test might reset the device so we set the config byte again controller_send_command(PS2::Command::WRITE_CONFIG, config); @@ -229,7 +221,7 @@ namespace Kernel::Input valid_ports[1] = false; } if (!valid_ports[0] && !valid_ports[1]) - return BAN::Error::from_c_string("No ports available on Controller"); + return {}; // Step 9: Enable Devices (and disable scanning) for (uint8_t device = 0; device < 2; device++) @@ -298,7 +290,7 @@ namespace Kernel::Input // Standard PS/2 Mouse if (index == 1 && (bytes[0] == 0x00)) - return BAN::Error::from_c_string("PS/2 mouse not supported"); + return BAN::Error::from_error_code(ErrorCode::PS2_UnsupportedDevice); // MF2 Keyboard if (index == 2 && (bytes[0] == 0xAB && bytes[1] == 0x83)) @@ -306,7 +298,8 @@ namespace Kernel::Input if (m_devices[device]) return {}; - return BAN::Error::from_format("Unhandled PS/2 device {}{} ({} bytes)", bytes[0], bytes[1], index); + + return BAN::Error::from_error_code(ErrorCode::PS2_UnsupportedDevice); } void PS2Controller::send_byte(const PS2Device* device, uint8_t byte) @@ -321,7 +314,7 @@ namespace Kernel::Input TRY(device_send_byte(device, PS2::DeviceCommand::RESET)); TRY(device_wait_ack()); if (TRY(device_read_byte()) != PS2::Response::SELF_TEST_PASS) - return BAN::Error::from_c_string("Device reset failed"); + return BAN::Error::from_error_code(ErrorCode::PS2_Reset); return {}; } diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index e6f95156..211c5d15 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -64,8 +64,7 @@ namespace Kernel BAN::ErrorOr Process::init_stdio() { - if (!m_open_files.empty()) - return BAN::Error::from_c_string("Could not init stdio, process already has open files"); + ASSERT(m_open_files.empty()); TRY(open("/dev/tty1", O_RDONLY)); // stdin TRY(open("/dev/tty1", O_WRONLY)); // stdout TRY(open("/dev/tty1", O_WRONLY)); // stderr @@ -152,13 +151,17 @@ namespace Kernel BAN::ErrorOr Process::creat(BAN::StringView path, mode_t mode) { auto absolute_path = TRY(absolute_path_of(path)); - while (absolute_path.back() != '/') - absolute_path.pop_back(); - - auto parent_file = TRY(VirtualFileSystem::get().file_from_absolute_path(absolute_path)); - if (path.count('/') > 0) - return BAN::Error::from_c_string("You can only create files to current working directory"); - TRY(parent_file.inode->create_file(path, mode)); + + size_t index; + for (index = absolute_path.size(); index > 0; index--) + if (absolute_path[index - 1] == '/') + break; + + auto directory = absolute_path.sv().substring(0, index); + auto file_name = absolute_path.sv().substring(index); + + auto parent_file = TRY(VirtualFileSystem::get().file_from_absolute_path(directory)); + TRY(parent_file.inode->create_file(file_name, mode)); return {}; } diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 329070dd..e68494c3 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -327,11 +327,26 @@ argument_done: if (arguments.empty()) { + } + else if (arguments.front() == "oof") + { + SpinLock lock; + for (int i = 0; i < 100; i++) + { + lock.lock(); + MUST(Process::create_kernel([](void*) { MUST(Process::current()->init_stdio()); TTY_PRINTLN("####"); Process::current()->exit(); }, nullptr)); + PIT::sleep(5); + kmalloc_dump_info(); + lock.unlock(); + } } else if (arguments.front() == "date") { if (arguments.size() != 1) - return BAN::Error::from_c_string("'date' does not support command line arguments"); + { + TTY_PRINTLN("'date' does not support command line arguments"); + return {}; + } auto time = RTC::get_current_time(); TTY_PRINTLN("{}", time); } @@ -348,7 +363,10 @@ argument_done: else if (arguments.front() == "clear") { if (arguments.size() != 1) - return BAN::Error::from_c_string("'clear' does not support command line arguments"); + { + TTY_PRINTLN("'clear' does not support command line arguments"); + return {}; + } TTY_PRINT("\e[2J\e[H"); } else if (arguments.front() == "time") @@ -382,8 +400,7 @@ argument_done: PIT::sleep(5000); if (auto res = shell->process_command(args); res.is_error()) - dprintln("{}", res.error()); - //BAN::Formatter::println([&](char c) { shell->m_tty->putchar(c); }, "{}", res.error()); + TTY_PRINT("{}", res.error()); }; SpinLock spinlock; @@ -395,19 +412,28 @@ argument_done: else if (arguments.front() == "memory") { if (arguments.size() != 1) - return BAN::Error::from_c_string("'memory' does not support command line arguments"); + { + TTY_PRINTLN("'memory' does not support command line arguments"); + return {}; + } kmalloc_dump_info(); } else if (arguments.front() == "sleep") { if (arguments.size() != 1) - return BAN::Error::from_c_string("'sleep' does not support command line arguments"); + { + TTY_PRINTLN("'sleep' does not support command line arguments"); + return {}; + } PIT::sleep(5000); } else if (arguments.front() == "cpuinfo") { if (arguments.size() != 1) - return BAN::Error::from_c_string("'cpuinfo' does not support command line arguments"); + { + TTY_PRINTLN("'cpuinfo' does not support command line arguments"); + return {}; + } uint32_t ecx, edx; auto vendor = CPUID::get_vendor(); @@ -428,11 +454,17 @@ argument_done: else if (arguments.front() == "random") { if (arguments.size() != 1) - return BAN::Error::from_c_string("'random' does not support command line arguments"); + { + TTY_PRINTLN("'random' does not support command line arguments"); + return {}; + } uint32_t ecx, edx; CPUID::get_features(ecx, edx); if (!(ecx & CPUID::Features::ECX_RDRND)) - return BAN::Error::from_c_string("cpu does not support RDRAND instruction"); + { + TTY_PRINTLN("cpu does not support RDRAND instruction"); + return {}; + } for (int i = 0; i < 10; i++) { @@ -444,7 +476,10 @@ argument_done: else if (arguments.front() == "reboot") { if (arguments.size() != 1) - return BAN::Error::from_c_string("'reboot' does not support command line arguments"); + { + TTY_PRINTLN("'reboot' does not support command line arguments"); + return {}; + } uint8_t good = 0x02; while (good & 0x02) good = IO::inb(0x64); @@ -454,14 +489,20 @@ argument_done: else if (arguments.front() == "lspci") { if (arguments.size() != 1) - return BAN::Error::from_c_string("'lspci' does not support command line arguments"); + { + TTY_PRINTLN("'lspci' does not support command line arguments"); + return {}; + } for (auto& device : PCI::get().devices()) TTY_PRINTLN("{2H}:{2H}.{2H} {2H}", device.bus(), device.dev(), device.func(), device.class_code()); } else if (arguments.front() == "ls") { if (arguments.size() > 2) - return BAN::Error::from_c_string("usage: 'ls [path]'"); + { + TTY_PRINTLN("usage: 'ls [path]'"); + return {}; + } BAN::String path; if (arguments.size() == 2) @@ -508,7 +549,10 @@ argument_done: else if (arguments.front() == "cat") { if (arguments.size() != 2) - return BAN::Error::from_c_string("usage: 'cat path'"); + { + TTY_PRINTLN("usage: 'cat path'"); + return {}; + } int fd = TRY(Process::current()->open(arguments[1], O_RDONLY)); BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); }); @@ -521,7 +565,10 @@ argument_done: else if (arguments.front() == "stat") { if (arguments.size() != 2) - return BAN::Error::from_c_string("usage: 'stat path'"); + { + TTY_PRINTLN("usage: 'stat path'"); + return {}; + } stat st; TRY(Process::current()->stat(arguments[1], &st)); @@ -549,7 +596,10 @@ argument_done: else if (arguments.front() == "cd") { if (arguments.size() > 2) - return BAN::Error::from_c_string("usage 'cd path'"); + { + TTY_PRINTLN("usage 'cd path'"); + return {}; + } BAN::StringView path = arguments.size() == 2 ? arguments[1].sv() : "/"sv; TRY(Process::current()->set_working_directory(path)); TRY(update_prompt()); @@ -557,13 +607,19 @@ argument_done: else if (arguments.front() == "touch") { if (arguments.size() != 2) - return BAN::Error::from_c_string("usage 'touch path'"); + { + TTY_PRINTLN("usage 'touch path'"); + return {}; + } TRY(Process::current()->creat(arguments[1], 0)); } else if (arguments.front() == "cksum") { if (arguments.size() < 2) - return BAN::Error::from_c_string("usage 'cksum paths...'"); + { + TTY_PRINTLN("usage 'cksum paths...'"); + return {}; + } uint8_t buffer[1024]; for (size_t i = 1; i < arguments.size(); i++) @@ -594,20 +650,27 @@ argument_done: else if (arguments.front() == "mount") { if (arguments.size() != 3) - return BAN::Error::from_c_string("usage: 'mount partition directory'"); + { + TTY_PRINTLN("usage: 'mount partition directory'"); + return {}; + } TRY(Process::current()->mount(arguments[1], arguments[2])); } else if (arguments.front() == "loadfont") { if (arguments.size() != 2) - return BAN::Error::from_c_string("usage: 'loadfont font_path'"); + { + TTY_PRINTLN("usage: 'loadfont font_path'"); + return {}; + } auto font = TRY(Font::load(arguments[1])); //m_tty->set_font(font); } else { - return BAN::Error::from_format("unrecognized command '{}'", arguments.front()); + TTY_PRINTLN("unrecognized command '{}'", arguments.front()); + return {}; } return {}; diff --git a/kernel/kernel/Storage/ATABus.cpp b/kernel/kernel/Storage/ATABus.cpp index 7557be31..e2c58c92 100644 --- a/kernel/kernel/Storage/ATABus.cpp +++ b/kernel/kernel/Storage/ATABus.cpp @@ -224,22 +224,23 @@ namespace Kernel { uint8_t err = io_read(ATA_PORT_ERROR); if (err & ATA_ERROR_AMNF) - return BAN::Error::from_c_string("Address mark not found."); + return BAN::Error::from_error_code(ErrorCode::ATA_AMNF); if (err & ATA_ERROR_TKZNF) - return BAN::Error::from_c_string("Track zero not found."); + return BAN::Error::from_error_code(ErrorCode::ATA_TKZNF); if (err & ATA_ERROR_ABRT) - return BAN::Error::from_c_string("Aborted command."); + return BAN::Error::from_error_code(ErrorCode::ATA_ABRT); if (err & ATA_ERROR_MCR) - return BAN::Error::from_c_string("Media change request."); + return BAN::Error::from_error_code(ErrorCode::ATA_MCR); if (err & ATA_ERROR_IDNF) - return BAN::Error::from_c_string("ID not found."); + return BAN::Error::from_error_code(ErrorCode::ATA_IDNF); if (err & ATA_ERROR_MC) - return BAN::Error::from_c_string("Media changed."); + return BAN::Error::from_error_code(ErrorCode::ATA_MC); if (err & ATA_ERROR_UNC) - return BAN::Error::from_c_string("Uncorrectable data error."); + return BAN::Error::from_error_code(ErrorCode::ATA_UNC); if (err & ATA_ERROR_BBK) - return BAN::Error::from_c_string("Bad Block detected."); - return BAN::Error::from_c_string("No error"); + return BAN::Error::from_error_code(ErrorCode::ATA_BBK); + + return BAN::Error::from_error_code(ErrorCode::None); } uint8_t ATABus::device_index(const ATADevice* device) const @@ -251,7 +252,7 @@ namespace Kernel BAN::ErrorOr ATABus::read(ATADevice* device, uint64_t lba, uint8_t sector_count, uint8_t* buffer) { if (lba + sector_count > device->m_lba_count) - return BAN::Error::from_c_string("Attempted to read outside of the device boundaries"); + return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries); LockGuard _(m_lock); @@ -285,7 +286,7 @@ namespace Kernel BAN::ErrorOr ATABus::write(ATADevice* device, uint64_t lba, uint8_t sector_count, const uint8_t* buffer) { if (lba + sector_count > device->m_lba_count) - return BAN::Error::from_c_string("Attempted to write outside of the device boundaries"); + return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries); LockGuard _(m_lock); diff --git a/kernel/kernel/Storage/ATADevice.cpp b/kernel/kernel/Storage/ATADevice.cpp index b4cde8f0..8e09cb56 100644 --- a/kernel/kernel/Storage/ATADevice.cpp +++ b/kernel/kernel/Storage/ATADevice.cpp @@ -18,7 +18,7 @@ namespace Kernel m_command_set |= (uint32_t)(identify_buffer[ATA_IDENTIFY_COMMAND_SET + 1] << 16); if (!(m_capabilities & ATA_CAPABILITIES_LBA)) - return BAN::Error::from_c_string("Device does not support LBA addressing"); + return BAN::Error::from_error_code(ErrorCode::ATA_NoLBA); if ((identify_buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 15)) == 0 && (identify_buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 14)) != 0 && diff --git a/kernel/kernel/Storage/StorageDevice.cpp b/kernel/kernel/Storage/StorageDevice.cpp index 500845e7..eeb0e742 100644 --- a/kernel/kernel/Storage/StorageDevice.cpp +++ b/kernel/kernel/Storage/StorageDevice.cpp @@ -147,28 +147,28 @@ namespace Kernel BAN::ErrorOr StorageDevice::initialize_partitions() { if (total_size() < sizeof(GPTHeader)) - return BAN::Error::from_format("Disk {} does not have enough space for GPT header", name()); + return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader); BAN::Vector lba1(sector_size()); TRY(read_sectors(1, 1, lba1.data())); const GPTHeader& header = *(const GPTHeader*)lba1.data(); if (!is_valid_gpt_header(header, sector_size())) - return BAN::Error::from_format("Disk {} has invalid GPT header", name()); + return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader); uint32_t size = header.partition_entry_count * header.partition_entry_size; if (uint32_t remainder = size % sector_size()) size += sector_size() - remainder; if (total_size() < header.partition_entry_lba * sector_size() + size) - return BAN::Error::from_format("Disk {} has invalid GPT header", name()); + return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader); BAN::Vector entry_array; TRY(entry_array.resize(size)); TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.data())); if (!is_valid_gpt_crc32(header, lba1, entry_array)) - return BAN::Error::from_format("Disk {} has invalid crc3 in the GPT header", name()); + return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader); for (uint32_t i = 0; i < header.partition_entry_count; i++) { @@ -220,7 +220,7 @@ namespace Kernel { const uint32_t sectors_in_partition = m_lba_end - m_lba_start; if (lba + sector_count > sectors_in_partition) - return BAN::Error::from_c_string("Attempted to read outside of the partition boundaries"); + return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries); TRY(m_device.read_sectors(m_lba_start + lba, sector_count, buffer)); return {}; } @@ -229,7 +229,7 @@ namespace Kernel { const uint32_t sectors_in_partition = m_lba_end - m_lba_start; if (lba + sector_count > sectors_in_partition) - return BAN::Error::from_c_string("Attempted to write outside of the partition boundaries"); + return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries); TRY(m_device.write_sectors(m_lba_start + lba, sector_count, buffer)); return {}; } diff --git a/libc/include/errno.h b/libc/include/errno.h index 003084cb..c7a0b7f6 100644 --- a/libc/include/errno.h +++ b/libc/include/errno.h @@ -15,6 +15,7 @@ #define ENAMETOOLONG 11 #define ENOBUFS 12 #define ENOTTY 13 +#define ENOTBLK 14 __BEGIN_DECLS diff --git a/libc/string.cpp b/libc/string.cpp index 269124fe..8df312fe 100644 --- a/libc/string.cpp +++ b/libc/string.cpp @@ -122,6 +122,9 @@ char* strerror(int error) case ENOTTY: strcpy(buffer, "Inappropriate I/O control operation"); break; + case ENOTBLK: + strcpy(buffer, "Block device required"); + break; default: { // FIXME: sprintf