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:
parent
cfa025acae
commit
aa2aee684b
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#if defined(__is_kernel)
|
#if defined(__is_kernel)
|
||||||
#include <kernel/Panic.h>
|
#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(); })
|
#define MUST(expr) ({ auto e = expr; if (e.is_error()) Kernel::panic("{}", e.error()); e.release_value(); })
|
||||||
#else
|
#else
|
||||||
#define MUST(expr) ({ auto e = expr; assert(!e.is_error()); e.release_value(); })
|
#define MUST(expr) ({ auto e = expr; assert(!e.is_error()); e.release_value(); })
|
||||||
|
@ -20,43 +21,38 @@ namespace BAN
|
||||||
|
|
||||||
class Error
|
class Error
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
static constexpr uint32_t kernel_error_mask = 0x80000000;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Error from_c_string(const char* message)
|
static Error from_error_code(Kernel::ErrorCode error)
|
||||||
{
|
{
|
||||||
Error result;
|
return Error((uint32_t)error | kernel_error_mask);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
static Error from_errno(int error)
|
static Error from_errno(int error)
|
||||||
{
|
{
|
||||||
Error result;
|
return Error(error);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t get_error_code() const { return m_error_code; }
|
Kernel::ErrorCode kernel_error() const
|
||||||
const char* get_message() const { return m_message; }
|
{
|
||||||
|
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:
|
private:
|
||||||
char m_message[128];
|
Error(uint32_t error)
|
||||||
uint8_t m_error_code;
|
: m_error_code(error)
|
||||||
|
{}
|
||||||
|
|
||||||
|
uint32_t m_error_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -102,12 +98,12 @@ namespace BAN
|
||||||
const Error& error() const { return m_data; }
|
const Error& error() const { return m_data; }
|
||||||
void value() { }
|
void value() { }
|
||||||
|
|
||||||
Error release_error() { return move(m_data); m_data = Error(); }
|
Error release_error() { return move(m_data); }
|
||||||
void release_value() { m_data = Error(); }
|
void release_value() { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Error m_data;
|
Error m_data { Error::from_error_code(Kernel::ErrorCode::None) };
|
||||||
bool m_has_error = false;
|
bool m_has_error { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -115,11 +111,8 @@ namespace BAN
|
||||||
namespace BAN::Formatter
|
namespace BAN::Formatter
|
||||||
{
|
{
|
||||||
template<typename F>
|
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_argument(putc, error.get_message(), format);
|
||||||
print(putc, error.get_message());
|
|
||||||
else
|
|
||||||
print(putc, "{} ({})", error.get_message(), error.get_error_code());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ set(KERNEL_SOURCES
|
||||||
kernel/Debug.cpp
|
kernel/Debug.cpp
|
||||||
kernel/Device.cpp
|
kernel/Device.cpp
|
||||||
kernel/DeviceManager.cpp
|
kernel/DeviceManager.cpp
|
||||||
|
kernel/Errors.cpp
|
||||||
kernel/Font.cpp
|
kernel/Font.cpp
|
||||||
kernel/FS/Ext2.cpp
|
kernel/FS/Ext2.cpp
|
||||||
kernel/FS/VirtualFileSystem.cpp
|
kernel/FS/VirtualFileSystem.cpp
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -100,7 +100,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
const RSDP* rsdp = locate_rsdp();
|
const RSDP* rsdp = locate_rsdp();
|
||||||
if (rsdp == nullptr)
|
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)
|
if (rsdp->revision >= 2)
|
||||||
{
|
{
|
||||||
|
@ -109,9 +109,9 @@ namespace Kernel
|
||||||
BAN::ScopeGuard _([xsdt] { MMU::get().unallocate_page((uintptr_t)xsdt); });
|
BAN::ScopeGuard _([xsdt] { MMU::get().unallocate_page((uintptr_t)xsdt); });
|
||||||
|
|
||||||
if (memcmp(xsdt->signature, "XSDT", 4) != 0)
|
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))
|
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_header_table = (uintptr_t)xsdt->entries;
|
||||||
m_entry_size = 8;
|
m_entry_size = 8;
|
||||||
|
@ -124,9 +124,9 @@ namespace Kernel
|
||||||
BAN::ScopeGuard _([rsdt] { MMU::get().unallocate_page((uintptr_t)rsdt); });
|
BAN::ScopeGuard _([rsdt] { MMU::get().unallocate_page((uintptr_t)rsdt); });
|
||||||
|
|
||||||
if (memcmp(rsdt->signature, "RSDT", 4) != 0)
|
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))
|
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_header_table = (uintptr_t)rsdt->entries;
|
||||||
m_entry_size = 4;
|
m_entry_size = 4;
|
||||||
|
@ -148,7 +148,7 @@ namespace Kernel
|
||||||
return header;
|
return header;
|
||||||
unmap_header(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)
|
void ACPI::unmap_header(const ACPI::SDTHeader* header)
|
||||||
|
|
|
@ -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];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -463,7 +463,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_superblock.magic != 0xEF53)
|
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)
|
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 = 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);
|
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)
|
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_COMPRESSION));
|
||||||
//ASSERT(!(m_superblock.feature_incompat & Ext2::Enum::FEATURE_INCOMPAT_FILETYPE));
|
//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)
|
void Ext2FS::read_block(uint32_t block, BAN::Span<uint8_t> buffer)
|
||||||
|
|
|
@ -18,8 +18,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
BAN::ScopeGuard guard([] { delete s_instance; s_instance = nullptr; } );
|
BAN::ScopeGuard guard([] { delete s_instance; s_instance = nullptr; } );
|
||||||
|
|
||||||
if (root.size() < 5 || root.substring(0, 5) != "/dev/")
|
ASSERT(root.size() >= 5 && root.substring(0, 5) == "/dev/"sv);;
|
||||||
return BAN::Error::from_c_string("root must be in /dev/");
|
|
||||||
root = root.substring(5);
|
root = root.substring(5);
|
||||||
|
|
||||||
auto partition_inode = TRY(DeviceManager::get().read_directory_inode(root));
|
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));
|
auto partition_file = TRY(file_from_absolute_path(partition));
|
||||||
if (partition_file.inode->inode_type() != Inode::InodeType::Device)
|
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();
|
Device* device = (Device*)partition_file.inode.ptr();
|
||||||
if (device->device_type() != Device::DeviceType::Partition)
|
if (device->device_type() != Device::DeviceType::BlockDevice)
|
||||||
return BAN::Error::from_c_string("Not a partition");
|
return BAN::Error::from_errno(ENOTBLK);
|
||||||
|
|
||||||
auto* file_system = TRY(Ext2FS::create(*(Partition*)device));
|
auto* file_system = TRY(Ext2FS::create(*(Partition*)device));
|
||||||
return mount(file_system, target);
|
return mount(file_system, target);
|
||||||
|
@ -90,8 +89,7 @@ namespace Kernel
|
||||||
ASSERT(path.front() == '/');
|
ASSERT(path.front() == '/');
|
||||||
|
|
||||||
auto inode = root_inode();
|
auto inode = root_inode();
|
||||||
if (!inode)
|
ASSERT(inode);
|
||||||
return BAN::Error::from_c_string("No root inode available");
|
|
||||||
|
|
||||||
BAN::String canonical_path;
|
BAN::String canonical_path;
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace Kernel
|
||||||
TRY(Process::current()->read(fd, file_data.data(), st.st_size));
|
TRY(Process::current()->read(fd, file_data.data(), st.st_size));
|
||||||
|
|
||||||
if (file_data.size() < 4)
|
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)
|
if (file_data[0] == PSF1_MAGIC0 && file_data[1] == PSF1_MAGIC1)
|
||||||
return TRY(parse_psf1(file_data.span()));
|
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)
|
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 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)
|
BAN::ErrorOr<Font> Font::parse_psf1(BAN::Span<const uint8_t> font_data)
|
||||||
{
|
{
|
||||||
if (font_data.size() < 4)
|
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
|
struct PSF1Header
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,7 @@ namespace Kernel
|
||||||
uint32_t glyph_data_size = glyph_size * glyph_count;
|
uint32_t glyph_data_size = glyph_size * glyph_count;
|
||||||
|
|
||||||
if (font_data.size() < sizeof(PSF1Header) + glyph_data_size)
|
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;
|
BAN::Vector<uint8_t> glyph_data;
|
||||||
TRY(glyph_data.resize(glyph_data_size));
|
TRY(glyph_data.resize(glyph_data_size));
|
||||||
|
@ -155,14 +155,14 @@ namespace Kernel
|
||||||
};
|
};
|
||||||
|
|
||||||
if (font_data.size() < sizeof(PSF2Header))
|
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();
|
const PSF2Header& header = *(const PSF2Header*)font_data.data();
|
||||||
|
|
||||||
uint32_t glyph_data_size = header.glyph_count * header.glyph_size;
|
uint32_t glyph_data_size = header.glyph_count * header.glyph_size;
|
||||||
|
|
||||||
if (font_data.size() < glyph_data_size + header.header_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;
|
BAN::Vector<uint8_t> glyph_data;
|
||||||
TRY(glyph_data.resize(glyph_data_size));
|
TRY(glyph_data.resize(glyph_data_size));
|
||||||
|
|
|
@ -116,7 +116,7 @@ namespace Kernel::Input
|
||||||
return {};
|
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()
|
static BAN::ErrorOr<uint8_t> device_read_byte()
|
||||||
|
@ -125,7 +125,7 @@ namespace Kernel::Input
|
||||||
while (PIT::ms_since_boot() < timeout)
|
while (PIT::ms_since_boot() < timeout)
|
||||||
if (IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_FULL)
|
if (IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_FULL)
|
||||||
return IO::inb(PS2::IOPort::DATA);
|
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()
|
static BAN::ErrorOr<void> device_wait_ack()
|
||||||
|
@ -175,15 +175,7 @@ namespace Kernel::Input
|
||||||
// FIXME
|
// FIXME
|
||||||
|
|
||||||
// Step 2: Determine if the PS/2 Controller Exists
|
// Step 2: Determine if the PS/2 Controller Exists
|
||||||
if (false)
|
// FIXME
|
||||||
{
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3: Disable Devices
|
// Step 3: Disable Devices
|
||||||
controller_send_command(PS2::Command::DISABLE_FIRST_PORT);
|
controller_send_command(PS2::Command::DISABLE_FIRST_PORT);
|
||||||
|
@ -203,7 +195,7 @@ namespace Kernel::Input
|
||||||
// Step 6: Perform Controller Self Test
|
// Step 6: Perform Controller Self Test
|
||||||
controller_send_command(PS2::Command::TEST_CONTROLLER);
|
controller_send_command(PS2::Command::TEST_CONTROLLER);
|
||||||
if (wait_and_read() != PS2::Response::TEST_CONTROLLER_PASS)
|
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
|
// NOTE: self test might reset the device so we set the config byte again
|
||||||
controller_send_command(PS2::Command::WRITE_CONFIG, config);
|
controller_send_command(PS2::Command::WRITE_CONFIG, config);
|
||||||
|
|
||||||
|
@ -229,7 +221,7 @@ namespace Kernel::Input
|
||||||
valid_ports[1] = false;
|
valid_ports[1] = false;
|
||||||
}
|
}
|
||||||
if (!valid_ports[0] && !valid_ports[1])
|
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)
|
// Step 9: Enable Devices (and disable scanning)
|
||||||
for (uint8_t device = 0; device < 2; device++)
|
for (uint8_t device = 0; device < 2; device++)
|
||||||
|
@ -298,7 +290,7 @@ namespace Kernel::Input
|
||||||
|
|
||||||
// Standard PS/2 Mouse
|
// Standard PS/2 Mouse
|
||||||
if (index == 1 && (bytes[0] == 0x00))
|
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
|
// MF2 Keyboard
|
||||||
if (index == 2 && (bytes[0] == 0xAB && bytes[1] == 0x83))
|
if (index == 2 && (bytes[0] == 0xAB && bytes[1] == 0x83))
|
||||||
|
@ -306,7 +298,8 @@ namespace Kernel::Input
|
||||||
|
|
||||||
if (m_devices[device])
|
if (m_devices[device])
|
||||||
return {};
|
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)
|
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_send_byte(device, PS2::DeviceCommand::RESET));
|
||||||
TRY(device_wait_ack());
|
TRY(device_wait_ack());
|
||||||
if (TRY(device_read_byte()) != PS2::Response::SELF_TEST_PASS)
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> Process::init_stdio()
|
BAN::ErrorOr<void> Process::init_stdio()
|
||||||
{
|
{
|
||||||
if (!m_open_files.empty())
|
ASSERT(m_open_files.empty());
|
||||||
return BAN::Error::from_c_string("Could not init stdio, process already has open files");
|
|
||||||
TRY(open("/dev/tty1", O_RDONLY)); // stdin
|
TRY(open("/dev/tty1", O_RDONLY)); // stdin
|
||||||
TRY(open("/dev/tty1", O_WRONLY)); // stdout
|
TRY(open("/dev/tty1", O_WRONLY)); // stdout
|
||||||
TRY(open("/dev/tty1", O_WRONLY)); // stderr
|
TRY(open("/dev/tty1", O_WRONLY)); // stderr
|
||||||
|
@ -152,13 +151,17 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> Process::creat(BAN::StringView path, mode_t mode)
|
BAN::ErrorOr<void> Process::creat(BAN::StringView path, mode_t mode)
|
||||||
{
|
{
|
||||||
auto absolute_path = TRY(absolute_path_of(path));
|
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));
|
size_t index;
|
||||||
if (path.count('/') > 0)
|
for (index = absolute_path.size(); index > 0; index--)
|
||||||
return BAN::Error::from_c_string("You can only create files to current working directory");
|
if (absolute_path[index - 1] == '/')
|
||||||
TRY(parent_file.inode->create_file(path, mode));
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -327,11 +327,26 @@ argument_done:
|
||||||
if (arguments.empty())
|
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")
|
else if (arguments.front() == "date")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1)
|
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();
|
auto time = RTC::get_current_time();
|
||||||
TTY_PRINTLN("{}", time);
|
TTY_PRINTLN("{}", time);
|
||||||
}
|
}
|
||||||
|
@ -348,7 +363,10 @@ argument_done:
|
||||||
else if (arguments.front() == "clear")
|
else if (arguments.front() == "clear")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1)
|
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");
|
TTY_PRINT("\e[2J\e[H");
|
||||||
}
|
}
|
||||||
else if (arguments.front() == "time")
|
else if (arguments.front() == "time")
|
||||||
|
@ -382,8 +400,7 @@ argument_done:
|
||||||
PIT::sleep(5000);
|
PIT::sleep(5000);
|
||||||
|
|
||||||
if (auto res = shell->process_command(args); res.is_error())
|
if (auto res = shell->process_command(args); res.is_error())
|
||||||
dprintln("{}", res.error());
|
TTY_PRINT("{}", res.error());
|
||||||
//BAN::Formatter::println([&](char c) { shell->m_tty->putchar(c); }, "{}", res.error());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SpinLock spinlock;
|
SpinLock spinlock;
|
||||||
|
@ -395,19 +412,28 @@ argument_done:
|
||||||
else if (arguments.front() == "memory")
|
else if (arguments.front() == "memory")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1)
|
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();
|
kmalloc_dump_info();
|
||||||
}
|
}
|
||||||
else if (arguments.front() == "sleep")
|
else if (arguments.front() == "sleep")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1)
|
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);
|
PIT::sleep(5000);
|
||||||
}
|
}
|
||||||
else if (arguments.front() == "cpuinfo")
|
else if (arguments.front() == "cpuinfo")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1)
|
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;
|
uint32_t ecx, edx;
|
||||||
auto vendor = CPUID::get_vendor();
|
auto vendor = CPUID::get_vendor();
|
||||||
|
@ -428,11 +454,17 @@ argument_done:
|
||||||
else if (arguments.front() == "random")
|
else if (arguments.front() == "random")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1)
|
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;
|
uint32_t ecx, edx;
|
||||||
CPUID::get_features(ecx, edx);
|
CPUID::get_features(ecx, edx);
|
||||||
if (!(ecx & CPUID::Features::ECX_RDRND))
|
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++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
|
@ -444,7 +476,10 @@ argument_done:
|
||||||
else if (arguments.front() == "reboot")
|
else if (arguments.front() == "reboot")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1)
|
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;
|
uint8_t good = 0x02;
|
||||||
while (good & 0x02)
|
while (good & 0x02)
|
||||||
good = IO::inb(0x64);
|
good = IO::inb(0x64);
|
||||||
|
@ -454,14 +489,20 @@ argument_done:
|
||||||
else if (arguments.front() == "lspci")
|
else if (arguments.front() == "lspci")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1)
|
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())
|
for (auto& device : PCI::get().devices())
|
||||||
TTY_PRINTLN("{2H}:{2H}.{2H} {2H}", device.bus(), device.dev(), device.func(), device.class_code());
|
TTY_PRINTLN("{2H}:{2H}.{2H} {2H}", device.bus(), device.dev(), device.func(), device.class_code());
|
||||||
}
|
}
|
||||||
else if (arguments.front() == "ls")
|
else if (arguments.front() == "ls")
|
||||||
{
|
{
|
||||||
if (arguments.size() > 2)
|
if (arguments.size() > 2)
|
||||||
return BAN::Error::from_c_string("usage: 'ls [path]'");
|
{
|
||||||
|
TTY_PRINTLN("usage: 'ls [path]'");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
BAN::String path;
|
BAN::String path;
|
||||||
if (arguments.size() == 2)
|
if (arguments.size() == 2)
|
||||||
|
@ -508,7 +549,10 @@ argument_done:
|
||||||
else if (arguments.front() == "cat")
|
else if (arguments.front() == "cat")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 2)
|
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));
|
int fd = TRY(Process::current()->open(arguments[1], O_RDONLY));
|
||||||
BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); });
|
BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); });
|
||||||
|
@ -521,7 +565,10 @@ argument_done:
|
||||||
else if (arguments.front() == "stat")
|
else if (arguments.front() == "stat")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 2)
|
if (arguments.size() != 2)
|
||||||
return BAN::Error::from_c_string("usage: 'stat path'");
|
{
|
||||||
|
TTY_PRINTLN("usage: 'stat path'");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
stat st;
|
stat st;
|
||||||
TRY(Process::current()->stat(arguments[1], &st));
|
TRY(Process::current()->stat(arguments[1], &st));
|
||||||
|
@ -549,7 +596,10 @@ argument_done:
|
||||||
else if (arguments.front() == "cd")
|
else if (arguments.front() == "cd")
|
||||||
{
|
{
|
||||||
if (arguments.size() > 2)
|
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;
|
BAN::StringView path = arguments.size() == 2 ? arguments[1].sv() : "/"sv;
|
||||||
TRY(Process::current()->set_working_directory(path));
|
TRY(Process::current()->set_working_directory(path));
|
||||||
TRY(update_prompt());
|
TRY(update_prompt());
|
||||||
|
@ -557,13 +607,19 @@ argument_done:
|
||||||
else if (arguments.front() == "touch")
|
else if (arguments.front() == "touch")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 2)
|
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));
|
TRY(Process::current()->creat(arguments[1], 0));
|
||||||
}
|
}
|
||||||
else if (arguments.front() == "cksum")
|
else if (arguments.front() == "cksum")
|
||||||
{
|
{
|
||||||
if (arguments.size() < 2)
|
if (arguments.size() < 2)
|
||||||
return BAN::Error::from_c_string("usage 'cksum paths...'");
|
{
|
||||||
|
TTY_PRINTLN("usage 'cksum paths...'");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
for (size_t i = 1; i < arguments.size(); i++)
|
for (size_t i = 1; i < arguments.size(); i++)
|
||||||
|
@ -594,20 +650,27 @@ argument_done:
|
||||||
else if (arguments.front() == "mount")
|
else if (arguments.front() == "mount")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 3)
|
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]));
|
TRY(Process::current()->mount(arguments[1], arguments[2]));
|
||||||
}
|
}
|
||||||
else if (arguments.front() == "loadfont")
|
else if (arguments.front() == "loadfont")
|
||||||
{
|
{
|
||||||
if (arguments.size() != 2)
|
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]));
|
auto font = TRY(Font::load(arguments[1]));
|
||||||
//m_tty->set_font(font);
|
//m_tty->set_font(font);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return BAN::Error::from_format("unrecognized command '{}'", arguments.front());
|
TTY_PRINTLN("unrecognized command '{}'", arguments.front());
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -224,22 +224,23 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
uint8_t err = io_read(ATA_PORT_ERROR);
|
uint8_t err = io_read(ATA_PORT_ERROR);
|
||||||
if (err & ATA_ERROR_AMNF)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
if (err & ATA_ERROR_BBK)
|
||||||
return BAN::Error::from_c_string("Bad Block detected.");
|
return BAN::Error::from_error_code(ErrorCode::ATA_BBK);
|
||||||
return BAN::Error::from_c_string("No error");
|
|
||||||
|
return BAN::Error::from_error_code(ErrorCode::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ATABus::device_index(const ATADevice* device) const
|
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)
|
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)
|
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);
|
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)
|
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)
|
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);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Kernel
|
||||||
m_command_set |= (uint32_t)(identify_buffer[ATA_IDENTIFY_COMMAND_SET + 1] << 16);
|
m_command_set |= (uint32_t)(identify_buffer[ATA_IDENTIFY_COMMAND_SET + 1] << 16);
|
||||||
|
|
||||||
if (!(m_capabilities & ATA_CAPABILITIES_LBA))
|
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 &&
|
if ((identify_buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 15)) == 0 &&
|
||||||
(identify_buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 14)) != 0 &&
|
(identify_buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 14)) != 0 &&
|
||||||
|
|
|
@ -147,28 +147,28 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> StorageDevice::initialize_partitions()
|
BAN::ErrorOr<void> StorageDevice::initialize_partitions()
|
||||||
{
|
{
|
||||||
if (total_size() < sizeof(GPTHeader))
|
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());
|
BAN::Vector<uint8_t> lba1(sector_size());
|
||||||
TRY(read_sectors(1, 1, lba1.data()));
|
TRY(read_sectors(1, 1, lba1.data()));
|
||||||
|
|
||||||
const GPTHeader& header = *(const GPTHeader*)lba1.data();
|
const GPTHeader& header = *(const GPTHeader*)lba1.data();
|
||||||
if (!is_valid_gpt_header(header, sector_size()))
|
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;
|
uint32_t size = header.partition_entry_count * header.partition_entry_size;
|
||||||
if (uint32_t remainder = size % sector_size())
|
if (uint32_t remainder = size % sector_size())
|
||||||
size += sector_size() - remainder;
|
size += sector_size() - remainder;
|
||||||
|
|
||||||
if (total_size() < header.partition_entry_lba * sector_size() + size)
|
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;
|
BAN::Vector<uint8_t> entry_array;
|
||||||
TRY(entry_array.resize(size));
|
TRY(entry_array.resize(size));
|
||||||
TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.data()));
|
TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.data()));
|
||||||
|
|
||||||
if (!is_valid_gpt_crc32(header, lba1, entry_array))
|
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++)
|
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;
|
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||||
if (lba + sector_count > sectors_in_partition)
|
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));
|
TRY(m_device.read_sectors(m_lba_start + lba, sector_count, buffer));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -229,7 +229,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||||
if (lba + sector_count > sectors_in_partition)
|
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));
|
TRY(m_device.write_sectors(m_lba_start + lba, sector_count, buffer));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#define ENAMETOOLONG 11
|
#define ENAMETOOLONG 11
|
||||||
#define ENOBUFS 12
|
#define ENOBUFS 12
|
||||||
#define ENOTTY 13
|
#define ENOTTY 13
|
||||||
|
#define ENOTBLK 14
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,9 @@ char* strerror(int error)
|
||||||
case ENOTTY:
|
case ENOTTY:
|
||||||
strcpy(buffer, "Inappropriate I/O control operation");
|
strcpy(buffer, "Inappropriate I/O control operation");
|
||||||
break;
|
break;
|
||||||
|
case ENOTBLK:
|
||||||
|
strcpy(buffer, "Block device required");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// FIXME: sprintf
|
// FIXME: sprintf
|
||||||
|
|
Loading…
Reference in New Issue