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.
This commit is contained in:
Bananymous 2023-04-11 23:25:21 +03:00
parent 2fabe1949c
commit 8d6db168d6
16 changed files with 258 additions and 123 deletions

View File

@ -8,6 +8,7 @@
#if defined(__is_kernel)
#include <kernel/Panic.h>
#include <kernel/Errors.h>
#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<typename... Args>
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>(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<typename T>
@ -82,7 +78,7 @@ namespace BAN
const T& value() const { return m_data.template get<T>(); }
T& value() { return m_data.template get<T>(); }
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<typename F>
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);
}
}

View File

@ -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

View File

@ -0,0 +1,39 @@
#pragma once
#include <BAN/StringView.h>
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);
}

View File

@ -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)

40
kernel/kernel/Errors.cpp Normal file
View File

@ -0,0 +1,40 @@
#include <kernel/Errors.h>
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];
}
}

View File

@ -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<uint8_t> buffer)

View File

@ -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;

View File

@ -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> Font::parse_psf1(BAN::Span<const uint8_t> 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<uint8_t> 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<uint8_t> glyph_data;
TRY(glyph_data.resize(glyph_data_size));

View File

@ -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<uint8_t> 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<void> 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 {};
}

View File

@ -64,8 +64,7 @@ namespace Kernel
BAN::ErrorOr<void> 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<void> 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 {};
}

View File

@ -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 {};

View File

@ -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<void> 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<void> 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);

View File

@ -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 &&

View File

@ -147,28 +147,28 @@ namespace Kernel
BAN::ErrorOr<void> 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<uint8_t> 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<uint8_t> 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 {};
}

View File

@ -15,6 +15,7 @@
#define ENAMETOOLONG 11
#define ENOBUFS 12
#define ENOTTY 13
#define ENOTBLK 14
__BEGIN_DECLS

View File

@ -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